From c1f10fe9fa807a9d2be79f929386545f575ce12b Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Fri, 17 Dec 2021 12:12:08 -0300 Subject: [PATCH] add client filtering flag Signed-off-by: Ignacio Hagopian --- .bingo/Variables.mk | 6 ++-- .bingo/golangci-lint.mod | 2 +- .bingo/variables.env | 2 +- README.md | 4 +-- main.go | 7 ++++- service/service.go | 21 ++++++++++++++ service/service_internal_test.go | 49 ++++++++++++++++++++++++++++++++ service/service_test.go | 16 +++++++++++ 8 files changed, 99 insertions(+), 8 deletions(-) create mode 100644 service/service_internal_test.go diff --git a/.bingo/Variables.mk b/.bingo/Variables.mk index 30221b0..1ee2d10 100644 --- a/.bingo/Variables.mk +++ b/.bingo/Variables.mk @@ -29,11 +29,11 @@ $(BUF): $(BINGO_DIR)/buf.mod @echo "(re)installing $(GOBIN)/buf-v0.41.0" @cd $(BINGO_DIR) && $(GO) build -mod=mod -modfile=buf.mod -o=$(GOBIN)/buf-v0.41.0 "github.com/bufbuild/buf/cmd/buf" -GOLANGCI_LINT := $(GOBIN)/golangci-lint-v1.39.0 +GOLANGCI_LINT := $(GOBIN)/golangci-lint-v1.43.0 $(GOLANGCI_LINT): $(BINGO_DIR)/golangci-lint.mod @# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies. - @echo "(re)installing $(GOBIN)/golangci-lint-v1.39.0" - @cd $(BINGO_DIR) && $(GO) build -mod=mod -modfile=golangci-lint.mod -o=$(GOBIN)/golangci-lint-v1.39.0 "github.com/golangci/golangci-lint/cmd/golangci-lint" + @echo "(re)installing $(GOBIN)/golangci-lint-v1.43.0" + @cd $(BINGO_DIR) && $(GO) build -mod=mod -modfile=golangci-lint.mod -o=$(GOBIN)/golangci-lint-v1.43.0 "github.com/golangci/golangci-lint/cmd/golangci-lint" GOMPLATE := $(GOBIN)/gomplate-v3.9.0 $(GOMPLATE): $(BINGO_DIR)/gomplate.mod diff --git a/.bingo/golangci-lint.mod b/.bingo/golangci-lint.mod index 3c3971a..e4ecc86 100644 --- a/.bingo/golangci-lint.mod +++ b/.bingo/golangci-lint.mod @@ -2,4 +2,4 @@ module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT go 1.16 -require github.com/golangci/golangci-lint v1.39.0 // cmd/golangci-lint +require github.com/golangci/golangci-lint v1.43.0 // cmd/golangci-lint diff --git a/.bingo/variables.env b/.bingo/variables.env index 9afa7e4..ba92591 100644 --- a/.bingo/variables.env +++ b/.bingo/variables.env @@ -12,7 +12,7 @@ BINGO="${GOBIN}/bingo-v0.4.0" BUF="${GOBIN}/buf-v0.41.0" -GOLANGCI_LINT="${GOBIN}/golangci-lint-v1.39.0" +GOLANGCI_LINT="${GOBIN}/golangci-lint-v1.43.0" GOMPLATE="${GOBIN}/gomplate-v3.9.0" diff --git a/README.md b/README.md index 873e9d7..df86ca1 100644 --- a/README.md +++ b/README.md @@ -201,11 +201,11 @@ Problems can arise, especially when you are new to bidbot. Here are some common - Try several times with the Glif node that Bidbot uses - `FULLNODE_API_INFO="https://api.node.glif.io" lotus net findpeer YOUR_MINER_PEER_ID`. * Or you set too small a `--deal-start-window`. You would see something like `deal rejected: cannot seal a sector before ...` in your miner log. Set your `deal-start-window` to be a few hours longer than `ExpectedSealDuration` in your miner config. -1. Too many deals flood in, exceeding you sealing capacity. Two ways to throttle. +2. Too many deals flood in, exceeding you sealing capacity. Two ways to throttle. * `--running-bytes-limit` to limit the total bytes bidbot processes in a period of time. * `--sealing-sectors-limit` to pause bidding if the miner node has more than desired sectors in sealing. -1. We've seen a case when bidbot importing data long after winning the bids, it got errors like "normal shutdown of state machine" or "given data does not match expected commP ..." even though the real problem was the deal start epoch being exceeded. When in doubt, check your `lotus-miner` logs around that time for the real reason. +3. We've seen a case when bidbot importing data long after winning the bids, it got errors like "normal shutdown of state machine" or "given data does not match expected commP ..." even though the real problem was the deal start epoch being exceeded. When in doubt, check your `lotus-miner` logs around that time for the real reason. It is also suggested to set `--log-debug=true` and keep the logs when you want to seek help from Textile or the community. diff --git a/main.go b/main.go index 474d284..fb9aee7 100644 --- a/main.go +++ b/main.go @@ -176,7 +176,11 @@ Zero means no limits`, DefValue: "3h", Description: `The timeout to fetch deal data. Be conservative to leave enough room for network instability.`, }, - + { + Name: "client-address-whitelist", + DefValue: "", + Description: `If not empty, only bid in auctions from the comma-separated list of client addresses`, + }, { Name: "cid-gravity-key", DefValue: "", @@ -407,6 +411,7 @@ var daemonCmd = &cobra.Command{ Min: v.GetUint64("deal-size-min"), Max: v.GetUint64("deal-size-max"), }, + ClientAddressWhitelist: strings.Split(v.GetString("client-address-whitelist"), ","), }, BytesLimiter: bytesLimiter, ConcurrentImports: v.GetInt("concurrent-imports-limit"), diff --git a/service/service.go b/service/service.go index 7aebb1e..6b61f47 100644 --- a/service/service.go +++ b/service/service.go @@ -12,6 +12,7 @@ import ( "sync/atomic" "time" + "github.com/filecoin-project/go-address" "github.com/ipfs/go-cid" "github.com/libp2p/go-libp2p-core/crypto" core "github.com/libp2p/go-libp2p-core/peer" @@ -121,6 +122,8 @@ type AuctionFilters struct { DealDuration MinMaxFilter // DealSize sets the min and max deal size to bid on. DealSize MinMaxFilter + // ClientAddressWhitelist if not empty only allows bidding in auctions from a clients list. + ClientAddressWhitelist []string } // Validate ensures AuctionFilters are valid. @@ -131,6 +134,11 @@ func (f *AuctionFilters) Validate() error { if err := f.DealDuration.Validate(); err != nil { return fmt.Errorf("invalid deal size filter: %v", err) } + for _, clientAddress := range f.ClientAddressWhitelist { + if _, err := address.NewFromString(clientAddress); err != nil { + return fmt.Errorf("invalid client address filter %s: %s", clientAddress, err) + } + } return nil } @@ -443,6 +451,19 @@ func (s *Service) filterAuction(auction *pb.Auction) (rejectReason string) { s.auctionFilters.DealDuration.Max) } + if len(s.auctionFilters.ClientAddressWhitelist) > 0 { + var isWhitelistedClient bool + for _, clientAddress := range s.auctionFilters.ClientAddressWhitelist { + if clientAddress == auction.ClientAddress { + isWhitelistedClient = true + break + } + } + if !isWhitelistedClient { + return fmt.Sprintf("auction is from client %s which isn't whitelisted", auction.ClientAddress) + } + } + return "" } diff --git a/service/service_internal_test.go b/service/service_internal_test.go new file mode 100644 index 0000000..fb38f26 --- /dev/null +++ b/service/service_internal_test.go @@ -0,0 +1,49 @@ +package service + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" + pb "github.com/textileio/bidbot/gen/v1" + core "github.com/textileio/bidbot/lib/auction" + "google.golang.org/protobuf/types/known/timestamppb" +) + +func TestClientFilter(t *testing.T) { + t.Parallel() + + // Start with no client filters + s := Service{ + auctionFilters: AuctionFilters{ + DealDuration: MinMaxFilter{ + Min: core.MinDealDuration, + Max: core.MaxDealDuration, + }, + DealSize: MinMaxFilter{ + Min: 1, + Max: 10, + }, + }, + } + auction := &pb.Auction{ + DealSize: 5, + DealDuration: core.MinDealDuration, + EndsAt: timestamppb.New(time.Now().Add(time.Minute)), + ClientAddress: "f2kb4izxsxu2jyyslzwmv2sfbrgpld56efedgru5i", + } + + t.Run("accept-any-client-address", func(t *testing.T) { + require.Empty(t, s.filterAuction(auction)) + }) + + s.auctionFilters.ClientAddressWhitelist = []string{"f144zep4gitj73rrujd3jw6iprljicx6vl4wbeavi"} + t.Run("reject-single-client-address", func(t *testing.T) { + require.Contains(t, s.filterAuction(auction), "f2kb4izxsxu2jyyslzwmv2sfbrgpld56efedgru5i") + }) + + auction.ClientAddress = s.auctionFilters.ClientAddressWhitelist[0] + t.Run("accept-single-client-address", func(t *testing.T) { + require.Empty(t, s.filterAuction(auction)) + }) +} diff --git a/service/service_test.go b/service/service_test.go index ae4d54d..964fffc 100644 --- a/service/service_test.go +++ b/service/service_test.go @@ -95,6 +95,22 @@ func TestNew(t *testing.T) { }) require.Error(t, err) + // Incorrect string representation of whitelisted client address. + _, err = newService(t, func(config *service.Config) { + config.AuctionFilters = service.AuctionFilters{ + DealDuration: service.MinMaxFilter{ + Min: 10, + Max: 20, + }, + DealSize: service.MinMaxFilter{ + Min: 10, + Max: 20, + }, + ClientAddressWhitelist: []string{"invalidClientAddr"}, + } + }) + require.Error(t, err) + // Good config s, err := newService(t, nil) require.NoError(t, err)