From dd3a60c79d0b0085d5710655046a637bc6d69bee Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 8 Mar 2023 13:23:24 +0100 Subject: [PATCH] zombierecovery: use Amboss API for channel query --- cmd/chantools/zombierecovery_findmatches.go | 331 ++++++++++++++------ go.mod | 16 +- go.sum | 54 +++- 3 files changed, 291 insertions(+), 110 deletions(-) diff --git a/cmd/chantools/zombierecovery_findmatches.go b/cmd/chantools/zombierecovery_findmatches.go index 77ccda7..074306e 100644 --- a/cmd/chantools/zombierecovery_findmatches.go +++ b/cmd/chantools/zombierecovery_findmatches.go @@ -1,27 +1,91 @@ package main import ( - "bytes" + "context" "encoding/json" "fmt" - "io/ioutil" + "os" "regexp" + "strconv" + "text/template" "time" "github.com/btcsuite/btcd/btcec/v2" - "github.com/gogo/protobuf/jsonpb" "github.com/guggero/chantools/btc" - "github.com/guggero/chantools/lnd" - "github.com/lightningnetwork/lnd/lnrpc" + "github.com/hasura/go-graphql-client" "github.com/spf13/cobra" + "golang.org/x/oauth2" ) var ( patternRegistration = regexp.MustCompile( - "(?m)(?s)ID: ([0-9a-f]{66})\nContact: (.*?)\n" + - "Time: ") + "(?m)(?s)ID: ([0-9a-f]{66})\nContact: (.*?)\nTime: ", + ) + + ambossQueryDelay = 7 * time.Second + + initialTemplate = `SEND TO: {{.Contact}} + +Hi + +This is Oliver from node-recovery.com. +You recently registered your node ({{.Node1}}) with my website. + +I have some good news! I found +{{- if eq .NumChannels 1}} a match for a channel{{end}} +{{- if gt .NumChannels 1}} matches for {{.NumChannels}} channels{{end}}. +Attached you find the JSON files that contain all the info I have about your +node and the remote node (open with a text editor). + +With those files you can close the channels and get your funds back. But you +need the cooperation of the remote peer. But because they also registered to the +same website, they should be aware of that and be willing to cooperate. + +Please contact the remote peer with the contact information listed below (this +is what they registered with, I don't have additional contact information): + +{{range $i, $peer := .Peers}} +Peer: {{$peer.PubKey}} +Contact: {{$peer.Contact}} + +{{end}} +The document that describes what to do exactly is located here: +https://github.com/guggero/chantools/blob/master/doc/zombierecovery.md + +Good luck! + +Oliver (guggero) + + +P.S.: If you don't want to be notified about future matches, please let me know. +` ) +type gqChannel struct { + ChanPoint string `graphql:"chan_point"` + Capacity string `graphql:"capacity"` + ClosureInfo struct { + ClosedHeight uint32 `graphql:"closed_height"` + } `graphql:"closure_info"` + Node1 string `graphql:"node1_pub"` + Node2 string `graphql:"node2_pub"` + ChannelID string `graphql:"long_channel_id"` +} + +type gqGraphInfo struct { + Channels struct { + ChannelList struct { + List []*gqChannel `graphql:"list"` + } `graphql:"channel_list(page:{limit:$limit,offset:$offset})"` + } `graphql:"channels"` +} + +type gqGetNodeQuery struct { + GetNode struct { + GraphInfo *gqGraphInfo `graphql:"graph_info"` + } `graphql:"getNode(pubkey: $pubkey)"` +} + type nodeInfo struct { PubKey string `json:"identity_pubkey"` Contact string `json:"contact"` @@ -48,22 +112,10 @@ type match struct { Channels []*channel `json:"channels"` } -type donePair struct { - Node1 *nodeInfo `json:"node1"` - Node2 *nodeInfo `json:"node2"` - Msg string `json:"msg"` -} - -func (p *donePair) matches(node1, node2 string) bool { - return (p.Node1.PubKey == node1 && p.Node2.PubKey == node2) || - (p.Node1.PubKey == node2 && p.Node2.PubKey == node1) -} - type zombieRecoveryFindMatchesCommand struct { APIURL string Registrations string - ChannelGraph string - PairsDone string + AmbossKey string cmd *cobra.Command } @@ -96,14 +148,8 @@ registered nodes.`, "where the registrations are stored in", ) cc.cmd.Flags().StringVar( - &cc.ChannelGraph, "channel_graph", "", "the full LN channel "+ - "graph in the JSON format that the "+ - "'lncli describegraph' returns", - ) - cc.cmd.Flags().StringVar( - &cc.PairsDone, "pairs_done", "", "an optional file containing "+ - "all pairs that have already been contacted and "+ - "shouldn't be matched again", + &cc.AmbossKey, "ambosskey", "", "the API key for the Amboss "+ + "GraphQL API", ) return cc.cmd @@ -112,9 +158,7 @@ registered nodes.`, func (c *zombieRecoveryFindMatchesCommand) Execute(_ *cobra.Command, _ []string) error { - api := &btc.ExplorerAPI{BaseURL: c.APIURL} - - logFileBytes, err := ioutil.ReadFile(c.Registrations) + logFileBytes, err := os.ReadFile(c.Registrations) if err != nil { return fmt.Errorf("error reading registrations file %s: %w", c.Registrations, err) @@ -129,116 +173,201 @@ func (c *zombieRecoveryFindMatchesCommand) Execute(_ *cobra.Command, return fmt.Errorf("error parsing node ID: %w", err) } - registrations[groups[1]] = groups[2] + if registrations[groups[1]] != "" { + registrations[groups[1]] += ", " + } - log.Infof("%s: %s", groups[1], groups[2]) - } + registrations[groups[1]] += groups[2] - graphBytes, err := ioutil.ReadFile(c.ChannelGraph) - if err != nil { - return fmt.Errorf("error reading graph JSON file %s: "+ - "%v", c.ChannelGraph, err) - } - graph := &lnrpc.ChannelGraph{} - err = jsonpb.UnmarshalString(string(graphBytes), graph) - if err != nil { - return fmt.Errorf("error parsing graph JSON: %w", err) + log.Infof("%s: %s", groups[1], groups[2]) } - var donePairs []*donePair - if c.PairsDone != "" { - donePairsBytes, err := readInput(c.PairsDone) - if err != nil { - return fmt.Errorf("error reading pairs JSON %s: %w", - c.PairsDone, err) - } - decoder := json.NewDecoder(bytes.NewReader(donePairsBytes)) - err = decoder.Decode(&donePairs) - if err != nil { - return fmt.Errorf("error parsing pairs JSON %s: %w", - c.PairsDone, err) - } - } + api := &btc.ExplorerAPI{BaseURL: c.APIURL} + src := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: c.AmbossKey}) + httpClient := oauth2.NewClient(context.Background(), src) + client := graphql.NewClient( + "https://api.amboss.space/graphql", httpClient, + ) // Loop through all nodes now. matches := make(map[string]map[string]*match) + idx := 0 for node1, contact1 := range registrations { matches[node1] = make(map[string]*match) - for node2, contact2 := range registrations { - if node1 == node2 { - continue - } - // We've already looked at this pair. - if matches[node2][node1] != nil { - continue - } + time.Sleep(ambossQueryDelay) + log.Debugf("Fetching channels for node %d of %d", idx, + len(registrations)) + idx++ + + channels, err := fetchChannels(client, node1) + if err != nil { + return fmt.Errorf("error fetching channels for %s: %w", + node1, err) + } + for _, node1Chan := range channels { + peer := identifyPeer(node1Chan, node1) - edges := lnd.FindCommonEdges(graph, node1, node2) - if len(edges) > 0 { - matches[node1][node2] = &match{ - Node1: &nodeInfo{ - PubKey: node1, - Contact: contact1, - }, - Node2: &nodeInfo{ - PubKey: node2, - Contact: contact2, - }, - Channels: make([]*channel, len(edges)), + for node2, contact2 := range registrations { + if node1 == node2 || node2 != peer { + continue } - for idx, edge := range edges { - cid := fmt.Sprintf("%d", edge.ChannelId) - c := &channel{ - ChannelID: cid, - ChanPoint: edge.ChanPoint, - Capacity: edge.Capacity, - } + if matches[node2][node1] != nil { + continue + } - addr, err := api.Address(c.ChanPoint) - if err == nil { - c.Address = addr + log.Debugf("Node 1 (%s, %s) has channel with "+ + "match (%s): %v", node1, contact1, peer, + node1Chan.ChannelID) + + // This is a new match. + if matches[node1][node2] == nil { + matches[node1][node2] = &match{ + Node1: &nodeInfo{ + PubKey: node1, + Contact: contact1, + }, + Node2: &nodeInfo{ + PubKey: node2, + Contact: contact2, + }, } + } - matches[node1][node2].Channels[idx] = c + // Find the address of the channel. + addr, err := api.Address(node1Chan.ChanPoint) + if err != nil { + return fmt.Errorf("error fetching "+ + "address for channel %s: %w", + node1Chan.ChannelID, err) + } + capacity, err := strconv.ParseUint( + node1Chan.Capacity, 10, 64, + ) + if err != nil { + return fmt.Errorf("error parsing "+ + "capacity for channel %s: %w", + node1Chan.ChannelID, err) } + + // We've found a new match for this peer. + newChan := &channel{ + ChannelID: node1Chan.ChannelID, + ChanPoint: node1Chan.ChanPoint, + Address: addr, + Capacity: int64(capacity), + } + matches[node1][node2].Channels = append( + matches[node1][node2].Channels, + newChan, + ) } } } // Write the matches to files. for node1, node1map := range matches { - for node2, match := range node1map { - if match == nil || isPairDone(donePairs, node1, node2) { - continue - } + tpl, err := template.New("initial").Parse(initialTemplate) + if err != nil { + return fmt.Errorf("error parsing template: %w", err) + } + + tplVars := struct { + Contact string + Node1 string + NumChannels int + Peers []*nodeInfo + }{ + Contact: registrations[node1], + Node1: node1, + } + folder := fmt.Sprintf("results/match-%s", node1) + err = os.MkdirAll(folder, 0755) + if err != nil { + return err + } + + for node2, match := range node1map { matchBytes, err := json.MarshalIndent(match, "", " ") if err != nil { return err } - fileName := fmt.Sprintf("results/match-%s-%s-%s.json", - time.Now().Format("2006-01-02"), - node1, node2) + fileName := fmt.Sprintf("%s/%s-%s.json", + folder, node2, time.Now().Format("2006-01-02")) log.Infof("Writing result to %s", fileName) - err = ioutil.WriteFile(fileName, matchBytes, 0644) + err = os.WriteFile(fileName, matchBytes, 0644) if err != nil { return err } + + tplVars.NumChannels += len(match.Channels) + tplVars.Peers = append(tplVars.Peers, match.Node2) + } + + if tplVars.NumChannels == 0 { + continue + } + + textFileName := fmt.Sprintf("%s/message.txt", folder) + file, err := os.OpenFile( + textFileName, os.O_RDWR|os.O_CREATE, 0644, + ) + if err != nil { + return fmt.Errorf("error opening file %s: %w", + textFileName, err) + } + + err = tpl.Execute(file, tplVars) + if err != nil { + return fmt.Errorf("error executing template: %w", err) } } return nil } -func isPairDone(donePairs []*donePair, node1, node2 string) bool { - for _, donePair := range donePairs { - if donePair.matches(node1, node2) { - return true +func fetchChannels(client *graphql.Client, pubkey string) ([]*gqChannel, + error) { + + variables := map[string]interface{}{ + "pubkey": pubkey, + "limit": 50.0, + "offset": 0.0, + } + + var channels []*gqChannel + for { + var query gqGetNodeQuery + err := client.Query(context.Background(), &query, variables) + if err != nil { + return nil, err + } + + if len(query.GetNode.GraphInfo.Channels.ChannelList.List) == 0 { + break } + + channels = append( + channels, + query.GetNode.GraphInfo.Channels.ChannelList.List..., + ) + + variables["offset"] = variables["offset"].(float64) + 50.0 + } + + return channels, nil +} + +func identifyPeer(channel *gqChannel, node1 string) string { + if channel.Node1 == node1 { + return channel.Node2 + } + if channel.Node2 == node1 { + return channel.Node1 } - return false + panic("peer not found") } diff --git a/go.mod b/go.mod index e0824eb..dde220c 100644 --- a/go.mod +++ b/go.mod @@ -16,14 +16,18 @@ require ( github.com/davecgh/go-spew v1.1.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 github.com/gogo/protobuf v1.3.2 + github.com/hasura/go-graphql-client v0.9.1 github.com/lightninglabs/pool v0.5.7-alpha.0.20220715160511-f7c1ef26af2b github.com/lightningnetwork/lnd v0.16.0-beta.rc1 github.com/lightningnetwork/lnd/kvdb v1.4.1 + github.com/lightningnetwork/lnd/queue v1.1.0 + github.com/lightningnetwork/lnd/ticker v1.1.0 github.com/lightningnetwork/lnd/tor v1.1.0 github.com/spf13/cobra v1.1.3 github.com/stretchr/testify v1.8.1 go.etcd.io/bbolt v1.3.6 golang.org/x/crypto v0.1.0 + golang.org/x/oauth2 v0.0.0-20210615190721-d04028783cf1 ) require ( @@ -50,6 +54,8 @@ require ( github.com/fergusstrange/embedded-postgres v1.10.0 // indirect github.com/frankban/quicktest v1.11.2 // indirect github.com/go-errors/errors v1.0.1 // indirect + github.com/go-logr/logr v1.2.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/gofrs/uuid v4.2.0+incompatible // indirect github.com/golang-jwt/jwt/v4 v4.4.2 // indirect github.com/golang/protobuf v1.5.2 // indirect @@ -84,7 +90,7 @@ require ( github.com/juju/version/v2 v2.0.0 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/kkdai/bstream v1.0.0 // indirect - github.com/klauspost/compress v1.13.6 // indirect + github.com/klauspost/compress v1.16.0 // indirect github.com/klauspost/pgzip v1.2.5 // indirect github.com/lib/pq v1.10.3 // indirect github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf // indirect @@ -93,8 +99,6 @@ require ( github.com/lightningnetwork/lightning-onion v1.2.1-0.20221202012345-ca23184850a1 // indirect github.com/lightningnetwork/lnd/clock v1.1.0 // indirect github.com/lightningnetwork/lnd/healthcheck v1.2.2 // indirect - github.com/lightningnetwork/lnd/queue v1.1.0 // indirect - github.com/lightningnetwork/lnd/ticker v1.1.0 // indirect github.com/lightningnetwork/lnd/tlv v1.1.0 // indirect github.com/ltcsuite/ltcd v0.0.0-20191228044241-92166e412499 // indirect github.com/mattn/go-isatty v0.0.16 // indirect @@ -132,11 +136,11 @@ require ( go.etcd.io/etcd/raft/v3 v3.5.7 // indirect go.etcd.io/etcd/server/v3 v3.5.7 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.25.0 // indirect - go.opentelemetry.io/otel v1.0.1 // indirect + go.opentelemetry.io/otel v1.6.3 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1 // indirect go.opentelemetry.io/otel/sdk v1.0.1 // indirect - go.opentelemetry.io/otel/trace v1.0.1 // indirect + go.opentelemetry.io/otel/trace v1.6.3 // indirect go.opentelemetry.io/proto/otlp v0.9.0 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect @@ -150,6 +154,7 @@ require ( golang.org/x/text v0.5.0 // indirect golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect golang.org/x/tools v0.2.0 // indirect + google.golang.org/appengine v1.6.6 // indirect google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced // indirect google.golang.org/grpc v1.41.0 // indirect google.golang.org/protobuf v1.27.1 // indirect @@ -169,5 +174,6 @@ require ( modernc.org/sqlite v1.20.3 // indirect modernc.org/strutil v1.1.3 // indirect modernc.org/token v1.0.1 // indirect + nhooyr.io/websocket v1.8.7 // indirect sigs.k8s.io/yaml v1.2.0 // indirect ) diff --git a/go.sum b/go.sum index 105f5b8..a8b0d67 100644 --- a/go.sum +++ b/go.sum @@ -186,6 +186,10 @@ github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= +github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -197,7 +201,25 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0= @@ -258,6 +280,7 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -277,8 +300,13 @@ github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/graph-gophers/graphql-go v1.5.0 h1:fDqblo50TEpD0LY7RXk/LFVYEVqo3+tXMNMPSVXA1yc= +github.com/graph-gophers/graphql-go v1.5.0/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os= +github.com/graph-gophers/graphql-transport-ws v0.0.2 h1:DbmSkbIGzj8SvHei6n8Mh9eLQin8PtA8xY9eCzjRpvo= +github.com/graph-gophers/graphql-transport-ws v0.0.2/go.mod h1:5BVKvFzOd2BalVIBFfnfmHjpJi/MZ5rOj8G55mXvZ8g= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= @@ -309,6 +337,8 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hasura/go-graphql-client v0.9.1 h1:RBnaMLdK+muvauxcRitn73BzWnYWzWpKQ3n++eG2+wk= +github.com/hasura/go-graphql-client v0.9.1/go.mod h1:AarJlxO1I59MPqU/TC7gQP0BMFgPEqUTt5LYPvykasw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= @@ -368,6 +398,7 @@ github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -403,9 +434,10 @@ github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6 github.com/kkdai/bstream v1.0.0 h1:Se5gHwgp2VT2uHfDrkbbgbgEvV9cimLELwrPJctSjg8= github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= +github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/pgzip v1.2.4/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= @@ -421,6 +453,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -514,6 +548,7 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pierrec/lz4/v4 v4.0.3/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= @@ -612,6 +647,10 @@ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= @@ -655,16 +694,18 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.25.0 h1:Wx7nFnvCaissIUZxPkBqDz2963Z+Cl+PkYbDKzTxDqQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.25.0/go.mod h1:E5NNboN0UqSAki0Atn9kVwaN7I+l25gGxDqBueo/74E= -go.opentelemetry.io/otel v1.0.1 h1:4XKyXmfqJLOQ7feyV5DB6gsBFZ0ltB8vLtp6pj4JIcc= go.opentelemetry.io/otel v1.0.1/go.mod h1:OPEOD4jIT2SlZPMmwT6FqZz2C0ZNdQqiWcoK6M0SNFU= +go.opentelemetry.io/otel v1.6.3 h1:FLOfo8f9JzFVFVyU+MSRJc2HdEAXQgm7pIv2uFKRSZE= +go.opentelemetry.io/otel v1.6.3/go.mod h1:7BgNga5fNlF/iZjG06hM3yofffp0ofKCDwSXx1GC4dI= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1 h1:ofMbch7i29qIUf7VtF+r0HRF6ac0SBaPSziSsKp7wkk= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1/go.mod h1:Kv8liBeVNFkkkbilbgWRpV+wWuu+H5xdOT6HAgd30iw= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1 h1:CFMFNoz+CGprjFAFy+RJFrfEe4GBia3RRm2a4fREvCA= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1/go.mod h1:xOvWoTOrQjxjW61xtOmD/WKGRYb/P4NzRo3bs65U6Rk= go.opentelemetry.io/otel/sdk v1.0.1 h1:wXxFEWGo7XfXupPwVJvTBOaPBC9FEg0wB8hMNrKk+cA= go.opentelemetry.io/otel/sdk v1.0.1/go.mod h1:HrdXne+BiwsOHYYkBE5ysIcv2bvdZstxzmCQhxTcZkI= -go.opentelemetry.io/otel/trace v1.0.1 h1:StTeIH6Q3G4r0Fiw34LTokUFESZgIDUr0qIJ7mKmAfw= go.opentelemetry.io/otel/trace v1.0.1/go.mod h1:5g4i4fKLaX2BQpSBsxw8YYcgKpMMSW3x7ZTuYBr3sUk= +go.opentelemetry.io/otel/trace v1.6.3 h1:IqN4L+5b0mPNjdXIiZ90Ni4Bl5BRkDQywePLWemd9bc= +go.opentelemetry.io/otel/trace v1.6.3/go.mod h1:GNJQusJlUgZl9/TQBPKU/Y/ty+0iVB5fjhKeJGZPGFs= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.9.0 h1:C0g6TWmQYvjKRnljRULLWUVJGy8Uvu0NEL/5frY2/t4= go.opentelemetry.io/proto/otlp v0.9.0/go.mod h1:1vKfU9rv61e9EVGthD1zNvUbiwPcimSsOPU9brfSHJg= @@ -700,6 +741,7 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -779,6 +821,7 @@ golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU= golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -859,6 +902,7 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1098,6 +1142,8 @@ modernc.org/tcl v1.15.0 h1:oY+JeD11qVVSgVvodMJsu7Edf8tr5E/7tuhF5cNYz34= modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg= modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/z v1.7.0 h1:xkDw/KepgEjeizO2sNco+hqYkU12taxQFqPEmgm1GWE= +nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= +nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=