diff --git a/.github/workflows/automerge.yml b/.github/workflows/automerge.yml new file mode 100644 index 0000000000000000000000000000000000000000..32bcc2e6e571121eee3c966f2f31bb86c5430e93 --- /dev/null +++ b/.github/workflows/automerge.yml @@ -0,0 +1,51 @@ +# File managed by web3-bot. DO NOT EDIT. +# See https://github.com/protocol/.github/ for details. + +# Automatically merge pull requests opened by web3-bot, as soon as (and only if) all tests pass. +# This reduces the friction associated with updating with our workflows. + +on: [ pull_request ] +name: Automerge + +jobs: + automerge-check: + if: github.event.pull_request.user.login == 'web3-bot' + runs-on: ubuntu-latest + outputs: + status: ${{ steps.should-automerge.outputs.status }} + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Check if we should automerge + id: should-automerge + run: | + for commit in $(git rev-list --first-parent origin/${{ github.event.pull_request.base.ref }}..${{ github.event.pull_request.head.sha }}); do + committer=$(git show --format=$'%ce' -s $commit) + echo "Committer: $committer" + if [[ "$committer" != "web3-bot@users.noreply.github.com" ]]; then + echo "Commit $commit wasn't committed by web3-bot, but by $committer." + echo "::set-output name=status::false" + exit + fi + done + echo "::set-output name=status::true" + automerge: + needs: automerge-check + runs-on: ubuntu-latest + if: ${{ needs.automerge-check.outputs.status == 'true' }} + steps: + - name: Wait on tests + uses: lewagon/wait-on-check-action@bafe56a6863672c681c3cf671f5e10b20abf2eaa # v0.2 + with: + ref: ${{ github.event.pull_request.head.sha }} + repo-token: ${{ secrets.GITHUB_TOKEN }} + wait-interval: 10 + running-workflow-name: 'automerge' # the name of this job + - name: Merge PR + uses: pascalgn/automerge-action@741c311a47881be9625932b0a0de1b0937aab1ae # v0.13.1 + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + MERGE_LABELS: "" + MERGE_METHOD: "squash" + MERGE_DELETE_BRANCH: true diff --git a/.github/workflows/go-check.yml b/.github/workflows/go-check.yml new file mode 100644 index 0000000000000000000000000000000000000000..00ce947c82a56a488b0fc018e4a7dbf2fad2e95e --- /dev/null +++ b/.github/workflows/go-check.yml @@ -0,0 +1,50 @@ +# File managed by web3-bot. DO NOT EDIT. +# See https://github.com/protocol/.github/ for details. + +on: [push, pull_request] +name: Go Checks + +jobs: + unit: + runs-on: ubuntu-latest + name: All + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive + - uses: actions/setup-go@v2 + with: + go-version: "1.16.x" + - name: Install staticcheck + run: go install honnef.co/go/tools/cmd/staticcheck@434f5f3816b358fe468fa83dcba62d794e7fe04b # 2021.1 (v0.2.0) + - name: Check that go.mod is tidy + uses: protocol/multiple-go-modules@v1.0 + with: + run: | + go mod tidy + if [[ -n $(git ls-files --other --exclude-standard --directory -- go.sum) ]]; then + echo "go.sum was added by go mod tidy" + exit 1 + fi + git diff --exit-code -- go.sum go.mod + - name: gofmt + if: ${{ success() || failure() }} # run this step even if the previous one failed + run: | + out=$(gofmt -s -l .) + if [[ -n "$out" ]]; then + echo $out | awk '{print "::error file=" $0 ",line=0,col=0::File is not gofmt-ed."}' + exit 1 + fi + - name: go vet + if: ${{ success() || failure() }} # run this step even if the previous one failed + uses: protocol/multiple-go-modules@v1.0 + with: + run: go vet ./... + - name: staticcheck + if: ${{ success() || failure() }} # run this step even if the previous one failed + uses: protocol/multiple-go-modules@v1.0 + with: + run: | + set -o pipefail + staticcheck ./... | sed -e 's@\(.*\)\.go@./\1.go@g' + diff --git a/.github/workflows/go-test.yml b/.github/workflows/go-test.yml new file mode 100644 index 0000000000000000000000000000000000000000..4c7138b01d0c904d152e351b15e45ff2a413174d --- /dev/null +++ b/.github/workflows/go-test.yml @@ -0,0 +1,47 @@ +# File managed by web3-bot. DO NOT EDIT. +# See https://github.com/protocol/.github/ for details. + +on: [push, pull_request] +name: Go Test + +jobs: + unit: + strategy: + fail-fast: false + matrix: + os: [ "ubuntu", "windows", "macos" ] + go: [ "1.15.x", "1.16.x" ] + runs-on: ${{ matrix.os }}-latest + name: ${{ matrix.os}} (go ${{ matrix.go }}) + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive + - uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go }} + - name: Go information + run: | + go version + go env + - name: Run tests + uses: protocol/multiple-go-modules@v1.0 + with: + run: go test -v -coverprofile coverage.txt ./... + - name: Run tests (32 bit) + if: ${{ matrix.os != 'macos' }} # can't run 32 bit tests on OSX. + uses: protocol/multiple-go-modules@v1.0 + env: + GOARCH: 386 + with: + run: go test -v ./... + - name: Run tests with race detector + if: ${{ matrix.os == 'ubuntu' }} # speed things up. Windows and OSX VMs are slow + uses: protocol/multiple-go-modules@v1.0 + with: + run: go test -v -race ./... + - name: Upload coverage to Codecov + uses: codecov/codecov-action@a1ed4b322b4b38cb846afb5a0ebfa17086917d27 # v1.5.0 + with: + file: coverage.txt + env_vars: OS=${{ matrix.os }}, GO=${{ matrix.go }} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 5163d693fc757ec0c13d134e9d4cabd6cc7c85d7..0000000000000000000000000000000000000000 --- a/.travis.yml +++ /dev/null @@ -1,30 +0,0 @@ -os: - - linux - -language: go - -go: - - 1.11.x - -env: - global: - - GOTFLAGS="-race" - matrix: - - BUILD_DEPTYPE=gomod - - -# disable travis install -install: - - true - -script: - - bash <(curl -s https://raw.githubusercontent.com/ipfs/ci-helpers/master/travis-ci/run-standard-tests.sh) - - -cache: - directories: - - $GOPATH/pkg/mod - - $HOME/.cache/go-build - -notifications: - email: false diff --git a/cid.go b/cid.go index 97daca3624b38b707e7d3750295870fed8dbf16a..73a4d62d06f4a3dfc07a5932e9c9872cb342fcbe 100644 --- a/cid.go +++ b/cid.go @@ -185,10 +185,12 @@ func NewCidV1(codecType uint64, mhash mh.Multihash) Cid { return Cid{string(buf[:n+hashlen])} } -var _ encoding.BinaryMarshaler = Cid{} -var _ encoding.BinaryUnmarshaler = (*Cid)(nil) -var _ encoding.TextMarshaler = Cid{} -var _ encoding.TextUnmarshaler = (*Cid)(nil) +var ( + _ encoding.BinaryMarshaler = Cid{} + _ encoding.BinaryUnmarshaler = (*Cid)(nil) + _ encoding.TextMarshaler = Cid{} + _ encoding.TextUnmarshaler = (*Cid)(nil) +) // Cid represents a self-describing content addressed // identifier. It is formed by a Version, a Codec (which indicates @@ -564,7 +566,7 @@ type Prefix struct { // and return a newly constructed Cid with the resulting multihash. func (p Prefix) Sum(data []byte) (Cid, error) { length := p.MhLength - if p.MhType == mh.ID { + if p.MhType == mh.IDENTITY { length = -1 } @@ -678,3 +680,139 @@ func CidFromBytes(data []byte) (int, Cid, error) { return l, Cid{string(data[0:l])}, nil } + +func toBufByteReader(r io.Reader, dst []byte) *bufByteReader { + // If the reader already implements ByteReader, use it directly. + // Otherwise, use a fallback that does 1-byte Reads. + if br, ok := r.(io.ByteReader); ok { + return &bufByteReader{direct: br, dst: dst} + } + return &bufByteReader{fallback: r, dst: dst} +} + +type bufByteReader struct { + direct io.ByteReader + fallback io.Reader + + dst []byte +} + +func (r *bufByteReader) ReadByte() (byte, error) { + // The underlying reader has ReadByte; use it. + if br := r.direct; br != nil { + b, err := br.ReadByte() + if err != nil { + return 0, err + } + r.dst = append(r.dst, b) + return b, nil + } + + // Fall back to a one-byte Read. + // TODO: consider reading straight into dst, + // once we have benchmarks and if they prove that to be faster. + var p [1]byte + if _, err := io.ReadFull(r.fallback, p[:]); err != nil { + return 0, err + } + r.dst = append(r.dst, p[0]) + return p[0], nil +} + +// CidFromReader reads a precise number of bytes for a CID from a given reader. +// It returns the number of bytes read, the CID, and any error encountered. +// The number of bytes read is accurate even if a non-nil error is returned. +// +// It's recommended to supply a reader that buffers and implements io.ByteReader, +// as CidFromReader has to do many single-byte reads to decode varints. +// If the argument only implements io.Reader, single-byte Read calls are used instead. +func CidFromReader(r io.Reader) (int, Cid, error) { + // 64 bytes is enough for any CIDv0, + // and it's enough for most CIDv1s in practice. + // If the digest is too long, we'll allocate more. + br := toBufByteReader(r, make([]byte, 0, 64)) + + // We read the first varint, to tell if this is a CIDv0 or a CIDv1. + // The varint package wants a io.ByteReader, so we must wrap our io.Reader. + vers, err := varint.ReadUvarint(br) + if err != nil { + return len(br.dst), Undef, err + } + + // If we have a CIDv0, read the rest of the bytes and cast the buffer. + if vers == mh.SHA2_256 { + if n, err := io.ReadFull(r, br.dst[1:34]); err != nil { + return len(br.dst) + n, Undef, err + } + + br.dst = br.dst[:34] + h, err := mh.Cast(br.dst) + if err != nil { + return len(br.dst), Undef, err + } + + return len(br.dst), Cid{string(h)}, nil + } + + if vers != 1 { + return len(br.dst), Undef, fmt.Errorf("expected 1 as the cid version number, got: %d", vers) + } + + // CID block encoding multicodec. + _, err = varint.ReadUvarint(br) + if err != nil { + return len(br.dst), Undef, err + } + + // We could replace most of the code below with go-multihash's ReadMultihash. + // Note that it would save code, but prevent reusing buffers. + // Plus, we already have a ByteReader now. + mhStart := len(br.dst) + + // Multihash hash function code. + _, err = varint.ReadUvarint(br) + if err != nil { + return len(br.dst), Undef, err + } + + // Multihash digest length. + mhl, err := varint.ReadUvarint(br) + if err != nil { + return len(br.dst), Undef, err + } + + // Refuse to make large allocations to prevent OOMs due to bugs. + const maxDigestAlloc = 32 << 20 // 32MiB + if mhl > maxDigestAlloc { + return len(br.dst), Undef, fmt.Errorf("refusing to allocate %d bytes for a digest", mhl) + } + + // Fine to convert mhl to int, given maxDigestAlloc. + prefixLength := len(br.dst) + cidLength := prefixLength + int(mhl) + if cidLength > cap(br.dst) { + // If the multihash digest doesn't fit in our initial 64 bytes, + // efficiently extend the slice via append+make. + br.dst = append(br.dst, make([]byte, cidLength-len(br.dst))...) + } else { + // The multihash digest fits inside our buffer, + // so just extend its capacity. + br.dst = br.dst[:cidLength] + } + + if n, err := io.ReadFull(r, br.dst[prefixLength:cidLength]); err != nil { + // We can't use len(br.dst) here, + // as we've only read n bytes past prefixLength. + return prefixLength + n, Undef, err + } + + // This simply ensures the multihash is valid. + // TODO: consider removing this bit, as it's probably redundant; + // for now, it helps ensure consistency with CidFromBytes. + _, _, err = mh.MHFromBytes(br.dst[mhStart:]) + if err != nil { + return len(br.dst), Undef, err + } + + return len(br.dst), Cid{string(br.dst)}, nil +} diff --git a/cid_fuzz.go b/cid_fuzz.go index 99842b5350cf7b450d459da43382611d77c71721..0bdd7e677b005b69eca0c74685d8d2e80da3c95c 100644 --- a/cid_fuzz.go +++ b/cid_fuzz.go @@ -4,7 +4,6 @@ package cid func Fuzz(data []byte) int { cid, err := Cast(data) - if err != nil { return 0 } diff --git a/cid_test.go b/cid_test.go index 116e04348dde03eca24395f52f409a9663b99420..b1a798663de126196ff78332fb7535e49bec4c8f 100644 --- a/cid_test.go +++ b/cid_test.go @@ -4,10 +4,12 @@ import ( "bytes" "encoding/json" "fmt" + "io" "math/rand" "reflect" "strings" "testing" + "testing/iotest" mbase "github.com/multiformats/go-multibase" mh "github.com/multiformats/go-multihash" @@ -82,7 +84,7 @@ func TestPrefixSum(t *testing.T) { // Test creating CIDs both manually and with Prefix. // Tests: https://gitlab.dms3.io/dms3/go-cid/issues/83 for _, hashfun := range []uint64{ - mh.ID, mh.SHA3, mh.SHA2_256, + mh.IDENTITY, mh.SHA3, mh.SHA2_256, } { h1, err := mh.Sum([]byte("TEST"), hashfun, -1) if err != nil { @@ -388,7 +390,6 @@ func TestNewPrefixV0(t *testing.T) { if c1.Prefix() != c2.Prefix() { t.Fatal("prefixes mismatch") } - } func TestInvalidV0Prefix(t *testing.T) { @@ -666,6 +667,7 @@ func TestReadCidsFromBuffer(t *testing.T) { "k2cwueckqkibutvhkr4p2ln2pjcaxaakpd9db0e7j7ax1lxhhxy3ekpv", "Qmf5Qzp6nGBku7CEn2UQx4mgN8TW69YUok36DrGa6NN893", "zb2rhZi1JR4eNc2jBGaRYJKYM8JEB4ovenym8L1CmFsRAytkz", + "bafkqarjpmzuwyzltorxxezjpkvcfgqkfjfbfcvslivje2vchkzdu6rckjjcfgtkolaze6mssjqzeyn2ekrcfatkjku2vowseky3fswkfkm2deqkrju3e2", } var cids []Cid @@ -693,51 +695,98 @@ func TestReadCidsFromBuffer(t *testing.T) { if cur != len(buf) { t.Fatal("had trailing bytes") } -} -func TestBadCidFromBytes(t *testing.T) { - l, c, err := CidFromBytes([]byte{mh.SHA2_256, 32, 0x00}) - if err == nil { - t.Fatal("expected not-enough-bytes for V0 CidFromBytes") - } - if l != 0 { - t.Fatal("expected length=0 from bad CidFromBytes") - } - if c != Undef { - t.Fatal("expected Undef CID from bad CidFromBytes") - } + // The same, but now with CidFromReader. + // In multiple forms, to catch more io interface bugs. + for _, r := range []io.Reader{ + // implements io.ByteReader + bytes.NewReader(buf), - c, err = Decode("bafkreie5qrjvaw64n4tjm6hbnm7fnqvcssfed4whsjqxzslbd3jwhsk3mm") - if err != nil { - t.Fatal(err) - } - byts := make([]byte, c.ByteLen()) - copy(byts, c.Bytes()) - byts[1] = 0x80 // bad codec varint - byts[2] = 0x00 - l, c, err = CidFromBytes(byts) - if err == nil { - t.Fatal("expected not-enough-bytes for V1 CidFromBytes") - } - if l != 0 { - t.Fatal("expected length=0 from bad CidFromBytes") - } - if c != Undef { - t.Fatal("expected Undef CID from bad CidFromBytes") + // tiny reads, no io.ByteReader + iotest.OneByteReader(bytes.NewReader(buf)), + } { + cur = 0 + for _, expc := range cids { + n, c, err := CidFromReader(r) + if err != nil { + t.Fatal(err) + } + if c != expc { + t.Fatal("cids mismatched") + } + cur += n + } + if cur != len(buf) { + t.Fatal("had trailing bytes") + } } +} - copy(byts, c.Bytes()) - byts[2] = 0x80 // bad multihash varint - byts[3] = 0x00 - l, c, err = CidFromBytes(byts) - if err == nil { - t.Fatal("expected not-enough-bytes for V1 CidFromBytes") - } - if l != 0 { - t.Fatal("expected length=0 from bad CidFromBytes") - } - if c != Undef { - t.Fatal("expected Undef CID from bad CidFromBytes") +func TestBadCidInput(t *testing.T) { + for _, name := range []string{ + "FromBytes", + "FromReader", + } { + t.Run(name, func(t *testing.T) { + usingReader := name == "FromReader" + + fromBytes := CidFromBytes + if usingReader { + fromBytes = func(data []byte) (int, Cid, error) { + return CidFromReader(bytes.NewReader(data)) + } + } + + l, c, err := fromBytes([]byte{mh.SHA2_256, 32, 0x00}) + if err == nil { + t.Fatal("expected not-enough-bytes for V0 CID") + } + if !usingReader && l != 0 { + t.Fatal("expected length==0 from bad CID") + } else if usingReader && l == 0 { + t.Fatal("expected length!=0 from bad CID") + } + if c != Undef { + t.Fatal("expected Undef CID from bad CID") + } + + c, err = Decode("bafkreie5qrjvaw64n4tjm6hbnm7fnqvcssfed4whsjqxzslbd3jwhsk3mm") + if err != nil { + t.Fatal(err) + } + byts := make([]byte, c.ByteLen()) + copy(byts, c.Bytes()) + byts[1] = 0x80 // bad codec varint + byts[2] = 0x00 + l, c, err = fromBytes(byts) + if err == nil { + t.Fatal("expected not-enough-bytes for V1 CID") + } + if !usingReader && l != 0 { + t.Fatal("expected length==0 from bad CID") + } else if usingReader && l == 0 { + t.Fatal("expected length!=0 from bad CID") + } + if c != Undef { + t.Fatal("expected Undef CID from bad CID") + } + + copy(byts, c.Bytes()) + byts[2] = 0x80 // bad multihash varint + byts[3] = 0x00 + l, c, err = fromBytes(byts) + if err == nil { + t.Fatal("expected not-enough-bytes for V1 CID") + } + if !usingReader && l != 0 { + t.Fatal("expected length==0 from bad CID") + } else if usingReader && l == 0 { + t.Fatal("expected length!=0 from bad CID") + } + if c != Undef { + t.Fatal("expected Undef CID from bad CidFromBytes") + } + }) } } diff --git a/go.mod b/go.mod index 66eec61e72a90d306e4dd8654004702aa71eb5c0..6d42fc6beb2851697b48285cd5488667e22c3125 100644 --- a/go.mod +++ b/go.mod @@ -2,8 +2,9 @@ module gitlab.dms3.io/dms3/go-cid require ( github.com/multiformats/go-multibase v0.0.3 - github.com/multiformats/go-multihash v0.0.14 + github.com/multiformats/go-multihash v0.0.15 github.com/multiformats/go-varint v0.0.6 + golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf // indirect ) go 1.15 diff --git a/go.sum b/go.sum index 01cb5f4b11272d00a88257c5d5cb7a39c265bfe0..b589aef632f80d4ffa439034507bff6748fee3b3 100644 --- a/go.sum +++ b/go.sum @@ -1,30 +1,35 @@ +github.com/klauspost/cpuid/v2 v2.0.4 h1:g0I61F2K2DjRHz1cnxlkNSBIaePVoJIjjnHui8QHbiw= +github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= -github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771 h1:MHkK1uRtFbVqvAgvWxafZe54+5uBxLluGylDiKgdhwo= -github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= -github.com/mr-tron/base58 v1.1.0 h1:Y51FGVJ91WBqCEabAi5OPUz38eAx8DakuAm5svLcsfQ= +github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= +github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= -github.com/mr-tron/base58 v1.1.3 h1:v+sk57XuaCKGXpWtVBX8YJzO7hMGx4Aajh4TQbdEFdc= -github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4= github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= github.com/multiformats/go-multibase v0.0.3 h1:l/B6bJDQjvQ5G52jw4QGSYeOTZoAwIO77RblWplfIqk= github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= -github.com/multiformats/go-multihash v0.0.14 h1:QoBceQYQQtNUuf6s7wHxnE2c8bhbMqhfGzNI032se/I= -github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= -github.com/multiformats/go-varint v0.0.5 h1:XVZwSo04Cs3j/jS0uAEPpT3JY6DzMcVLLoWOSnCxOjg= -github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-multihash v0.0.15 h1:hWOPdrNqDjwHDx82vsYGSDZNyktOJJ2dzZJzFkOV1jM= +github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg= github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= -github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf h1:B2n+Zi5QeYRDAEodEu72OS36gmTWjgpXr2+cWcBW90o= +golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210309074719-68d13333faf2 h1:46ULzRKLh1CwgRq2dC5SlBzEqqNCi8rreOZnNrbqcIY= +golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=