From 3c50706377d753f90cc3ccc1c9535229d50f3f76 Mon Sep 17 00:00:00 2001 From: Will Date: Fri, 24 Apr 2020 11:10:16 -0700 Subject: [PATCH] fuzzing harness (#153) Adds a go-fuzz entrypoint for fuzzing datastore transactions for crashes. --- fuzz/.gitignore | 5 + fuzz/README.md | 28 +++ fuzz/cmd/compare/main.go | 104 +++++++++++ fuzz/cmd/generate/main.go | 75 ++++++++ fuzz/cmd/isprefix/main.go | 115 +++++++++++++ fuzz/cmd/run/main.go | 41 +++++ fuzz/fuzzer.go | 350 ++++++++++++++++++++++++++++++++++++++ fuzz/go.mod | 11 ++ fuzz/go.sum | 112 ++++++++++++ go.mod | 3 +- go.sum | 21 +-- 11 files changed, 848 insertions(+), 17 deletions(-) create mode 100644 fuzz/.gitignore create mode 100644 fuzz/README.md create mode 100644 fuzz/cmd/compare/main.go create mode 100644 fuzz/cmd/generate/main.go create mode 100644 fuzz/cmd/isprefix/main.go create mode 100644 fuzz/cmd/run/main.go create mode 100644 fuzz/fuzzer.go create mode 100644 fuzz/go.mod create mode 100644 fuzz/go.sum diff --git a/fuzz/.gitignore b/fuzz/.gitignore new file mode 100644 index 0000000..ae1c595 --- /dev/null +++ b/fuzz/.gitignore @@ -0,0 +1,5 @@ +provider_*.go +*.zip +corpus +crashers +suppressions diff --git a/fuzz/README.md b/fuzz/README.md new file mode 100644 index 0000000..715b026 --- /dev/null +++ b/fuzz/README.md @@ -0,0 +1,28 @@ +IPFS Datastore Fuzzer +==== + +The fuzzer provides a [go fuzzer](https://github.com/dvyukov/go-fuzz) interface +to Datastore implementations. This can be used for fuzz testing of these +implementations. + +Usage +---- + +First, configure the datastores to fuzz (from this directory): +```golang +// either run via `go run` +go run ./cmd/generate github.com/ipfs/go-ds-badger +// or `go generate` +DS_PROVIDERS="github.com/ipfs/go-ds-badger" go generate +``` + +Then, build the fuzzing artifact and fuzz: +```golang +go-fuzz-build +go-fuzz +``` + +If you don't have `go-fuzz` installed, it can be acquired as: +``` +go get -u github.com/dvyukov/go-fuzz/go-fuzz github.com/dvyukov/go-fuzz/go-fuzz-build +``` diff --git a/fuzz/cmd/compare/main.go b/fuzz/cmd/compare/main.go new file mode 100644 index 0000000..77a2d8c --- /dev/null +++ b/fuzz/cmd/compare/main.go @@ -0,0 +1,104 @@ +package main + +import ( + "fmt" + "io/ioutil" + "os" + + ds "github.com/ipfs/go-datastore" + fuzzer "github.com/ipfs/go-datastore/fuzz" + dsq "github.com/ipfs/go-datastore/query" + + "github.com/spf13/pflag" +) + +var input *string = pflag.StringP("input", "i", "", "file to read input from (stdin used if not specified)") +var db1 *string = pflag.StringP("db1", "d", "badger", "database to fuzz") +var db2 *string = pflag.StringP("db2", "e", "level", "database to fuzz") +var dbFile *string = pflag.StringP("file", "f", "tmp", "where the db instances should live on disk") +var threads *int = pflag.IntP("threads", "t", 1, "concurrent threads") + +func main() { + pflag.Parse() + + // do one, then the other, then compare state. + + fuzzer.Threads = *threads + + var dat []byte + var err error + if *input == "" { + dat, err = ioutil.ReadAll(os.Stdin) + } else { + dat, err = ioutil.ReadFile(*input) + } + if err != nil { + fmt.Fprintf(os.Stderr, "Could not read %s: %v\n", *input, err) + return + } + + db1loc := *dbFile + "1" + inst1, err := fuzzer.Open(*db1, db1loc, false) + if err != nil { + fmt.Fprintf(os.Stderr, "Could not open db: %v\n", err) + return + } + defer inst1.Cancel() + + db2loc := *dbFile + "2" + inst2, err := fuzzer.Open(*db2, db2loc, false) + if err != nil { + inst1.Cancel() + fmt.Fprintf(os.Stderr, "Could not open db: %v\n", err) + return + } + defer inst2.Cancel() + + fmt.Printf("Running db1.........") + inst1.Fuzz(dat) + fmt.Printf("done\n") + fmt.Printf("Running db2.........") + inst2.Fuzz(dat) + fmt.Printf("done\n") + + fmt.Printf("Checking equality...") + db1 := inst1.DB() + db2 := inst2.DB() + r1, err := db1.Query(dsq.Query{}) + if err != nil { + panic(err) + } + + for r := range r1.Next() { + if r.Error != nil { + break + } + if r.Entry.Key == "/" { + continue + } + + if exist, _ := db2.Has(ds.NewKey(r.Entry.Key)); !exist { + fmt.Fprintf(os.Stderr, "db2 failed to get key %s held by db1\n", r.Entry.Key) + } + } + + r2, err := db2.Query(dsq.Query{}) + if err != nil { + panic(err) + } + + for r := range r2.Next() { + if r.Error != nil { + break + } + if r.Entry.Key == "/" { + continue + } + + if exist, _ := db1.Has(ds.NewKey(r.Entry.Key)); !exist { + fmt.Fprintf(os.Stderr, "db1 failed to get key %s held by db2\n", r.Entry.Key) + } + } + + fmt.Printf("Done\n") +} diff --git a/fuzz/cmd/generate/main.go b/fuzz/cmd/generate/main.go new file mode 100644 index 0000000..011b911 --- /dev/null +++ b/fuzz/cmd/generate/main.go @@ -0,0 +1,75 @@ +// This file is invoked by `go generate` +package main + +import ( + "fmt" + "os" + "os/exec" + "strings" + "text/template" +) + +// This program generates bindings to fuzz a concrete datastore implementation. +// It can be invoked by running `go generate ` + +func main() { + providers := os.Args[1:] + + if len(providers) == 0 { + providers = strings.Split(os.Getenv("DS_PROVIDERS"), ",") + } + if len(providers) == 0 { + fmt.Fprintf(os.Stderr, "No providers specified to generate. Nothing to do.") + return + } + + for _, provider := range providers { + provider = strings.TrimSpace(provider) + if len(provider) == 0 { + continue + } + cmd := exec.Command("go", "get", provider) + err := cmd.Run() + if err != nil { + fmt.Fprintf(os.Stderr, "failed to add dependency for %s: %v\n", provider, err) + os.Exit(1) + } + + nameComponents := strings.Split(provider, "/") + name := nameComponents[len(nameComponents)-1] + f, err := os.Create(fmt.Sprintf("provider_%s.go", name)) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to create provider file: %v\n", err) + os.Exit(1) + } + defer f.Close() + err = provideTemplate.Execute(f, struct { + Package string + PackageName string + }{ + Package: provider, + PackageName: name, + }) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to write provider: %v\n", err) + os.Exit(1) + } + } +} + +var provideTemplate = template.Must(template.New("").Parse(`// Code generated by go generate; DO NOT EDIT. + +package fuzzer +import prov "{{ .Package }}" +import ds "github.com/ipfs/go-datastore" + +func init() { + AddOpener("{{ .PackageName }}", func(loc string) ds.TxnDatastore { + d, err := prov.NewDatastore(loc, nil) + if err != nil { + panic("could not create db instance") + } + return d + }) +} +`)) diff --git a/fuzz/cmd/isprefix/main.go b/fuzz/cmd/isprefix/main.go new file mode 100644 index 0000000..a6f7555 --- /dev/null +++ b/fuzz/cmd/isprefix/main.go @@ -0,0 +1,115 @@ +package main + +// Checks if a db instance is equivalent to some prefix of an input script. + +import ( + "fmt" + "io/ioutil" + "os" + + ds "github.com/ipfs/go-datastore" + fuzzer "github.com/ipfs/go-datastore/fuzz" + dsq "github.com/ipfs/go-datastore/query" + + "github.com/spf13/pflag" +) + +var input *string = pflag.StringP("input", "i", "", "file to read input from (stdin used if not specified)") +var db *string = pflag.StringP("db", "d", "go-ds-badger", "database driver") +var dbPrev *string = pflag.StringP("exist", "e", "tmp1", "database instance already made") +var dbFile *string = pflag.StringP("file", "f", "tmp2", "where the replay should live") +var threads *int = pflag.IntP("threads", "t", 1, "concurrent threads") + +type validatingReader struct { + b []byte + i int + validator func(bool) bool + validI int +} + +func (v *validatingReader) Read(buf []byte) (n int, err error) { + if v.i == len(v.b) { + return 0, nil + } + if v.validator(false) { + v.validI = v.i + } + buf[0] = v.b[v.i] + v.i++ + return 1, nil +} + +func main() { + pflag.Parse() + + fuzzer.Threads = *threads + + var dat []byte + var err error + if *input == "" { + dat, err = ioutil.ReadAll(os.Stdin) + } else { + dat, err = ioutil.ReadFile(*input) + } + if err != nil { + fmt.Fprintf(os.Stderr, "could not read %s: %v\n", *input, err) + return + } + + previousDB, err := fuzzer.Open(*db, *dbPrev, false) + if err != nil { + fmt.Fprintf(os.Stderr, "could not open: %v\n", err) + return + } + defer previousDB.Cancel() + + replayDB, err := fuzzer.Open(*db, *dbFile, true) + if err != nil { + fmt.Fprintf(os.Stderr, "could not open: %v\n", err) + return + } + defer replayDB.Cancel() + + reader := validatingReader{dat, 0, func(verbose bool) bool { + res, _ := replayDB.DB().Query(dsq.Query{}) + for e := range res.Next() { + if e.Entry.Key == "/" { + continue + } + if h, _ := previousDB.DB().Has(ds.NewKey(e.Entry.Key)); !h { + if verbose { + fmt.Printf("failed - script run db has %s not in existing.\n", e.Entry.Key) + } + return false // not yet complete + } + } + // next; make sure the other way is equal. + res, _ = previousDB.DB().Query(dsq.Query{}) + for e := range res.Next() { + if e.Entry.Key == "/" { + continue + } + if h, _ := replayDB.DB().Has(ds.NewKey(e.Entry.Key)); !h { + if verbose { + fmt.Printf("failed - existing db has %s not in replay.\n", e.Entry.Key) + } + return false + } + } + // db images are the same. + return true + }, -1} + + replayDB.FuzzStream(&reader) + if reader.validator(true) { + reader.validI = reader.i + } + + if reader.validI > -1 { + fmt.Printf("Matched at stream position %d.\n", reader.validI) + os.Exit(0) + } else { + fmt.Printf("Failed to match\n") + os.Exit(1) + } +} diff --git a/fuzz/cmd/run/main.go b/fuzz/cmd/run/main.go new file mode 100644 index 0000000..332a544 --- /dev/null +++ b/fuzz/cmd/run/main.go @@ -0,0 +1,41 @@ +package main + +import ( + "bufio" + "fmt" + "io/ioutil" + "os" + + fuzzer "github.com/ipfs/go-datastore/fuzz" + + "github.com/spf13/pflag" +) + +var input *string = pflag.StringP("input", "i", "", "file to read input from (stdin used if not specified)") +var db *string = pflag.StringP("database", "d", "go-ds-badger", "database to fuzz") +var dbFile *string = pflag.StringP("file", "f", "tmp", "where the db instace should live on disk") +var threads *int = pflag.IntP("threads", "t", 1, "concurrent threads") + +func main() { + pflag.Parse() + + fuzzer.Threads = *threads + + if *input != "" { + dat, err := ioutil.ReadFile(*input) + if err != nil { + fmt.Fprintf(os.Stderr, "could not read %s: %v\n", *input, err) + os.Exit(1) + } + ret := fuzzer.FuzzDB(*db, *dbFile, false, dat) + os.Exit(ret) + } else { + reader := bufio.NewReader(os.Stdin) + err := fuzzer.FuzzStream(*db, *dbFile, false, reader) + if err != nil { + fmt.Fprintf(os.Stderr, "Error fuzzing: %v\n", err) + os.Exit(1) + } + return + } +} diff --git a/fuzz/fuzzer.go b/fuzz/fuzzer.go new file mode 100644 index 0000000..8252563 --- /dev/null +++ b/fuzz/fuzzer.go @@ -0,0 +1,350 @@ +package fuzzer + +import ( + "context" + "fmt" + "io" + "io/ioutil" + "os" + "sync" + "sync/atomic" + + ds "github.com/ipfs/go-datastore" + dsq "github.com/ipfs/go-datastore/query" +) + +//go:generate go run ./cmd/generate + +// openers contains the known datastore implementations. +var openers map[string]func(string) ds.TxnDatastore + +// AddOpener allows registration of a new driver for fuzzing. +func AddOpener(name string, opener func(loc string) ds.TxnDatastore) { + if openers == nil { + openers = make(map[string]func(string) ds.TxnDatastore) + } + openers[name] = opener +} + +// Threads is a measure of concurrency. +// Note: if Threads > 1, determinism is not guaranteed. +var Threads int + +func init() { + if openers == nil { + openers = make(map[string]func(string) ds.TxnDatastore) + } + Threads = 1 +} + +// RunState encapulates the state of a given fuzzing run +type RunState struct { + inst ds.TxnDatastore + inputChannels []chan<- byte + wg sync.WaitGroup + Cancel context.CancelFunc + + keyCache [128]ds.Key + cachedKeys int32 + ctr int32 //nolint:structcheck,unused +} + +// DB returns the datastore being driven by this instance +func (r *RunState) DB() ds.TxnDatastore { + return r.inst +} + +type threadState struct { + op + keyReady bool + key ds.Key + valReady bool + val []byte + reader ds.Read + writer ds.Write + txn ds.Txn + *RunState +} + +// Open instantiates an instance of the database implementation for testing. +func Open(driver string, location string, cleanup bool) (*RunState, error) { + ctx, cncl := context.WithCancel(context.Background()) + + opener, ok := openers[driver] + if !ok { + cncl() + return nil, fmt.Errorf("no such driver: %s", driver) + } + + state := RunState{} + state.inst = opener(location) + state.keyCache[0] = ds.NewKey("/") + state.cachedKeys = 1 + + state.wg.Add(Threads) + + // wrap the context cancel to block until everythign is fully closed. + doneCh := make(chan struct{}) + state.Cancel = func() { + for i := 0; i < Threads; i++ { + close(state.inputChannels[i]) + } + cncl() + <-doneCh + } + go func() { + state.wg.Wait() + state.inst.Close() + if cleanup { + os.RemoveAll(location) + } + close(doneCh) + }() + + state.inputChannels = make([]chan<- byte, Threads) + for i := 0; i < Threads; i++ { + dr := make(chan byte, 15) + go threadDriver(ctx, &state, dr) + state.inputChannels[i] = dr + } + return &state, nil +} + +// Fuzz is a go-fuzzer compatible input point for replaying +// data (interpreted as a script of commands) +// to known ipfs datastore implementations +func Fuzz(data []byte) int { + var impls []string + for impl := range openers { + impls = append(impls, impl) + } + + defaultLoc, _ := ioutil.TempDir("", "fuzz-*") + + if len(impls) == 0 { + fmt.Fprintf(os.Stderr, "No datastores to fuzz.\n") + return -1 + } else if len(impls) == 1 { + return FuzzDB(impls[0], defaultLoc, true, data) + } else { + impl := impls[int(data[0])%len(impls)] + return FuzzDB(impl, defaultLoc, true, data[1:]) + } +} + +// FuzzDB fuzzes a given database entry, providing sufficient hooks to be +// used by CLI commands. +func FuzzDB(driver string, location string, cleanup bool, data []byte) int { + inst, err := Open(driver, location, cleanup) + if err != nil { + return -1 + } + inst.Fuzz(data) + inst.Cancel() + return 0 +} + +// FuzzStream does the same as fuzz but with streaming input +func FuzzStream(driver string, location string, cleanup bool, data io.Reader) error { + inst, err := Open("badger", "tmp", true) + if err != nil { + return err + } + + inst.FuzzStream(data) + inst.Cancel() + return nil +} + +// Fuzz sends a set of bytes to drive the current open datastore instance. +func (r *RunState) Fuzz(data []byte) { + for i, b := range data { + r.inputChannels[i%Threads] <- b + } +} + +// FuzzStream sends a set of bytes to drive the current instance from a reader. +func (r *RunState) FuzzStream(data io.Reader) { + b := make([]byte, 4096) + for { + n, _ := data.Read(b) + if n == 0 { + break + } + r.Fuzz(b[:n]) + } +} + +type op byte + +const ( + opNone op = iota + opGet + opHas + opGetSize + opQuery + opPut + opDelete + opNewTX + opCommitTX + opDiscardTX + opSync + opMax +) + +func threadDriver(ctx context.Context, runState *RunState, cmnds chan byte) { + defer runState.wg.Done() + s := threadState{} + s.RunState = runState + s.reader = runState.inst + s.writer = runState.inst + + for { + select { + case c, ok := <-cmnds: + if !ok { + return + } + _ = nextState(&s, c) + case <-ctx.Done(): + return + } + } +} + +func nextState(s *threadState, c byte) error { + if s.op == opNone { + s.op = op(c) % opMax + return nil + } else if s.op == opGet { + if !s.keyReady { + return makeKey(s, c) + } + _, _ = s.reader.Get(s.key) + reset(s) + return nil + } else if s.op == opHas { + if !s.keyReady { + return makeKey(s, c) + } + _, _ = s.reader.Has(s.key) + reset(s) + return nil + } else if s.op == opGetSize { + if !s.keyReady { + return makeKey(s, c) + } + _, _ = s.reader.GetSize(s.key) + reset(s) + return nil + } else if s.op == opQuery { + r, _ := s.reader.Query(dsq.Query{}) + defer r.Close() + reset(s) + + for e := range r.Next() { + if e.Error != nil { + return nil + } + } + return nil + } else if s.op == opPut { + if !s.keyReady { + return makeKey(s, c) + } + if !s.valReady { + return makeValue(s, c) + } + _ = s.writer.Put(s.key, s.val) + reset(s) + return nil + } else if s.op == opDelete { + if !s.keyReady { + return makeKey(s, c) + } + _ = s.writer.Delete(s.key) + reset(s) + return nil + } else if s.op == opNewTX { + if s.txn == nil { + s.txn, _ = s.RunState.inst.NewTransaction(((c & 1) == 1)) + if (c & 1) != 1 { // read+write + s.writer = s.txn + } + s.reader = s.txn + } + reset(s) + return nil + } else if s.op == opCommitTX { + if s.txn != nil { + s.txn.Discard() + s.txn = nil + s.reader = s.RunState.inst + s.writer = s.RunState.inst + } + reset(s) + return nil + } else if s.op == opDiscardTX { + if s.txn != nil { + s.txn.Discard() + s.txn = nil + s.reader = s.RunState.inst + s.writer = s.RunState.inst + } + reset(s) + return nil + } else if s.op == opSync { + if !s.keyReady { + return makeKey(s, c) + } + _ = s.RunState.inst.Sync(s.key) + reset(s) + return nil + } + return nil +} + +func reset(s *threadState) { + s.op = opNone + s.keyReady = false + s.key = ds.RawKey("") + s.valReady = false +} + +func makeKey(s *threadState, c byte) error { + keys := atomic.LoadInt32(&s.RunState.cachedKeys) + if keys > 128 { + keys = 128 + } + if c&1 == 1 { + // 50% chance we want to-reuse an existing key + s.key = s.RunState.keyCache[(c>>1)%byte(keys)] + s.keyReady = true + } else { + s.key = ds.NewKey(fmt.Sprintf("key-%d", atomic.AddInt32(&s.ctr, 1))) + // half the time we'll make it a child of an existing key + if c&2 == 2 { + s.key = s.RunState.keyCache[(c>>1)%byte(keys)].Child(s.key) + } + // new key + if keys < 128 { + keys = atomic.AddInt32(&s.RunState.cachedKeys, 1) + if keys >= 128 { + atomic.StoreInt32(&s.RunState.cachedKeys, 128) + } else { + s.RunState.keyCache[keys-1] = s.key + } + } + s.keyReady = true + } + return nil +} + +func makeValue(s *threadState, c byte) error { + s.val = make([]byte, c) + if c != 0 { + s.val[0] = 1 + } + s.valReady = true + return nil +} diff --git a/fuzz/go.mod b/fuzz/go.mod new file mode 100644 index 0000000..a080762 --- /dev/null +++ b/fuzz/go.mod @@ -0,0 +1,11 @@ +module github.com/ipfs/go-datastore/fuzz + +go 1.14 + +replace github.com/ipfs/go-datastore => ../ + +require ( + github.com/ipfs/go-datastore v0.4.4 + github.com/ipfs/go-ds-badger v0.2.4 + github.com/spf13/pflag v1.0.3 +) diff --git a/fuzz/go.sum b/fuzz/go.sum new file mode 100644 index 0000000..6be1ad6 --- /dev/null +++ b/fuzz/go.sum @@ -0,0 +1,112 @@ +github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9 h1:HD8gA2tkByhMAwYaFAX9w2l7vxvBQ5NMoxDrkhqhtn4= +github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgraph-io/badger v1.6.1 h1:w9pSFNSdq/JPM1N12Fz/F/bzo993Is1W+Q7HjPzi7yg= +github.com/dgraph-io/badger v1.6.1/go.mod h1:FRmFw3uxvcpa8zG3Rxs0th+hCLIuaQg8HlNV5bjgnuU= +github.com/dgraph-io/ristretto v0.0.2 h1:a5WaUrDa0qm0YrAAS1tUykT5El3kt62KNZZeMxQn3po= +github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/ipfs/go-datastore v0.4.4 h1:rjvQ9+muFaJ+QZ7dN5B1MSDNQ0JVZKkkES/rMZmA8X8= +github.com/ipfs/go-datastore v0.4.4/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= +github.com/ipfs/go-ds-badger v0.2.4 h1:UPGB0y7luFHk+mY/tUZrif/272M8o+hFsW+avLUeWrM= +github.com/ipfs/go-ds-badger v0.2.4/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBRn4FS6UHUk= +github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= +github.com/ipfs/go-log v0.0.1 h1:9XTUN/rW64BCG1YhPK9Hoy3q8nr4gOmHHBpgFdfw6Lc= +github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= +github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= +github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY= +github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= +github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc h1:9lDbC6Rz4bwmou+oE6Dt4Cb2BGMur5eR/GYptkKUVHo= +github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= diff --git a/go.mod b/go.mod index 1e3a08c..1364c12 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,8 @@ module github.com/ipfs/go-datastore require ( github.com/google/uuid v1.1.1 github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8 - github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8 + github.com/jbenet/goprocess v0.1.4 + github.com/kr/pretty v0.2.0 // indirect go.uber.org/multierr v1.5.0 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 diff --git a/go.sum b/go.sum index 42ad0af..162cb11 100644 --- a/go.sum +++ b/go.sum @@ -1,41 +1,32 @@ -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8 h1:NAviDvJ0WXgD+yiL2Rj35AmnfgI11+pHXbdciD917U0= github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= -github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8 h1:bspPhN+oKYFk5fcGNuQzp6IGzYQSenLEgH3s6jkXrWw= -github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY= +github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= +github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= +github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw= +github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/multierr v1.4.0 h1:f3WCSC2KzAcBXGATIxAB1E2XuCpNU255wNKZ505qi3E= -go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -48,7 +39,6 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -56,5 +46,4 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=