diff --git a/.gemini/config.yaml b/.gemini/config.yaml deleted file mode 100644 index 9b4e971..0000000 --- a/.gemini/config.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# Config for the Gemini Pull Request Review Bot. -# https://github.com/marketplace/gemini-code-assist -have_fun: false -code_review: - disable: false - comment_severity_threshold: MEDIUM - max_review_comments: -1 - pull_request_opened: - help: false - summary: true - code_review: true -ignore_patterns: [] diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml deleted file mode 100644 index ebe85a6..0000000 --- a/.github/workflows/docker.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Docker image build - -on: - push: - tags: - - 'v*' - -defaults: - run: - shell: bash - -jobs: - main: - runs-on: ubuntu-latest - steps: - - name: Set up QEMU - uses: lightninglabs/gh-actions/setup-qemu-action@2021.01.25.00 - - - name: Set up Docker buildx - uses: lightninglabs/gh-actions/setup-buildx-action@2021.01.25.00 - - - name: Login to DockerHub - uses: lightninglabs/gh-actions/login-action@2021.01.25.00 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_API_KEY }} - - - name: Set env - run: | - echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV - DOCKER_REPO_DEFAULT=${{secrets.DOCKER_REPO}} - echo "DOCKER_REPO=${DOCKER_REPO_DEFAULT:-lightninglabs/faraday}" >> $GITHUB_ENV - - - name: Build and push image - id: docker_build - uses: lightninglabs/gh-actions/build-push-action@2021.01.25.00 - with: - push: true - platforms: linux/amd64,linux/arm64 - tags: "${{ env.DOCKER_REPO }}:${{ env.RELEASE_VERSION }}" - build-args: checkout=${{ env.RELEASE_VERSION }} - - - name: Image digest - run: echo ${{ steps.docker_build.outputs.digest }} \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index eeeb9cc..d69252d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,7 +21,7 @@ env: # /Dockerfile # /frdrpc/Dockerfile # /itest/Dockerfile - GO_VERSION: 1.25.10 + GO_VERSION: 1.19.4 jobs: ######################## @@ -50,28 +50,10 @@ jobs: - name: run imports check run: make fmt - + - name: run JS stubs check run: make rpc-js-compile - ####################### - # sql model generation - ####################### - sqlc-check: - name: Sqlc check - runs-on: ubuntu-latest - steps: - - name: git checkout - uses: actions/checkout@v2 - - - name: setup go ${{ env.GO_VERSION }} - uses: actions/setup-go@v2 - with: - go-version: '${{ env.GO_VERSION }}' - - - name: Generate sql models - run: make sqlc-check - ######################## # lint code ######################## @@ -104,10 +86,8 @@ jobs: fail-fast: false matrix: unit_type: - - unit-race - unit - - unit dbbackend=postgres - - unit dbbackend=sqlite + - unit-race - itest steps: - name: git checkout diff --git a/.golangci.yml b/.golangci.yml index fa1de72..9f6d004 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,29 +1,27 @@ run: # timeout for analysis - timeout: 4m + deadline: 4m linters-settings: + govet: + # Don't report about shadowed variables + check-shadowing: false gofmt: # simplify code: gofmt with `-s` option, true by default simplify: true - tagliatelle: case: rules: json: snake - whitespace: multi-func: true multi-if: true - gosec: excludes: - G402 # Look for bad TLS connection settings. - G306 # Poor file permissions used when writing to a new file. - - G601 # Implicit memory aliasing in for loop. - - G115 # Integer overflow in conversion. - staticcheck: + go: "1.18" checks: ["-SA1019"] linters: diff --git a/Dockerfile b/Dockerfile index 37e4888..a2ecf1e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.25.10-alpine as builder +FROM golang:1.18.8-alpine as builder # Force Go to use the cgo based DNS resolver. This is required to ensure DNS # queries required to connect to linked containers succeed. @@ -11,9 +11,9 @@ RUN apk add --no-cache --update alpine-sdk \ git \ make \ gcc \ - && cd /go/src/github.com/lightninglabs/faraday \ - && make \ - && make install +&& cd /go/src/github.com/lightninglabs/faraday \ +&& make \ +&& make install # Start a new, final image. FROM alpine as final diff --git a/Makefile b/Makefile index 2c78e97..1e6d5fd 100644 --- a/Makefile +++ b/Makefile @@ -27,11 +27,8 @@ XARGS := xargs -L 1 include make/testing_flags.mk -DOCKER_TOOLS = docker run \ - -v $(shell bash -c "go env GOCACHE || (mkdir -p /tmp/go-cache; echo /tmp/go-cache)"):/tmp/build/.cache \ - -v $(shell bash -c "go env GOMODCACHE || (mkdir -p /tmp/go-modcache; echo /tmp/go-modcache)"):/tmp/build/.modcache \ - -v $(shell bash -c "mkdir -p /tmp/go-lint-cache; echo /tmp/go-lint-cache"):/root/.cache/golangci-lint \ - -v $$(pwd):/build faraday-tools +LINT = $(LINT_BIN) run -v +DOCKER_TOOLS = docker run -v $$(pwd):/build faraday-tools default: scratch @@ -137,14 +134,6 @@ rpc-js-compile: @$(call print, "Compiling JSON/WASM stubs.") GOOS=js GOARCH=wasm $(GOBUILD) $(PKG)/frdrpc -sqlc: - @$(call print, "Generating sql models and queries in Go") - ./scripts/gen_sqlc_docker.sh - -sqlc-check: sqlc - @$(call print, "Verifying sql code generation.") - if test -n "$$(git status --porcelain '*.go')"; then echo "SQL models not properly generated!"; git status --porcelain '*.go'; exit 1; fi - list: @$(call print, "Listing commands.") @$(MAKE) -qp | \ diff --git a/README.md b/README.md index d6dd807..0bca937 100644 --- a/README.md +++ b/README.md @@ -94,42 +94,6 @@ Faraday serves requests over grpc by default on `localhost:8465`. This default c --rpclisten={host:port to listen for requests} ``` -#### Channel Event Storage -Faraday records channel events (online/offline transitions and balance updates) -in its database. On high-frequency channels this table can grow without bound, -so a size ceiling is enabled by default, with an optional age-based retention -window: -```text ---chanevents.max-events={maximum number of events to retain} ---chanevents.retention={minimum duration of events to keep, e.g. 1440h} -``` -By default only the size ceiling is active: a maximum of 7 million events -(`--chanevents.max-events=7000000`, roughly 1 GB of storage). Age-based -retention is disabled by default (`--chanevents.retention=0`) so that history is -never aged out unless an operator opts in. The retention window is a Go duration -string (e.g. `1440h` for 60 days). The two limits are applied independently: - -1. **Size Ceiling (Hard Limit):** If the database exceeds `max-events`, older - events are pruned unconditionally to ensure the database size is strictly - capped, preventing disk filling. Newer events inside the retention window can - still be pruned if needed to satisfy this size limit. -2. **Age Threshold (Freshness):** When `retention` is set to a non-zero - duration, any events older than that window are automatically pruned to keep - history fresh, even if the database size is below `max-events`. - -Because the two limits are independent, disabling pruning entirely requires -turning off both: `--chanevents.max-events=0 --chanevents.retention=0`. Setting -only `max-events=0` disables the size ceiling, leaving the table bounded only by -any retention window that has been configured. - -As a rough rule of thumb, each channel event consumes on the order of 140 bytes -of storage once table and index overhead is taken into account. The default -`--chanevents.max-events=7000000` therefore bounds the table at roughly 1 GB -(7 million events × ~140 bytes ≈ 1 GB). For roughly 100 MB use -`--chanevents.max-events=700000`. These are approximations measured on a -compacted SQLite database, and actual usage runs higher on a live database -(write-ahead log, page fragmentation) and varies by backend. - #### Cli Tool The RPC server can be conveniently accessed using a command line tool. 1. Run faraday as detailed above diff --git a/accounting/categories.go b/accounting/categories.go index c2dbffa..6eeee3e 100644 --- a/accounting/categories.go +++ b/accounting/categories.go @@ -1,9 +1,6 @@ package accounting -import ( - "fmt" - "regexp" -) +import "regexp" // CustomCategory describes a custom category which can be used to identify // special case groups of transactions. @@ -27,8 +24,7 @@ func NewCustomCategory(name string, regexes []string) (*CustomCategory, error) { for _, regex := range regexes { exp, err := regexp.Compile(regex) if err != nil { - return nil, fmt.Errorf("category %v: compiling regex "+ - "%v failed: %w", name, regex, err) + return nil, err } category.Regexes = append(category.Regexes, exp) diff --git a/accounting/config.go b/accounting/config.go index a2ee8ff..37d5265 100644 --- a/accounting/config.go +++ b/accounting/config.go @@ -97,10 +97,8 @@ type CommonConfig struct { // The txLookup function may be nil if a connection to a bitcoin backend is not // available. If this is the case, the fee report will log warnings indicating // that fee lookups are not possible in certain cases. -func NewOnChainConfig(ctx context.Context, - lnd lndclient.LndServices, startTime, endTime time.Time, - blockRangeLookup func(start, end time.Time) (uint32, uint32, error), - disableFiat bool, txLookup fees.GetDetailsFunc, +func NewOnChainConfig(ctx context.Context, lnd lndclient.LndServices, startTime, + endTime time.Time, disableFiat bool, txLookup fees.GetDetailsFunc, priceCfg *fiat.PriceSourceConfig, categories []CustomCategory) *OnChainConfig { @@ -111,29 +109,6 @@ func NewOnChainConfig(ctx context.Context, } } - // Set both start and end height to 0, meaning we will query for all - // onchain history. - startHeight := uint32(0) - endHeight := uint32(0) - - if blockRangeLookup != nil { - var err error - - startHeight, endHeight, err = blockRangeLookup(startTime, endTime) - if err != nil { - log.Errorf("Error finding block height range for start time: %v "+ - "end time: %v error: %v", startTime, endTime, err) - - // If we cannot find the block height range, set both start and end - // height to 0, meaning we will query for all onchain history. - startHeight = 0 - endHeight = 0 - } - } - - log.Debugf("Using startheight: %v endheight: %v while querying onchain "+ - "activity", startHeight, endHeight) - return &OnChainConfig{ OpenChannels: lndwrap.ListChannels( ctx, lnd.Client, false, @@ -145,12 +120,10 @@ func NewOnChainConfig(ctx context.Context, return lnd.Client.PendingChannels(ctx) }, OnChainTransactions: func() ([]lndclient.Transaction, error) { - return lnd.Client.ListTransactions( - ctx, int32(startHeight), int32(endHeight), - ) + return lnd.Client.ListTransactions(ctx, 0, 0) }, ListSweeps: func() ([]string, error) { - return lnd.WalletKit.ListSweeps(ctx, int32(startHeight)) + return lnd.WalletKit.ListSweeps(ctx) }, CommonConfig: CommonConfig{ StartTime: startTime, diff --git a/accounting/conversions.go b/accounting/conversions.go index 04ae995..8e882dc 100644 --- a/accounting/conversions.go +++ b/accounting/conversions.go @@ -2,7 +2,6 @@ package accounting import ( "context" - "fmt" "time" "github.com/btcsuite/btcd/btcutil" @@ -45,18 +44,12 @@ func getConversion(ctx context.Context, startTime, endTime time.Time, err := utils.ValidateTimeRange(startTime, endTime) if err != nil { - return nil, fmt.Errorf("conversion: invalid time range [%v,%v): %w", - startTime, endTime, err) + return nil, err } fiatClient, err := fiat.NewPriceSource(priceCfg) if err != nil { - backend := "" - if priceCfg != nil { - backend = priceCfg.Backend.String() - } - return nil, fmt.Errorf("conversion: initialising price "+ - "source backend %v failed: %w", backend, err) + return nil, err } // Get price data for our relevant period. We get pricing for the whole @@ -64,19 +57,12 @@ func getConversion(ctx context.Context, startTime, endTime time.Time, // calls we need to make to our external data source. prices, err := fiatClient.GetPrices(ctx, startTime, endTime) if err != nil { - return nil, fmt.Errorf("conversion: fetching prices for "+ - "range [%v,%v) failed: %w", startTime, endTime, err) + return nil, err } // Create a wrapper function which can be used to get individual price // points from our set of price data as we create our report. return func(ts time.Time) (*fiat.Price, error) { - price, err := fiat.GetPrice(prices, ts) - if err != nil { - return nil, fmt.Errorf("conversion: fetching price "+ - "at %v failed: %w", ts, err) - } - - return price, nil + return fiat.GetPrice(prices, ts) }, nil } diff --git a/accounting/entries.go b/accounting/entries.go index d944d64..988cad3 100644 --- a/accounting/entries.go +++ b/accounting/entries.go @@ -80,8 +80,7 @@ func channelOpenEntries(channel channelInfo, tx lndclient.Transaction, true, u.getFiat, ) if err != nil { - return nil, fmt.Errorf("tx %v channel %v: creating open entry "+ - "failed: %w", tx.TxHash, channel.channelID, err) + return nil, err } // If we did not initiate opening the channel, we can just return the @@ -102,9 +101,7 @@ func channelOpenEntries(channel channelInfo, tx lndclient.Transaction, FeeReference(tx.TxHash), note, category, true, u.getFiat, ) if err != nil { - return nil, fmt.Errorf("tx %v channel %v: creating channel "+ - "open fee entry failed: %w", tx.TxHash, - channel.channelID, err) + return nil, err } return []*HarmonyEntry{openEntry, feeEntry}, nil @@ -138,9 +135,7 @@ func closedChannelEntries(channel closedChannelInfo, tx lndclient.Transaction, tx.TxHash, note, category, true, u.getFiat, ) if err != nil { - return nil, fmt.Errorf("tx %v channel %v: creating channel "+ - "close entry failed: %w", tx.TxHash, channel.channelID, - err) + return nil, err } switch channel.initiator { @@ -177,9 +172,7 @@ func closedChannelEntries(channel closedChannelInfo, tx lndclient.Transaction, fees, err := u.getFee(tx.Tx.TxHash()) if err != nil { - return nil, fmt.Errorf("tx %v channel %v: fetching on-chain "+ - "close fees failed: %w", tx.TxHash, channel.channelID, - err) + return nil, err } // Our fees are provided as a positive amount in sats. Convert this to @@ -192,9 +185,7 @@ func closedChannelEntries(channel closedChannelInfo, tx lndclient.Transaction, true, u.getFiat, ) if err != nil { - return nil, fmt.Errorf("tx %v channel %v: creating channel "+ - "close fee entry failed: %w", tx.TxHash, - channel.channelID, err) + return nil, err } return []*HarmonyEntry{closeEntry, feeEntry}, nil @@ -210,8 +201,7 @@ func sweepEntries(tx lndclient.Transaction, u entryUtils) ([]*HarmonyEntry, erro tx.TxHash, tx.Label, category, true, u.getFiat, ) if err != nil { - return nil, fmt.Errorf("tx %v: creating sweep entry failed: %w", - tx.TxHash, err) + return nil, err } // If we do not have a fee lookup function set, we log a warning that @@ -226,8 +216,7 @@ func sweepEntries(tx lndclient.Transaction, u entryUtils) ([]*HarmonyEntry, erro fee, err := u.getFee(tx.Tx.TxHash()) if err != nil { - return nil, fmt.Errorf("tx %v: fetching sweep fee failed: %w", - tx.TxHash, err) + return nil, err } feeEntry, err := newHarmonyEntry( @@ -236,70 +225,21 @@ func sweepEntries(tx lndclient.Transaction, u entryUtils) ([]*HarmonyEntry, erro u.getFiat, ) if err != nil { - return nil, fmt.Errorf("tx %v: creating sweep fee entry "+ - "failed: %w", tx.TxHash, err) + return nil, err } return []*HarmonyEntry{txEntry, feeEntry}, nil } -// isUtxoManagementTx checks whether a transaction is restructuring our utxos. -func isUtxoManagementTx(txn lndclient.Transaction) bool { - // Check all inputs. - for _, input := range txn.PreviousOutpoints { - if !input.IsOurOutput { - return false - } - } - - // Check all outputs. - for _, output := range txn.OutputDetails { - if !output.IsOurAddress { - return false - } - } - - // If all inputs and outputs belong to our wallet, it's utxo management. - return true -} - -// createOnchainFeeEntry creates a fee entry for an on chain transaction. -func createOnchainFeeEntry(tx lndclient.Transaction, category string, - note string, u entryUtils) (*HarmonyEntry, error) { - - // Total fees are expressed as a positive value in sats, we convert to - // msat here and make the value negative so that it reflects as a - // debit. - feeAmt := invertedSatsToMsats(tx.Fee) - - feeEntry, err := newHarmonyEntry( - tx.Timestamp, feeAmt, EntryTypeFee, - tx.TxHash, FeeReference(tx.TxHash), note, category, true, - u.getFiat, - ) - - if err != nil { - return nil, fmt.Errorf("tx %v: creating on-chain fee entry "+ - "failed: %w", tx.TxHash, err) - } - - return feeEntry, nil -} - -// utxoManagementFeeNote creates a note for utxo management fee types. -func utxoManagementFeeNote(txid string) string { - return fmt.Sprintf("fees for utxo management transaction: %v", txid) -} - // onChainEntries produces relevant entries for an on chain transaction. func onChainEntries(tx lndclient.Transaction, u entryUtils) ([]*HarmonyEntry, error) { var ( - amtMsat = satsToMsat(tx.Amount) - entryType EntryType - category = getCategory(tx.Label, u.customCategories) - utxoManagement bool + amtMsat = satsToMsat(tx.Amount) + entryType EntryType + feeType = EntryTypeFee + category = getCategory(tx.Label, u.customCategories) ) // Determine the type of entry we are creating. If this is a sweep, we @@ -312,9 +252,6 @@ func onChainEntries(tx lndclient.Transaction, case amtMsat > 0: entryType = EntryTypeReceipt - case isUtxoManagementTx(tx): - utxoManagement = true - // If we have a zero amount on chain transaction, we do not create an // entry for it. This may happen when the remote party claims a htlc on // our commitment. We do not want to report 0 value transactions that @@ -323,26 +260,12 @@ func onChainEntries(tx lndclient.Transaction, return nil, nil } - // If this is a utxo management transaction, we return a fee entry only. - if utxoManagement { - note := utxoManagementFeeNote(tx.TxHash) - feeEntry, err := createOnchainFeeEntry(tx, category, note, u) - if err != nil { - return nil, fmt.Errorf("tx %v: creating utxo "+ - "management fee entry failed: %w", tx.TxHash, - err) - } - - return []*HarmonyEntry{feeEntry}, nil - } - txEntry, err := newHarmonyEntry( tx.Timestamp, amtMsat, entryType, tx.TxHash, tx.TxHash, tx.Label, category, true, u.getFiat, ) if err != nil { - return nil, fmt.Errorf("tx %v: creating on-chain transaction "+ - "entry failed: %w", tx.TxHash, err) + return nil, err } // If we did not pay any fees, we can just return a single entry. @@ -350,10 +273,17 @@ func onChainEntries(tx lndclient.Transaction, return []*HarmonyEntry{txEntry}, nil } - feeEntry, err := createOnchainFeeEntry(tx, category, "", u) + // Total fees are expressed as a positive value in sats, we convert to + // msat here and make the value negative so that it reflects as a + // debit. + feeAmt := invertedSatsToMsats(tx.Fee) + + feeEntry, err := newHarmonyEntry( + tx.Timestamp, feeAmt, feeType, tx.TxHash, + FeeReference(tx.TxHash), "", category, true, u.getFiat, + ) if err != nil { - return nil, fmt.Errorf("tx %v: creating on-chain fee entry "+ - "failed: %w", tx.TxHash, err) + return nil, err } return []*HarmonyEntry{txEntry, feeEntry}, nil @@ -418,18 +348,11 @@ func paymentReference(sequenceNumber uint64, preimage lntypes.Preimage) string { // paymentNote creates a note for payments from our node. // nolint: interfacer -func paymentNote(dest *route.Vertex, memo *string) string { - var notes []string - - if memo != nil && *memo != "" { - notes = append(notes, fmt.Sprintf("memo: %v", *memo)) +func paymentNote(dest *route.Vertex) string { + if dest == nil { + return "" } - - if dest != nil { - notes = append(notes, fmt.Sprintf("destination: %v", dest)) - } - - return strings.Join(notes, "/") + return dest.String() } // paymentEntry creates an entry for an off chain payment, including fee entries @@ -456,7 +379,7 @@ func paymentEntry(payment paymentInfo, paidToSelf bool, // Create a note for our payment. Since we have already checked that our // payment is settled, we will not have a nil preimage. - note := paymentNote(payment.destination, payment.description) + note := paymentNote(payment.destination) ref := paymentReference(payment.SequenceNumber, *payment.Preimage) // Payment values are expressed as positive values over rpc, but they @@ -468,8 +391,7 @@ func paymentEntry(payment paymentInfo, paidToSelf bool, ref, note, "", false, u.getFiat, ) if err != nil { - return nil, fmt.Errorf("payment %v: creating payment entry "+ - "failed: %w", payment.Hash, err) + return nil, err } // If we paid no fees (possible for payments to our direct peer), then @@ -486,8 +408,7 @@ func paymentEntry(payment paymentInfo, paidToSelf bool, feeRef, note, "", false, u.getFiat, ) if err != nil { - return nil, fmt.Errorf("payment %v: creating payment fee "+ - "entry failed: %w", payment.Hash, err) + return nil, err } return []*HarmonyEntry{paymentEntry, feeEntry}, nil } @@ -521,8 +442,7 @@ func forwardingEntry(forward lndclient.ForwardingEvent, false, u.getFiat, ) if err != nil { - return nil, fmt.Errorf("forward %v: creating forwarding "+ - "entry failed: %w", txid, err) + return nil, err } // If we did not earn any fees, return the forwarding entry. @@ -535,8 +455,7 @@ func forwardingEntry(forward lndclient.ForwardingEvent, EntryTypeForwardFee, txid, "", "", "", false, u.getFiat, ) if err != nil { - return nil, fmt.Errorf("forward %v: creating forwarding fee "+ - "entry failed: %w", txid, err) + return nil, err } return []*HarmonyEntry{fwdEntry, feeEntry}, nil diff --git a/accounting/entries_test.go b/accounting/entries_test.go index 459c439..c96e4fd 100644 --- a/accounting/entries_test.go +++ b/accounting/entries_test.go @@ -83,6 +83,10 @@ var ( Tx: &wire.MsgTx{}, } + paymentRequest = "lnbcrt10n1p0t6nmypp547evsfyrakg0nmyw59ud9cegkt99yccn5nnp4suq3ac4qyzzgevsdqqcqzpgsp54hvffpajcyddm20k3ptu53930425hpnv8m06nh5jrd6qhq53anrq9qy9qsqphhzyenspf7kfwvm3wyu04fa8cjkmvndyexlnrmh52huwa4tntppjmak703gfln76rvswmsx2cz3utsypzfx40dltesy8nj64ttgemgqtwfnj9" + + invoiceMemo = "memo" + invoiceAmt = lnwire.MilliSatoshi(300) invoiceOverpaidAmt = lnwire.MilliSatoshi(400) @@ -108,7 +112,7 @@ var ( paymentTime = time.Unix(1590399649, 0) - paymentHash = "0001020304050607080900010203040506070809000102030405060708090102" + paymentHash = "11f414479f0a0c2762492c71c58dded5dce99d56d65c3fa523f73513605bebb3" pmtHash, _ = lntypes.MakeHashFromStr(paymentHash) paymentPreimage = "adfef20b24152accd4ed9a05257fb77203d90a8bbbe6d4069a75c5320f0538d9" @@ -130,13 +134,11 @@ var ( Fee: lnwire.MilliSatoshi(paymentFeeMsat), Htlcs: []*lnrpc.HTLCAttempt{{}}, SequenceNumber: uint64(paymentIndex), - PaymentRequest: paymentRequest, } payInfo = paymentInfo{ Payment: payment, destination: &otherPubkey, - description: &invoiceMemo, settleTime: paymentTime, } @@ -499,13 +501,12 @@ func TestSweepEntry(t *testing.T) { // TestOnChainEntry tests creation of entries for receipts and payments, and the // generation of a fee entry where applicable. func TestOnChainEntry(t *testing.T) { - getOnChainEntry := func(amount btcutil.Amount, hasFee bool, - isUtxoManagement bool, label string, note string) []*HarmonyEntry { + getOnChainEntry := func(amount btcutil.Amount, + hasFee bool, label string) []*HarmonyEntry { var ( - entryType EntryType - feeType = EntryTypeFee - utxoManagement bool + entryType EntryType + feeType = EntryTypeFee ) switch { @@ -515,33 +516,10 @@ func TestOnChainEntry(t *testing.T) { case amount > 0: entryType = EntryTypeReceipt - case isUtxoManagement: - utxoManagement = true - default: return nil } - if utxoManagement { - feeAmt := satsToMsat(onChainFeeSat) - feeMsat := lnwire.MilliSatoshi(feeAmt) - - feeEntry := &HarmonyEntry{ - Timestamp: onChainTimestamp, - Amount: feeMsat, - FiatValue: fiat.MsatToFiat(mockBTCPrice.Price, feeMsat), - TxID: onChainTxID, - Reference: FeeReference(onChainTxID), - Note: note, - Type: feeType, - OnChain: true, - Credit: false, - BTCPrice: mockBTCPrice, - } - - return []*HarmonyEntry{feeEntry} - } - amt := satsToMsat(onChainAmtSat) amtMsat := lnwire.MilliSatoshi(amt) entry := &HarmonyEntry{ @@ -571,7 +549,7 @@ func TestOnChainEntry(t *testing.T) { FiatValue: fiat.MsatToFiat(mockBTCPrice.Price, feeMsat), TxID: onChainTxID, Reference: FeeReference(onChainTxID), - Note: note, + Note: "", Type: feeType, OnChain: true, Credit: false, @@ -591,14 +569,8 @@ func TestOnChainEntry(t *testing.T) { // Whether the transaction has a fee attached. hasFee bool - // Whether the transaction is a sweep. - isUtxoManagement bool - // txLabel is an optional label on the rpc transaction. txLabel string - - // Note is the expected note on the entry. - note string }{ { name: "receive with fee", @@ -625,13 +597,6 @@ func TestOnChainEntry(t *testing.T) { amount: 0, hasFee: false, }, - { - name: "zero amount utxo management tx", - amount: 0, - hasFee: true, - isUtxoManagement: true, - note: utxoManagementFeeNote(onChainTxID), - }, } for _, test := range tests { @@ -650,13 +615,6 @@ func TestOnChainEntry(t *testing.T) { chainTx.Fee = 0 } - chainTx.PreviousOutpoints = []*lnrpc.PreviousOutPoint{{ - IsOurOutput: test.isUtxoManagement, - }} - chainTx.OutputDetails = []*lnrpc.OutputDetail{{ - IsOurAddress: test.isUtxoManagement, - }} - // Set the label as per the test. chainTx.Label = test.txLabel @@ -666,7 +624,7 @@ func TestOnChainEntry(t *testing.T) { // Create the entries we expect based on the test // params. expected := getOnChainEntry( - test.amount, test.hasFee, test.isUtxoManagement, test.txLabel, test.note, + test.amount, test.hasFee, test.txLabel, ) require.Equal(t, expected, entries) @@ -756,7 +714,7 @@ func TestPaymentEntry(t *testing.T) { FiatValue: fiat.MsatToFiat(mockBTCPrice.Price, amtMsat), TxID: paymentHash, Reference: paymentRef, - Note: paymentNote(&otherPubkey, &invoiceMemo), + Note: paymentNote(&otherPubkey), Type: EntryTypePayment, OnChain: false, Credit: false, @@ -771,7 +729,7 @@ func TestPaymentEntry(t *testing.T) { FiatValue: fiat.MsatToFiat(mockBTCPrice.Price, feeMsat), TxID: paymentHash, Reference: FeeReference(paymentRef), - Note: paymentNote(&otherPubkey, &invoiceMemo), + Note: paymentNote(&otherPubkey), Type: EntryTypeFee, OnChain: false, Credit: false, diff --git a/accounting/filter.go b/accounting/filter.go index 3bc585c..90f48e5 100644 --- a/accounting/filter.go +++ b/accounting/filter.go @@ -109,16 +109,15 @@ func filterInvoices(startTime, endTime time.Time, return filtered } -// paymentInfo wraps a lndclient payment struct with a destination, and -// description if available from the information we have available, and its -// settle time. Since we now allow multi-path payments, a single payment may -// have multiple htlcs resolved over a period of time. We use the most recent -// settle time for payment because payments are not considered settled until -// all the htlcs are resolved. +// paymentInfo wraps a lndclient payment struct with a destination, if it is +// available from the information we have available, and its settle time. +// Since we now allow multi-path payments, a single payment may have multiple +// htlcs resolved over a period of time. We use the most recent settle time for +// payment because payments are not considered settled until all the htlcs are +// resolved. type paymentInfo struct { lndclient.Payment destination *route.Vertex - description *string settleTime time.Time } @@ -136,33 +135,24 @@ func preProcessPayments(payments []lndclient.Payment, paymentList := make([]paymentInfo, len(payments)) for i, payment := range payments { - // Attempt to obtain the payment destination and description - // from our payment request. If this is not possible (which - // can be the case for legacy payments that did not store - // payment requests, or payments that pay directly to a - // payment hash), then try to get it from our HTLCs. Note - // that HTLCs may also not be available for legacy payments - // that did not store HTLCs. In the event that we get a - // destination from both sources, we prefer the destination - // from the HTLCs. - payReqDestination, description, err := paymentRequestDetails( - payment.PaymentRequest, decode, - ) - if err != nil && err != errNoPaymentRequest { - return nil, fmt.Errorf("payment %v: retrieving "+ - "payment request details failed: %w", - payment.Hash, err) - } - + // Try to get our payment destination from our set of htlcs. + // If we cannot get it from our htlcs (which is the case for + // legacy payments that did not store htlcs), we try to get it + // from our payment request. This value may not be present for + // all payments, so we do not error if it is not. destination, err := paymentHtlcDestination(payment) if err != nil { - destination = payReqDestination + destination, err = paymentRequestDestination( + payment.PaymentRequest, decode, + ) + if err != nil && err != errNoPaymentRequest { + return nil, err + } } pmt := paymentInfo{ Payment: payment, destination: destination, - description: description, } // If the payment did not succeed, we can add it to our list @@ -216,31 +206,27 @@ func paymentHtlcDestination(payment lndclient.Payment) (*route.Vertex, error) { lastHop := hops[len(hops)-1] lastHopPubkey, err := route.NewVertexFromStr(lastHop.PubKey) if err != nil { - return nil, fmt.Errorf("payment %v: parsing last hop "+ - "pubkey %v failed: %w", payment.Hash, lastHop.PubKey, - err) + return nil, err } return &lastHopPubkey, nil } -// paymentRequestDetails attempts to decode a payment address, and returns -// the destination and the description. -func paymentRequestDetails(paymentRequest string, - decode decodePaymentRequest) (*route.Vertex, *string, error) { +// paymentRequestDestination attempts to decode a payment address, and returns +// the destination. +func paymentRequestDestination(paymentRequest string, + decode decodePaymentRequest) (*route.Vertex, error) { if paymentRequest == "" { - return nil, nil, errNoPaymentRequest + return nil, errNoPaymentRequest } payReq, err := decode(paymentRequest) if err != nil { - return nil, nil, fmt.Errorf( - "decode payment request failed: %w", err, - ) + return nil, fmt.Errorf("decode payment request failed: %w", err) } - return &payReq.Destination, &payReq.Description, nil + return &payReq.Destination, nil } // filterPayments filters out unsuccessful payments and those which did not diff --git a/accounting/filter_test.go b/accounting/filter_test.go index 77b274b..c406fbb 100644 --- a/accounting/filter_test.go +++ b/accounting/filter_test.go @@ -378,7 +378,6 @@ func decode(toSelf bool) func(_ string) (*lndclient.PaymentRequest, return &lndclient.PaymentRequest{ Destination: pubkey, - Description: invoiceMemo, }, nil } } @@ -438,39 +437,35 @@ func TestPaymentHtlcDestination(t *testing.T) { } } -// TestPaymentRequestDestination tests getting of payment details from our +// TestPaymentRequestDestination tests getting of payment destinations from our // payment request. -func TestPaymentRequestDetails(t *testing.T) { +func TestPaymentRequestDestination(t *testing.T) { tests := []struct { name string paymentRequest string decode decodePaymentRequest - destination *route.Vertex - description *string + dest *route.Vertex err error }{ { name: "no payment request", decode: decode(true), paymentRequest: "", - destination: nil, - description: nil, + dest: nil, err: errNoPaymentRequest, }, { name: "to self", decode: decode(true), paymentRequest: paymentRequest, - destination: &ourPubKey, - description: &invoiceMemo, + dest: &ourPubKey, err: nil, }, { name: "not to self", decode: decode(false), paymentRequest: paymentRequest, - destination: &otherPubkey, - description: &invoiceMemo, + dest: &otherPubkey, err: nil, }, } @@ -481,13 +476,11 @@ func TestPaymentRequestDetails(t *testing.T) { t.Run(test.name, func(t *testing.T) { t.Parallel() - destination, description, err := paymentRequestDetails( + dest, err := paymentRequestDestination( test.paymentRequest, test.decode, ) - require.Equal(t, test.err, err) - require.Equal(t, test.destination, destination) - require.Equal(t, test.description, description) + require.Equal(t, test.dest, dest) }) } } diff --git a/accounting/log.go b/accounting/log.go index 06ebe09..3457345 100644 --- a/accounting/log.go +++ b/accounting/log.go @@ -1,7 +1,7 @@ package accounting import ( - "github.com/btcsuite/btclog/v2" + "github.com/btcsuite/btclog" "github.com/lightningnetwork/lnd/build" ) diff --git a/accounting/off_chain.go b/accounting/off_chain.go index 7b55c22..6e72012 100644 --- a/accounting/off_chain.go +++ b/accounting/off_chain.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "errors" - "fmt" "github.com/lightninglabs/lndclient" "github.com/lightningnetwork/lnd/lntypes" @@ -49,9 +48,7 @@ func OffChainReport(ctx context.Context, cfg *OffChainConfig) (Report, error) { cfg.PriceSourceCfg, ) if err != nil { - return nil, fmt.Errorf("off-chain report: init conversion "+ - "lookup for range [%v,%v) failed: %w", cfg.StartTime, - cfg.EndTime, err) + return nil, err } return offChainReportWithPrices(cfg, getPrice) @@ -65,8 +62,7 @@ func offChainReportWithPrices(cfg *OffChainConfig, getPrice fiatPrice) (Report, invoices, err := cfg.ListInvoices() if err != nil { - return nil, fmt.Errorf("off-chain report: listing invoices "+ - "failed: %w", err) + return nil, err } filteredInvoices := filterInvoices(cfg.StartTime, cfg.EndTime, invoices) @@ -75,31 +71,25 @@ func offChainReportWithPrices(cfg *OffChainConfig, getPrice fiatPrice) (Report, payments, err := cfg.ListPayments() if err != nil { - return nil, fmt.Errorf("off-chain report: listing payments "+ - "failed: %w", err) + return nil, err } preProcessed, err := preProcessPayments(payments, cfg.DecodePayReq) if err != nil { - return nil, fmt.Errorf("off-chain report: preprocessing %d "+ - "payments failed: %w", len(payments), err) + return nil, err } // Get a list of all the payments we made to ourselves. paymentsToSelf, err := getCircularPayments(cfg.OwnPubKey, preProcessed) if err != nil { - return nil, fmt.Errorf("off-chain report: identifying "+ - "circular payments for node %v failed: %w", - cfg.OwnPubKey, err) + return nil, err } filteredPayments := filterPayments( cfg.StartTime, cfg.EndTime, preProcessed, ) if err := sanityCheckDuplicates(filteredPayments); err != nil { - return nil, fmt.Errorf("off-chain report: duplicate payment "+ - "hashes detected in range [%v,%v): %w", cfg.StartTime, - cfg.EndTime, err) + return nil, err } log.Infof("Retrieved: %v payments, %v filtered, %v circular", @@ -109,8 +99,7 @@ func offChainReportWithPrices(cfg *OffChainConfig, getPrice fiatPrice) (Report, // are already supplied over the relevant range for our query. forwards, err := cfg.ListForwards() if err != nil { - return nil, fmt.Errorf("off-chain report: listing forwards "+ - "failed: %w", err) + return nil, err } log.Infof("Retrieved: %v forwards", len(forwards)) @@ -144,8 +133,7 @@ func offChainReport(invoices []lndclient.Invoice, payments []paymentInfo, entry, err := invoiceEntry(invoice, toSelf, utils) if err != nil { - return nil, fmt.Errorf("invoice %v: creating entry "+ - "failed: %w", invoice.Hash, err) + return nil, err } reports = append(reports, entry) @@ -158,8 +146,7 @@ func offChainReport(invoices []lndclient.Invoice, payments []paymentInfo, entries, err := paymentEntry(payment, toSelf, utils) if err != nil { - return nil, fmt.Errorf("payment %v: creating entries "+ - "failed: %w", payment.Hash, err) + return nil, err } reports = append(reports, entries...) @@ -168,8 +155,7 @@ func offChainReport(invoices []lndclient.Invoice, payments []paymentInfo, for _, forward := range forwards { entries, err := forwardingEntry(forward, utils) if err != nil { - return nil, fmt.Errorf("forward at %v: creating "+ - "entries failed: %w", forward.Timestamp, err) + return nil, err } reports = append(reports, entries...) diff --git a/accounting/off_chain_test.go b/accounting/off_chain_test.go index 8205869..b7acd95 100644 --- a/accounting/off_chain_test.go +++ b/accounting/off_chain_test.go @@ -24,9 +24,6 @@ var ( paymentHash2 = "a5530c5930b9eb7ea4284bcff39da52c6bca3103fc790749eb632911edc7143b" hash2, _ = lntypes.MakeHashFromStr(paymentHash2) - paymentRequest = "lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpuaztrnwngzn3kdzw5hydlzf03qdgm2hdq27cqv3agm2awhz5se903vruatfhq77w3ls4evs3ch9zw97j25emudupq63nyw24cg27h2rspfj9srp" - invoiceMemo = "1 cup coffee" - hopToUs = &lnrpc.Hop{ PubKey: ourPK, } diff --git a/accounting/on_chain.go b/accounting/on_chain.go index 8ef1bf8..7a1fa0b 100644 --- a/accounting/on_chain.go +++ b/accounting/on_chain.go @@ -2,7 +2,6 @@ package accounting import ( "context" - "fmt" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/wire" @@ -24,15 +23,12 @@ func OnChainReport(ctx context.Context, cfg *OnChainConfig) (Report, error) { cfg.PriceSourceCfg, ) if err != nil { - return nil, fmt.Errorf("on-chain report: init conversion "+ - "lookup for range [%v,%v) failed: %w", cfg.StartTime, - cfg.EndTime, err) + return nil, err } info, err := getOnChainInfo(cfg, getPrice) if err != nil { - return nil, fmt.Errorf("on-chain report: gathering on-chain "+ - "data failed: %w", err) + return nil, err } return onChainReport(info) @@ -97,8 +93,7 @@ func getOnChainInfo(cfg *OnChainConfig, getPrice fiatPrice) (*onChainInformation onChainTxns, err := cfg.OnChainTransactions() if err != nil { - return nil, fmt.Errorf("on-chain report: listing on-chain "+ - "transactions failed: %w", err) + return nil, err } // Filter our on chain transactions by start and end time. If we have @@ -106,9 +101,7 @@ func getOnChainInfo(cfg *OnChainConfig, getPrice fiatPrice) (*onChainInformation // early. info.txns, err = filterOnChain(cfg.StartTime, cfg.EndTime, onChainTxns) if err != nil { - return nil, fmt.Errorf("on-chain report: filtering "+ - "transactions for range [%v,%v) failed: %w", - cfg.StartTime, cfg.EndTime, err) + return nil, err } if len(info.txns) == 0 { @@ -122,8 +115,7 @@ func getOnChainInfo(cfg *OnChainConfig, getPrice fiatPrice) (*onChainInformation // closing channels that are awaiting resolution). pending, err := cfg.PendingChannels() if err != nil { - return nil, fmt.Errorf("on-chain report: listing pending "+ - "channels failed: %w", err) + return nil, err } // We add our pending force close channels to opened and closed channels @@ -179,8 +171,7 @@ func getOnChainInfo(cfg *OnChainConfig, getPrice fiatPrice) (*onChainInformation // other on chain transactions. openRPCChannels, err := cfg.OpenChannels() if err != nil { - return nil, fmt.Errorf("on-chain report: listing open "+ - "channels failed: %w", err) + return nil, err } for _, channel := range openRPCChannels { @@ -188,9 +179,7 @@ func getOnChainInfo(cfg *OnChainConfig, getPrice fiatPrice) (*onChainInformation channel.ChannelPoint, ) if err != nil { - return nil, fmt.Errorf("on-chain report: parsing open "+ - "channel point %v failed: %w", - channel.ChannelPoint, err) + return nil, err } init := lndclient.InitiatorLocal @@ -212,8 +201,7 @@ func getOnChainInfo(cfg *OnChainConfig, getPrice fiatPrice) (*onChainInformation // on chain transactions. closedRPCChannels, err := cfg.ClosedChannels() if err != nil { - return nil, fmt.Errorf("on-chain report: listing closed "+ - "channels failed: %w", err) + return nil, err } // Add our already closed channels open and closed transactions to our @@ -224,9 +212,7 @@ func getOnChainInfo(cfg *OnChainConfig, getPrice fiatPrice) (*onChainInformation closed.ChannelPoint, ) if err != nil { - return nil, fmt.Errorf("on-chain report: parsing "+ - "closed channel point %v failed: %w", - closed.ChannelPoint, err) + return nil, err } inf := newChannelInfo( @@ -248,8 +234,7 @@ func getOnChainInfo(cfg *OnChainConfig, getPrice fiatPrice) (*onChainInformation // identify them separately to other on chain transactions. sweeps, err := cfg.ListSweeps() if err != nil { - return nil, fmt.Errorf("on-chain report: listing sweep "+ - "transactions failed: %w", err) + return nil, err } for _, sweep := range sweeps { @@ -275,9 +260,7 @@ func onChainReport(info *onChainInformation) ( openChannel, txn, info.entryUtils, ) if err != nil { - return nil, fmt.Errorf("tx %v: creating "+ - "channel open entries failed: %w", - txn.TxHash, err) + return nil, err } report = append(report, entries...) @@ -291,9 +274,7 @@ func onChainReport(info *onChainInformation) ( channelClose, txn, info.entryUtils, ) if err != nil { - return nil, fmt.Errorf("tx %v: creating "+ - "channel close entries failed: %w", - txn.TxHash, err) + return nil, err } report = append(report, entries...) @@ -308,8 +289,7 @@ func onChainReport(info *onChainInformation) ( txn, info.entryUtils, ) if err != nil { - return nil, fmt.Errorf("tx %v: creating sweep "+ - "entries failed: %w", txn.TxHash, err) + return nil, err } report = append(report, entries...) @@ -320,8 +300,7 @@ func onChainReport(info *onChainInformation) ( // closes, we create a generic on chain entry for it. entries, err := onChainEntries(txn, info.entryUtils) if err != nil { - return nil, fmt.Errorf("tx %v: creating generic "+ - "on-chain entries failed: %w", txn.TxHash, err) + return nil, err } report = append(report, entries...) } diff --git a/accounting/report.go b/accounting/report.go index c02c4c7..0a0ff74 100644 --- a/accounting/report.go +++ b/accounting/report.go @@ -78,8 +78,7 @@ func newHarmonyEntry(ts time.Time, amountMsat int64, e EntryType, txid, btcPrice, err := convert(ts) if err != nil { - return nil, fmt.Errorf("fiat conversion at %v failed: %w", ts, - err) + return nil, err } amtMsat := lnwire.MilliSatoshi(absAmt) diff --git a/chanevents/analyzer.go b/chanevents/analyzer.go deleted file mode 100644 index e010d1b..0000000 --- a/chanevents/analyzer.go +++ /dev/null @@ -1,895 +0,0 @@ -package chanevents - -import ( - "context" - "errors" - "fmt" - "iter" - "log/slog" - "sort" - "time" - - "github.com/btcsuite/btcd/btcutil" - "github.com/btcsuite/btclog/v2" - "github.com/lightninglabs/lndclient" -) - -var ( - // errUnexpectedUpdateEvent fires when getInitialChannelState's - // residual-event walk surfaces an Update at a timestamp newer than the - // seed update. - errUnexpectedUpdateEvent = errors.New("unexpected update event in " + - "initial-state walk") - - // errUnknownEventType fires when the event-replay switch sees an - // EventType outside {Offline, Online, Update}. Indicates schema drift - // between the store and the analyzer. - errUnknownEventType = errors.New("unknown channel event type") -) - -// EventsSource abstracts the chanevents store so ForwardingAnalyzer can derive -// uptime metrics without coupling to a specific storage backend. -type EventsSource interface { - // GetLatestChannelUpdateBefore returns the latest channel event before - // the given time, or (nil, nil) if no event predates it. - GetLatestChannelUpdateBefore(ctx context.Context, channelID int64, - before time.Time) (*ChannelEvent, error) - - // GetChannelEvents fetches up to limit events for a channel with id > - // afterID and timestamp in [startTime, endTime), ordered by id ASC. - // Callers page through a range by passing the last returned id as - // afterID until a short page comes back. - GetChannelEvents(ctx context.Context, channelID, afterID int64, - startTime, endTime time.Time, - limit int32) ([]*ChannelEvent, error) - - // GetChannelByShortChanID resolves an scid to a Channel, returning - // ErrUnknownChannel when no row matches. - GetChannelByShortChanID(ctx context.Context, - shortChannelID uint64) (*Channel, error) - - // ScidToPeerMap returns the historically recorded scid→peer index, - // including closed channels. - ScidToPeerMap(ctx context.Context) (map[uint64]string, error) -} - -// ForwardingAnalyzer computes forwarding velocity and effective uptime for -// every (peerIn, peerOut) pair. -type ForwardingAnalyzer struct { - store EventsSource - lnd lndclient.LndServices -} - -// channelEventSeq is a chronologically ordered stream of channel events -// paired with a propagated error value. -type channelEventSeq = iter.Seq2[*ChannelEvent, error] - -// ForwardingAbility holds the raw forwarding facts for one direction of a peer -// pair over the analysis window. It carries no derived rates or categories. The -// consumer derives velocity and uptime fraction from these and the window, and -// reconstructs any categorization (such as forwards observed without qualifying -// uptime) from EffectiveUptime and ForwardedAmount. -type ForwardingAbility struct { - // EffectiveUptime is the time the pair held at least the liquidity floor - // of directional forwardable liquidity over the window. - EffectiveUptime time.Duration - - // ForwardedAmount is the total successfully forwarded amount over the - // window. - ForwardedAmount btcutil.Amount -} - -// PeerPair identifies a unidirectional routing edge from PeerIn to PeerOut. -// PeerIn names the source-side peer (the incoming channel's far end in lnd's -// forwarding vocabulary) and PeerOut names the sink-side peer. -type PeerPair struct { - PeerIn string - PeerOut string -} - -// channelState is the per-channel snapshot the uptime walk carries forward as -// it consumes events: liveness plus the two balances that determine forwarding -// liquidity. -type channelState struct { - online bool - localBalance btcutil.Amount - remoteBalance btcutil.Amount -} - -// NewForwardingAnalyzer returns a ready-to-use analyzer. -func NewForwardingAnalyzer(store EventsSource, - lnd lndclient.LndServices) *ForwardingAnalyzer { - - return &ForwardingAnalyzer{ - store: store, - lnd: lnd, - } -} - -// EffectiveUptime returns a ForwardingAbility for every (peerIn, peerOut) pair -// over [startTime, endTime). Closed channels are folded into the considered set -// so survivorship bias does not skew the uptime denominator. A single -// liquidityFloor is applied uniformly to every pair, so effective uptime is the -// time each pair held at least that much directional forwardable liquidity. -func (a *ForwardingAnalyzer) EffectiveUptime(ctx context.Context, startTime, - endTime time.Time, liquidityFloor btcutil.Amount) ( - map[PeerPair]ForwardingAbility, error) { - - log.DebugS( - ctx, "Calculating effective uptime", - slog.Time("startTime", startTime), - slog.Time("endTime", endTime), - slog.Int64("liquidityFloor", int64(liquidityFloor)), - ) - - scidToPeer, err := a.store.ScidToPeerMap(ctx) - if err != nil { - return nil, err - } - log.DebugS( - ctx, "Found historical channels", - slog.Int("count", len(scidToPeer)), - ) - - successfulForwards, channelPeersConsidered, err := a.getForwardingData( - ctx, startTime, endTime, scidToPeer, - ) - if err != nil { - return nil, err - } - log.DebugS( - ctx, "Found peer pairs with successful forwards", - slog.Int("count", len(successfulForwards)), - ) - - err = a.addActiveChannels(ctx, channelPeersConsidered) - if err != nil { - return nil, err - } - - peerChannels, initialStates, err := a.getPeerChannelData( - ctx, startTime, channelPeersConsidered, - ) - if err != nil { - return nil, err - } - log.DebugS( - ctx, "Identified channels for peers", - slog.Int("count", len(peerChannels)), - ) - - return calculateAllPairsUptime( - ctx, a.store, startTime, endTime, liquidityFloor, - successfulForwards, initialStates, peerChannels, - ) -} - -// getForwardingData queries lnd's forwarding history sequentially in paginated -// batches to retrieve successful forwarding events within the specified time -// range, indexing the results by peer pair. -func (a *ForwardingAnalyzer) getForwardingData(ctx context.Context, startTime, - endTime time.Time, scidToPeer map[uint64]string) ( - map[PeerPair][]btcutil.Amount, map[uint64]string, error) { - - var events []lndclient.ForwardingEvent - var offset uint32 - const forwardingPageSize = 1000 - - for { - fwds, err := a.lnd.Client.ForwardingHistory( - ctx, lndclient.ForwardingHistoryRequest{ - StartTime: startTime, - EndTime: endTime, - Offset: offset, - MaxEvents: forwardingPageSize, - }, - ) - if err != nil { - return nil, nil, err - } - - if len(fwds.Events) == 0 { - break - } - - events = append(events, fwds.Events...) - if len(fwds.Events) < forwardingPageSize { - break - } - - // Guard against a non-advancing offset: if lnd does not move - // LastIndexOffset past the cursor we already queried, stop - // rather than re-fetch the same page forever. - if fwds.LastIndexOffset <= offset { - break - } - offset = fwds.LastIndexOffset - } - - log.DebugS( - ctx, "Found forwarding events", - slog.Int( - "count", len(events), - ), - ) - - channelPeersConsidered := make(map[uint64]string) - successfulForwards := make(map[PeerPair][]btcutil.Amount) - for _, fwd := range events { - inPeer, ok := scidToPeer[fwd.ChannelIn] - if !ok { - log.WarnS( - ctx, "Could not find peer for incoming channel", - nil, slog.Uint64("channelIn", fwd.ChannelIn), - ) - continue - } - - outPeer, ok := scidToPeer[fwd.ChannelOut] - if !ok { - log.WarnS( - ctx, "Could not find peer for outgoing channel", - nil, slog.Uint64("channelOut", fwd.ChannelOut), - ) - continue - } - - channelPeersConsidered[fwd.ChannelIn] = inPeer - channelPeersConsidered[fwd.ChannelOut] = outPeer - - pair := PeerPair{ - PeerIn: inPeer, - PeerOut: outPeer, - } - - amt := fwd.AmountMsatOut.ToSatoshis() - successfulForwards[pair] = append(successfulForwards[pair], amt) - } - - return successfulForwards, channelPeersConsidered, nil -} - -// addActiveChannels ensures the channel set includes both open and closed -// channels so that channels that closed during the analysis period are not -// silently excluded. -func (a *ForwardingAnalyzer) addActiveChannels(ctx context.Context, - channelPeersConsidered map[uint64]string) error { - - // Currently open channels surface their peer directly. - openChannels, err := a.lnd.Client.ListChannels(ctx, false, false) - if err != nil { - return err - } - - for _, channel := range openChannels { - channelPeersConsidered[channel.ChannelID] = - channel.PubKeyBytes.String() - } - - // Historically closed channels are added so survivorship bias does not - // skew the denominator. - closedChannels, err := a.lnd.Client.ClosedChannels(ctx) - if err != nil { - return err - } - - for _, channel := range closedChannels { - // Channels that did not confirm onchain will not have a - // ChannelID. - if channel.ChannelID == 0 { - continue - } - - channelPeersConsidered[channel.ChannelID] = - channel.PubKeyBytes.String() - } - - return nil -} - -// getPeerChannelData returns channels and their initial state at startTime, -// grouped by peer, including only those present in the store. -func (a *ForwardingAnalyzer) getPeerChannelData(ctx context.Context, - startTime time.Time, channelPeersConsidered map[uint64]string) ( - map[string][]int64, map[string]map[int64]*channelState, error) { - - peerChannels := make(map[string][]int64) - initialStates := make(map[string]map[int64]*channelState) - for scid, peerPubKey := range channelPeersConsidered { - channel, err := a.store.GetChannelByShortChanID(ctx, scid) - if errors.Is(err, ErrUnknownChannel) { - // Channels obtained from lnd but not present in the - // store. This can happen if the channel was very - // recently opened or closed and the store hasn't - // ingested the event yet. - log.DebugS( - ctx, "Skipping channel not in events store", - slog.Uint64("scid", scid), - ) - - continue - } - if err != nil { - return nil, nil, err - } - - state, err := a.getInitialChannelState( - ctx, startTime, channel.ID, - ) - if err != nil { - return nil, nil, err - } - - if _, ok := initialStates[peerPubKey]; !ok { - initialStates[peerPubKey] = make( - map[int64]*channelState, - ) - } - initialStates[peerPubKey][channel.ID] = state - - peerChannels[peerPubKey] = append( - peerChannels[peerPubKey], channel.ID, - ) - } - - return peerChannels, initialStates, nil -} - -// getInitialChannelState reconstructs a channel's state at startTime by seeding -// from the latest pre-window update and replaying any residual same-second -// siblings the SQL keyset may have surfaced. A channel with no prior update is -// treated as offline with zero balance. -func (a *ForwardingAnalyzer) getInitialChannelState(ctx context.Context, - startTime time.Time, channelID int64) (*channelState, error) { - - lastUpdate, err := a.store.GetLatestChannelUpdateBefore( - ctx, channelID, startTime, - ) - if err != nil { - return nil, err - } - - if lastUpdate == nil { - log.TraceS( - ctx, "No update event for channel", - slog.Int64("channelID", channelID), - slog.Time("startTime", startTime), - ) - - return &channelState{online: false}, nil - } - - // An update event always implies the channel is online. - state := &channelState{ - online: true, - } - lastUpdate.LocalBalance.WhenSome( - func(amt btcutil.Amount) { - state.localBalance = amt - }, - ) - lastUpdate.RemoteBalance.WhenSome( - func(amt btcutil.Amount) { - state.remoteBalance = amt - }, - ) - - // Fetch any residual events between the last update and the start time. - // The range is bounded (typically a handful of same-second siblings or - // status events) so materialising in one call is fine. Replay below - // assumes id-ASC matches chronological order, true while writers leave - // Timestamp zero so the store stamps clock.Now(). Overflow at the cap - // signals pathological volume the analyzer cannot safely seed from. - const residualEventLimit = 1024 - - residual, err := a.store.GetChannelEvents( - ctx, channelID, lastUpdate.ID, lastUpdate.Timestamp, startTime, - residualEventLimit, - ) - if err != nil { - return nil, err - } - - if len(residual) == residualEventLimit { - return nil, fmt.Errorf("residual events overflow (>=%d) for "+ - "chanID=%d", residualEventLimit, channelID) - } - - // Replay the residual events to arrive at the channel state on the - // window's open. - for _, event := range residual { - switch event.EventType { - case EventTypeOffline: - state.online = false - - case EventTypeOnline: - state.online = true - - case EventTypeUpdate: - // Defensively check that the seed update is indeed the - // latest before startTime. - if !event.Timestamp.Equal(lastUpdate.Timestamp) { - return nil, fmt.Errorf("%w: chanID=%d ts=%v", - errUnexpectedUpdateEvent, channelID, - event.Timestamp) - } - - default: - return nil, fmt.Errorf("%w: chanID=%d type=%v", - errUnknownEventType, channelID, event.EventType) - } - } - - return state, nil -} - -// calculateAllPairsUptime returns forwarding abilities for every peer pair, -// computing both directions (A→B and B→A) in a single pass. -func calculateAllPairsUptime(ctx context.Context, store EventsSource, startTime, - endTime time.Time, liquidityFloor btcutil.Amount, - successfulForwards map[PeerPair][]btcutil.Amount, - initialStates map[string]map[int64]*channelState, - peerChannels map[string][]int64) ( - map[PeerPair]ForwardingAbility, error) { - - results := make(map[PeerPair]ForwardingAbility) - recordResult := func(peerIn, peerOut string, a ForwardingAbility) { - results[PeerPair{PeerIn: peerIn, PeerOut: peerOut}] = a - } - - // Lazy per-peer event cache: each peer's events are fetched once and - // replayed across every pair walk that consumes them. - peerEvents := make(map[string][]*ChannelEvent, len(initialStates)) - loadPeer := func(peer string) ([]*ChannelEvent, error) { - if cached, ok := peerEvents[peer]; ok { - return cached, nil - } - - events, err := loadPeerEvents( - ctx, store, startTime, endTime, peerChannels[peer], - ) - if err != nil { - return nil, err - } - - peerEvents[peer] = events - - return events, nil - } - - peers := make([]string, 0, len(initialStates)) - for peer := range initialStates { - peers = append(peers, peer) - } - - type peerInitialSums struct { - remote btcutil.Amount - local btcutil.Amount - } - - // We gather the initial balance sums for each peer upfront so the pair - // walk can be more efficient and doesn't have to recalculate. - initialSums := make(map[string]peerInitialSums, len(initialStates)) - for peer, states := range initialStates { - var remoteSum, localSum btcutil.Amount - for _, s := range states { - if s.online { - remoteSum += s.remoteBalance - localSum += s.localBalance - } - } - initialSums[peer] = peerInitialSums{ - remote: remoteSum, - local: localSum, - } - } - - for i, peerA := range peers { - if ctx.Err() != nil { - return nil, ctx.Err() - } - - statesA := initialStates[peerA] - sumsA := initialSums[peerA] - - sliceA, err := loadPeer(peerA) - if err != nil { - return nil, err - } - - for j := i; j < len(peers); j++ { - if ctx.Err() != nil { - return nil, ctx.Err() - } - - peerB := peers[j] - statesB := initialStates[peerB] - sumsB := initialSums[peerB] - - forwardedAB := pairForwardedTotal( - successfulForwards, peerA, peerB, - ) - forwardedBA := pairForwardedTotal( - successfulForwards, peerB, peerA, - ) - - sliceB := sliceA - if i != j { - sliceB, err = loadPeer(peerB) - if err != nil { - return nil, err - } - } - - abilityAB, abilityBA, err := - calculateBothDirectionsUptime( - ctx, startTime, endTime, - liquidityFloor, - statesA, statesB, - sumsA.remote, sumsA.local, - sumsB.remote, sumsB.local, - mergeEventSlices(sliceA, sliceB), - forwardedAB, forwardedBA, - ) - if err != nil { - return nil, err - } - - recordResult(peerA, peerB, *abilityAB) - if i != j { - recordResult(peerB, peerA, *abilityBA) - } - } - } - - return results, nil -} - -// eventPageSize bounds a single channel-event page so the per-channel fetch -// never asks the store for an unbounded result set. -const eventPageSize = 1000 - -// loadPeerEvents fetches every event in [startTime, endTime) on the given -// channels and returns them merged into a single chronologically sorted slice. -// Each channel is paged through in id-ascending batches so no single store -// query is unbounded. Events sharing a timestamp are ordered by ascending id so -// the result is deterministic. -func loadPeerEvents(ctx context.Context, store EventsSource, startTime, - endTime time.Time, chanIDs []int64) ([]*ChannelEvent, error) { - - var events []*ChannelEvent - for _, chanID := range chanIDs { - var afterID int64 - for { - page, err := store.GetChannelEvents( - ctx, chanID, afterID, startTime, endTime, - eventPageSize, - ) - if err != nil { - return nil, err - } - - events = append(events, page...) - if len(page) < eventPageSize { - break - } - - // Events come back id-ASC, so the last id is the - // largest; continue the next page after it. - afterID = page[len(page)-1].ID - } - } - - sort.SliceStable( - events, - func(i, j int) bool { - if events[i].Timestamp.Equal(events[j].Timestamp) { - return events[i].ID < events[j].ID - } - - return events[i].Timestamp.Before(events[j].Timestamp) - }, - ) - - return events, nil -} - -// pairForwardedTotal sums the successfully forwarded amounts for one direction -// of a peer pair over the analysis window. -func pairForwardedTotal(successfulForwards map[PeerPair][]btcutil.Amount, - peerIn, peerOut string) btcutil.Amount { - - var total btcutil.Amount - for _, amt := range successfulForwards[PeerPair{ - PeerIn: peerIn, PeerOut: peerOut, - }] { - total += amt - } - - return total -} - -// calculateBothDirectionsUptime computes the effective forwarding uptime for -// both directions of a peer pair in a single chronological walk of the merged -// event stream. Only the liquidity-direction roles differ between the two -// accumulators, as both share the same uniform liquidityFloor. forwardedAB and -// forwardedBA carry each direction's total forwarded volume through to the -// returned abilities. For self-pair calls both returned abilities are equal. -func calculateBothDirectionsUptime(ctx context.Context, startTime, - endTime time.Time, liquidityFloor btcutil.Amount, statesA, - statesB map[int64]*channelState, sumARemote, sumALocal, sumBRemote, - sumBLocal btcutil.Amount, mergedEvents channelEventSeq, - forwardedAB, forwardedBA btcutil.Amount) ( - *ForwardingAbility, *ForwardingAbility, error) { - - traceOn := log.Level() <= btclog.LevelTrace - - if traceOn { - log.TraceS(ctx, "Calculating bidirectional effective uptime") - for chanID, state := range statesA { - log.TraceS( - ctx, "Initial state A", - slog.Int64("chanID", chanID), - slog.Bool("online", state.online), - slog.Int64( - "localBalance", int64( - state.localBalance, - ), - ), - slog.Int64( - "remoteBalance", int64( - state.remoteBalance, - ), - ), - ) - } - for chanID, state := range statesB { - log.TraceS( - ctx, "Initial state B", - slog.Int64("chanID", chanID), - slog.Bool("online", state.online), - slog.Int64( - "localBalance", int64( - state.localBalance, - ), - ), - slog.Int64( - "remoteBalance", int64( - state.remoteBalance, - ), - ), - ) - } - log.TraceS( - ctx, "Using uniform forwarding liquidity floor", - slog.Int64("liquidityFloor", int64(liquidityFloor)), - ) - } - - statesA = copyChannelStates(statesA) - statesB = copyChannelStates(statesB) - - var uptimeAB, uptimeBA time.Duration - lastTimestamp := startTime - - accumulate := func(intervalDuration time.Duration) { - if intervalDuration <= 0 { - return - } - // (A→B): A is incoming, B is outgoing. Liquidity bottleneck is - // min(A's online inbound, B's online outbound). - liqAB := min(sumARemote, sumBLocal) - // (B→A): roles flipped. - liqBA := min(sumBRemote, sumALocal) - if traceOn { - log.TraceS( - ctx, "Forwarding liquidity check", - slog.Duration("interval", intervalDuration), - slog.Int64( - "liqAB", int64(liqAB), - ), - slog.Int64( - "liqBA", int64(liqBA), - ), - ) - } - - // A direction qualifies when its bottleneck liquidity is at - // least the floor, matching the "at least" contract documented - // on the ForwardingAbility proto, struct, and CLI flag. The - // liquidity must also be strictly positive: zero forwardable - // liquidity can never route a payment, even when the floor is 0. - if liqAB >= liquidityFloor && liqAB > 0 { - uptimeAB += intervalDuration - } - if liqBA >= liquidityFloor && liqBA > 0 { - uptimeBA += intervalDuration - } - } - - // Walk the merged event stream, applying each event to both peers' - // states and accumulating uptime for each direction when the respective - // liquidity conditions are met. - for event, err := range mergedEvents { - if err != nil { - return nil, nil, err - } - if traceOn { - log.TraceS( - ctx, "Processing event", - slog.Int64("chanID", event.ChannelID), - btclog.Fmt("type", "%v", event.EventType), - slog.Time("time", event.Timestamp), - ) - } - - // accumulate uptime for the elapsed interval since the last - // event, based on the state of the channels during that - // interval. The events are ordered chronologically so the state - // is consistent with the entire interval. - accumulate(event.Timestamp.Sub(lastTimestamp)) - - // Update the state for each peer if the event affects one of - // their channels. Before applying the event, we remove the - // channel's contribution to the sums if it's currently online, - // because the event may change the channel's online status or - // balances in a way that affects the sums. - if state, ok := statesA[event.ChannelID]; ok { - // We would have inlcuded the channel's balances in the - // sums if it was online, so we need to remove them - // before applying the event. - if state.online { - sumARemote -= state.remoteBalance - sumALocal -= state.localBalance - } - - if err := applyEvent(state, event); err != nil { - return nil, nil, err - } - - // If the channel is still online after applying the - // event, we add its (possibly updated) balances back to - // the sums. - if state.online { - sumARemote += state.remoteBalance - sumALocal += state.localBalance - } - } - if state, ok := statesB[event.ChannelID]; ok { - if state.online { - sumBRemote -= state.remoteBalance - sumBLocal -= state.localBalance - } - if err := applyEvent(state, event); err != nil { - return nil, nil, err - } - if state.online { - sumBRemote += state.remoteBalance - sumBLocal += state.localBalance - } - } - - lastTimestamp = event.Timestamp - } - - // Account for the final interval between the last event and the end - // time. - accumulate(endTime.Sub(lastTimestamp)) - - if traceOn { - log.TraceS( - ctx, "Total effective uptime", - slog.Duration("uptimeAB", uptimeAB), - slog.Duration("uptimeBA", uptimeBA), - slog.Duration( - "totalDuration", endTime.Sub(startTime), - ), - ) - } - - abilityAB := makeAbility(uptimeAB, forwardedAB) - abilityBA := makeAbility(uptimeBA, forwardedBA) - - return abilityAB, abilityBA, nil -} - -// mergeEventSlices interleaves two sorted event streams into a single -// chronological iter.Seq2. Equal-timestamp events from sliceA are yielded -// first. Self-pair calls (sliceA == sliceB) yield each event twice. Callers -// must keep their state updates idempotent under same-timestamp duplicates. -func mergeEventSlices(sliceA, sliceB []*ChannelEvent) channelEventSeq { - return func(yield func(*ChannelEvent, error) bool) { - i, j := 0, 0 - - // Interleave both slices until one is exhausted, ensuring - // strict chronological order across the combined stream. - for i < len(sliceA) && j < len(sliceB) { - if sliceA[i].Timestamp.After(sliceB[j].Timestamp) { - if !yield(sliceB[j], nil) { - return - } - j++ - } else { - if !yield(sliceA[i], nil) { - return - } - i++ - } - } - - // Drain any remaining events from sliceA. This loop only - // executes if sliceB was exhausted first. - for ; i < len(sliceA); i++ { - if !yield(sliceA[i], nil) { - return - } - } - - // Drain any remaining events from sliceB. This loop only - // executes if sliceA was exhausted first. - for ; j < len(sliceB); j++ { - if !yield(sliceB[j], nil) { - return - } - } - } -} - -// copyChannelStates returns a deep copy of the per-channel state map so the -// bidirectional walk cannot mutate the caller's snapshot. -func copyChannelStates(states map[int64]*channelState) map[int64]*channelState { - statesCopy := make(map[int64]*channelState, len(states)) - for chanID, state := range states { - statesCopy[chanID] = &channelState{ - online: state.online, - localBalance: state.localBalance, - remoteBalance: state.remoteBalance, - } - } - - return statesCopy -} - -// applyEvent advances a channel's snapshot by one event. Update events imply -// online and overwrite whichever balance the event carries. Unknown event -// types return errUnknownEventType to surface store↔analyzer schema drift. -func applyEvent(state *channelState, event *ChannelEvent) error { - switch event.EventType { - case EventTypeOffline: - state.online = false - - case EventTypeOnline: - state.online = true - - case EventTypeUpdate: - state.online = true - event.LocalBalance.WhenSome( - func(amt btcutil.Amount) { - state.localBalance = amt - }, - ) - event.RemoteBalance.WhenSome( - func(amt btcutil.Amount) { - state.remoteBalance = amt - }, - ) - - default: - return fmt.Errorf("%w: chanID=%d type=%v", errUnknownEventType, - event.ChannelID, event.EventType) - } - - return nil -} - -// makeAbility folds an accumulated uptime and successful-amount total into a -// ForwardingAbility carrying the raw facts. Derived rates and categories are -// left to the consumer. -func makeAbility(totalUptime time.Duration, - totalAmt btcutil.Amount) *ForwardingAbility { - - return &ForwardingAbility{ - EffectiveUptime: totalUptime, - ForwardedAmount: totalAmt, - } -} diff --git a/chanevents/analyzer_test.go b/chanevents/analyzer_test.go deleted file mode 100644 index ced5e5d..0000000 --- a/chanevents/analyzer_test.go +++ /dev/null @@ -1,1041 +0,0 @@ -package chanevents - -import ( - "context" - "testing" - "time" - - "github.com/btcsuite/btcd/btcutil" - "github.com/lightninglabs/lndclient" - "github.com/lightningnetwork/lnd/clock" - "github.com/lightningnetwork/lnd/fn/v2" - "github.com/lightningnetwork/lnd/routing/route" - "github.com/stretchr/testify/require" -) - -// nextEventID is incremented by newEvent so every synthetic event carries a -// unique ID, making assertion failures easier to trace. -var nextEventID int64 = 1 - -// newEvent returns an update-typed ChannelEvent with the given balances. The -// ID is auto-incremented so failing assertions can identify the offending row. -func newEvent(chanID int64, ts int64, eventType EventType, local, - remote btcutil.Amount) *ChannelEvent { - - id := nextEventID - nextEventID++ - - return &ChannelEvent{ - ID: id, - ChannelID: chanID, - Timestamp: time.Unix(ts, 0), - EventType: eventType, - LocalBalance: fn.Some(local), - RemoteBalance: fn.Some(remote), - } -} - -// newStatusEvent returns an Online or Offline event with no balance payload, -// matching the schema contract for non-Update event types. -func newStatusEvent(chanID int64, ts int64, eventType EventType) *ChannelEvent { - return &ChannelEvent{ - ChannelID: chanID, - Timestamp: time.Unix(ts, 0), - EventType: eventType, - LocalBalance: fn.None[btcutil.Amount](), - RemoteBalance: fn.None[btcutil.Amount](), - } -} - -// TestMergeEventSlices verifies that interleaving distinct or identical streams -// preserves strict chronological order and resolves timestamp collisions -// deterministically. -func TestMergeEventSlices(t *testing.T) { - t.Parallel() - - const ( - fromA int64 = 1 - fromB int64 = 2 - ) - - // selfPair is the same backing slice passed as both sliceA and sliceB - // in the self-pair row. The merge must yield each element twice. - selfPair := []*ChannelEvent{ - newStatusEvent(fromA, 100, EventTypeOnline), - newStatusEvent(fromA, 200, EventTypeOffline), - } - - testCases := []struct { - name string - sliceA []*ChannelEvent - sliceB []*ChannelEvent - expected []*ChannelEvent - }{ - { - name: "Both empty", - }, - { - name: "Only A", - sliceA: []*ChannelEvent{ - newStatusEvent(fromA, 100, EventTypeOnline), - newStatusEvent(fromA, 200, EventTypeOffline), - }, - expected: []*ChannelEvent{ - newStatusEvent(fromA, 100, EventTypeOnline), - newStatusEvent(fromA, 200, EventTypeOffline), - }, - }, - { - name: "Only B", - sliceB: []*ChannelEvent{ - newStatusEvent(fromB, 100, EventTypeOnline), - newStatusEvent(fromB, 200, EventTypeOffline), - }, - expected: []*ChannelEvent{ - newStatusEvent(fromB, 100, EventTypeOnline), - newStatusEvent(fromB, 200, EventTypeOffline), - }, - }, - { - name: "Disjoint A before B", - sliceA: []*ChannelEvent{ - newStatusEvent(fromA, 100, EventTypeOnline), - newStatusEvent(fromA, 150, EventTypeOffline), - }, - sliceB: []*ChannelEvent{ - newStatusEvent(fromB, 200, EventTypeOnline), - newStatusEvent(fromB, 250, EventTypeOffline), - }, - expected: []*ChannelEvent{ - newStatusEvent(fromA, 100, EventTypeOnline), - newStatusEvent(fromA, 150, EventTypeOffline), - newStatusEvent(fromB, 200, EventTypeOnline), - newStatusEvent(fromB, 250, EventTypeOffline), - }, - }, - { - name: "Interleaved", - sliceA: []*ChannelEvent{ - newStatusEvent(fromA, 100, EventTypeOnline), - newStatusEvent(fromA, 300, EventTypeOffline), - }, - sliceB: []*ChannelEvent{ - newStatusEvent(fromB, 200, EventTypeOnline), - newStatusEvent(fromB, 400, EventTypeOffline), - }, - expected: []*ChannelEvent{ - newStatusEvent(fromA, 100, EventTypeOnline), - newStatusEvent(fromB, 200, EventTypeOnline), - newStatusEvent(fromA, 300, EventTypeOffline), - newStatusEvent(fromB, 400, EventTypeOffline), - }, - }, - { - name: "Equal timestamps yield A first", - sliceA: []*ChannelEvent{ - newStatusEvent(fromA, 100, EventTypeOnline), - newStatusEvent(fromA, 200, EventTypeOffline), - }, - sliceB: []*ChannelEvent{ - newStatusEvent(fromB, 100, EventTypeOnline), - newStatusEvent(fromB, 200, EventTypeOffline), - }, - expected: []*ChannelEvent{ - newStatusEvent(fromA, 100, EventTypeOnline), - newStatusEvent(fromB, 100, EventTypeOnline), - newStatusEvent(fromA, 200, EventTypeOffline), - newStatusEvent(fromB, 200, EventTypeOffline), - }, - }, - { - name: "Self-pair duplicates each event", - sliceA: selfPair, - sliceB: selfPair, - expected: []*ChannelEvent{ - selfPair[0], selfPair[0], - selfPair[1], selfPair[1], - }, - }, - } - - for _, tc := range testCases { - t.Run( - tc.name, - func(t *testing.T) { - t.Parallel() - - var got []*ChannelEvent - for event, err := range mergeEventSlices( - tc.sliceA, tc.sliceB, - ) { - require.NoError(t, err) - got = append(got, event) - } - require.Equal(t, tc.expected, got) - }, - ) - } -} - -// TestMergeEventSlicesEarlyTermination verifies that the merge sequence safely -// halts mid-stream without exhausting inputs when the consumer aborts. -func TestMergeEventSlicesEarlyTermination(t *testing.T) { - t.Parallel() - - sliceA := []*ChannelEvent{ - newStatusEvent(1, 100, EventTypeOnline), - newStatusEvent(1, 300, EventTypeOffline), - } - sliceB := []*ChannelEvent{ - newStatusEvent(2, 200, EventTypeOnline), - newStatusEvent(2, 400, EventTypeOffline), - } - - var got []*ChannelEvent - for event, err := range mergeEventSlices(sliceA, sliceB) { - require.NoError(t, err) - got = append(got, event) - if len(got) == 2 { - break - } - } - require.Len(t, got, 2) -} - -// TestCalculateBothDirectionsUptime verifies that the bidirectional uptime -// walk correctly attributes effective uptime given varying liveness, balance -// changes, and forwarding amounts. Each table row pins one boundary condition -// of the (A→B) direction. Full bidirectional invariants are covered by -// dedicated tests. -func TestCalculateBothDirectionsUptime(t *testing.T) { - t.Parallel() - - var ( - chanInID int64 = 1 - chanOutID int64 = 2 - startTime = time.Unix(100, 0) - endTime = time.Unix(200, 0) - ) - - testCases := []struct { - name string - - inStates map[int64]*channelState - outStates map[int64]*channelState - inEvents []*ChannelEvent - outEvents []*ChannelEvent - - successAmts []btcutil.Amount - liquidityFloor btcutil.Amount - - expectedUptime time.Duration - }{ - { - name: "Basic case always online", - inStates: map[int64]*channelState{ - chanInID: { - online: true, - remoteBalance: 1000, - }, - }, - outStates: map[int64]*channelState{ - chanOutID: { - online: true, - localBalance: 800, - }, - }, - successAmts: []btcutil.Amount{ - 100, - }, - expectedUptime: 100 * time.Second, - }, - { - // Liquidity sits exactly on the floor for the whole - // window. The "at least" contract counts equality, so - // the pair accrues the full window (a strict greater- - // than comparison would wrongly report zero). - name: "Liquidity exactly at floor qualifies", - inStates: map[int64]*channelState{ - chanInID: { - online: true, - remoteBalance: 500, - }, - }, - outStates: map[int64]*channelState{ - chanOutID: { - online: true, - localBalance: 500, - }, - }, - liquidityFloor: 500, - expectedUptime: 100 * time.Second, - }, - { - // The forward in successAmts updates both channels: - // the in-channel's remoteBalance drops by the amount - // (peer A spent it) and the out-channel's localBalance - // drops by the same (forwarded out to B). Both Update - // events fire at the forward's timestamp. The threshold - // straddles pre and post liquidity so the boundary at - // the forward time is what carves the uptime window. - // The later tests in here aren't causally consistent - // with the successAmts, which in general is the source - // of truth for forwards. - name: "Forward drives the balance timeline", - inStates: map[int64]*channelState{ - chanInID: { - online: true, - remoteBalance: 1500, - }, - }, - outStates: map[int64]*channelState{ - chanOutID: { - online: true, - localBalance: 1000, - }, - }, - inEvents: []*ChannelEvent{ - // Forward of 200 sats at t=150 on the in side: - // local 0 → 200, remote 1500 → 1300. - newEvent( - chanInID, 150, EventTypeUpdate, 200, - 1300, - ), - }, - outEvents: []*ChannelEvent{ - // Same forward on the out side: local 1000 → - // 800, remote 0 → 200. - newEvent( - chanOutID, 150, EventTypeUpdate, 800, - 200, - ), - }, - successAmts: []btcutil.Amount{ - 200, - }, - liquidityFloor: 900, - // t=100..150 (50s): liq = min(1500, 1000) = 1000 - // > 900 → qualifies. - // t=150..200 (50s): liq = min(1300, 800) = 800 - // < 900 → drops out. - // Total uptime = 50s, total amount = 200 sats. - expectedUptime: 50 * time.Second, - }, - { - name: "Channel goes offline", - inStates: map[int64]*channelState{ - chanInID: { - online: true, - remoteBalance: 1000, - }, - }, - outStates: map[int64]*channelState{ - chanOutID: { - online: true, - localBalance: 800, - }, - }, - inEvents: []*ChannelEvent{ - newStatusEvent(chanInID, 150, EventTypeOffline), - }, - successAmts: []btcutil.Amount{ - 100, - }, - liquidityFloor: 1, - expectedUptime: 50 * time.Second, - }, - { - name: "Balance change", - inStates: map[int64]*channelState{ - chanInID: { - online: true, - remoteBalance: 1000, - }, - }, - outStates: map[int64]*channelState{ - chanOutID: { - online: true, - localBalance: 800, - }, - }, - outEvents: []*ChannelEvent{ - newEvent( - chanOutID, 150, EventTypeUpdate, 1200, - 0, - ), - }, - successAmts: []btcutil.Amount{ - 100, - }, - liquidityFloor: 1, - // Balance changes at t=150, so for the first 50s the - // liquidity is 800, then it's 1000 for the next 50s. - // The total effective uptime is 100s, because the - // liquidity threshold is low. - expectedUptime: 100 * time.Second, - }, - { - name: "Duplicate event timestamps", - inStates: map[int64]*channelState{ - chanInID: { - online: true, - remoteBalance: 1000, - }, - }, - outStates: map[int64]*channelState{ - chanOutID: { - online: true, - localBalance: 800, - }, - }, - inEvents: []*ChannelEvent{ - newStatusEvent(chanInID, 150, EventTypeOffline), - }, - outEvents: []*ChannelEvent{ - newEvent( - chanOutID, 150, EventTypeUpdate, 1200, - 0, - ), - }, - successAmts: []btcutil.Amount{ - 100, - }, - // At t=150, two events happen. From t=100 to t=150 - // (50s), liquidity is min(1000, 800) = 800. After - // t=150, chanIn is offline, so liquidity is 0 for the - // remaining 50s. - expectedUptime: 50 * time.Second, - }, - { - name: "No initial state", - inStates: map[int64]*channelState{ - chanInID: { - online: false, - }, - }, - outStates: map[int64]*channelState{ - chanOutID: { - online: false, - }, - }, - inEvents: []*ChannelEvent{ - newEvent( - chanInID, 120, EventTypeUpdate, 0, 1000, - ), - }, - outEvents: []*ChannelEvent{ - newEvent( - chanOutID, 140, EventTypeUpdate, 800, 0, - ), - }, - successAmts: []btcutil.Amount{ - 100, - }, - liquidityFloor: 1, - // We don't have initial balance states, so we can't - // determine liquidity until we see an event on both - // channels. At t=140 we know the liquidity is 800, and - // it's online for the remaining 60s of the 100s total. - // So uptime fraction is 0.6 for 800. - expectedUptime: 60 * time.Second, - }, - { - name: "Multiple channels for out peer", - inStates: map[int64]*channelState{ - chanInID: { - online: true, - remoteBalance: 1000, - }, - }, - outStates: map[int64]*channelState{ - chanOutID: { - online: true, - localBalance: 800, - }, - 3: { - online: true, - localBalance: 500, - }, - }, - outEvents: []*ChannelEvent{ - newEvent( - chanOutID, 150, EventTypeUpdate, 1200, - 0, - ), - }, - successAmts: []btcutil.Amount{ - 100, - }, - liquidityFloor: 900, - // We expect the liquidity to be the sum of the - // available balances of the out channels. t=100-150: - // min(1000, 800 + 500) = 1000 t=150-200: min(1000, 1200 - // + 500) = 1000 - expectedUptime: 100 * time.Second, - }, - { - name: "Circular payment ability", - inStates: map[int64]*channelState{ - chanInID: { - online: true, - localBalance: 1000, - }, - }, - outStates: map[int64]*channelState{ - chanInID: { - online: true, - localBalance: 1000, - }, - }, - inEvents: []*ChannelEvent{ - newEvent( - chanInID, 150, EventTypeUpdate, 500, - 500, - ), - }, - outEvents: []*ChannelEvent{ - newEvent( - chanInID, 150, EventTypeUpdate, 500, - 500, - ), - }, - successAmts: []btcutil.Amount{ - 100, - }, - liquidityFloor: 1, - // For the first 50s, liquidity is min(1000, 0) = 0. For - // the next 50s, liquidity is min(500, 500) = 500. - expectedUptime: 50 * time.Second, - }, - { - name: "Self route multiple channels", - inStates: map[int64]*channelState{ - chanInID: { - online: true, - remoteBalance: 1000, - localBalance: 1000, - }, - chanOutID: { - online: true, - remoteBalance: 1000, - localBalance: 1000, - }, - }, - outStates: map[int64]*channelState{ - chanInID: { - online: true, - remoteBalance: 1000, - localBalance: 1000, - }, - chanOutID: { - online: true, - remoteBalance: 1000, - localBalance: 1000, - }, - }, - inEvents: []*ChannelEvent{}, - outEvents: []*ChannelEvent{ - // At 150s (midpoint), out channel balance drops - // to 0. - newEvent( - chanOutID, 150, EventTypeUpdate, 0, - 2000, - ), - }, - successAmts: []btcutil.Amount{ - 100, - }, - liquidityFloor: 1500, - // Initial fwdLiquidity = min(2000, 2000) = 2000. 2000 > - // 1500, so first 50s accrue. At t=150, chanOut local - // drops to 0. outStates total local becomes 1000 (from - // chanIn). fwdLiquidity = min(2000, 1000) = 1000. 1000 - // is not > 1500, so last 50s do not accrue. - expectedUptime: 50 * time.Second, - }, - { - name: "Zero uptime no forwards", - inStates: map[int64]*channelState{ - chanInID: { - online: false, - }, - }, - outStates: map[int64]*channelState{ - chanOutID: { - online: false, - }, - }, - expectedUptime: 0, - }, - { - // Forwards landed but the pair never held qualifying - // liquidity: zero uptime, yet the forwarded volume is - // still reported so the consumer keeps the demand - // signal. - name: "Zero uptime with forwards retains volume", - inStates: map[int64]*channelState{ - chanInID: { - online: false, - }, - }, - outStates: map[int64]*channelState{ - chanOutID: { - online: false, - }, - }, - successAmts: []btcutil.Amount{ - 100, - }, - expectedUptime: 0, - }, - } - - for _, tc := range testCases { - t.Run( - tc.name, - func(t *testing.T) { - t.Parallel() - - var totalSuccessfulAmount btcutil.Amount - for _, amt := range tc.successAmts { - totalSuccessfulAmount += amt - } - - mergedEvents := mergeEventSlices( - tc.inEvents, tc.outEvents, - ) - - // Precompute the starting balances. - var sumARemote, sumALocal, sumBRemote, - sumBLocal btcutil.Amount - - for _, s := range tc.inStates { - if s.online { - sumARemote += s.remoteBalance - sumALocal += s.localBalance - } - } - for _, s := range tc.outStates { - if s.online { - sumBRemote += s.remoteBalance - sumBLocal += s.localBalance - } - } - - // The (B→A) forwarded total is not asserted by - // this test; pass zero so the second ability is - // well-defined but ignored. - abilityAB, _, err := - calculateBothDirectionsUptime( - context.Background(), - startTime, endTime, - tc.liquidityFloor, - tc.inStates, tc.outStates, - sumARemote, sumALocal, - sumBRemote, sumBLocal, - mergedEvents, - totalSuccessfulAmount, 0, - ) - require.NoError(t, err) - require.Equal(t, &ForwardingAbility{ - EffectiveUptime: tc.expectedUptime, - ForwardedAmount: totalSuccessfulAmount, - }, abilityAB) - }, - ) - } -} - -// TestCalculateBothDirectionsUptimeAsymmetric pins that the two accumulators -// are independent: with liquidity that crosses only the A→B threshold, the B→A -// direction must report zero uptime regardless of how high the A→B side scores. -func TestCalculateBothDirectionsUptimeAsymmetric(t *testing.T) { - t.Parallel() - - var ( - chanInID int64 = 1 - chanOutID int64 = 2 - startTime = time.Unix(100, 0) - endTime = time.Unix(200, 0) - ) - - // A holds inbound liquidity (remoteBalance high). B holds outbound - // liquidity (localBalance high). The situation favours A→B and starves - // B→A. - statesA := map[int64]*channelState{ - chanInID: { - online: true, - remoteBalance: 1000, - localBalance: 100, - }, - } - statesB := map[int64]*channelState{ - chanOutID: { - online: true, - localBalance: 1000, - remoteBalance: 100, - }, - } - - // The floor sits between the two directions: A→B has min(1000, 1000) - // = 1000 ≥ 500 (qualifying); B→A has min(100, 100) = 100 < 500 (not - // qualifying). - const liquidityFloor btcutil.Amount = 500 - - // Precompute the starting balances. - var sumARemote, sumALocal, sumBRemote, sumBLocal btcutil.Amount - for _, s := range statesA { - if s.online { - sumARemote += s.remoteBalance - sumALocal += s.localBalance - } - } - for _, s := range statesB { - if s.online { - sumBRemote += s.remoteBalance - sumBLocal += s.localBalance - } - } - - abilityAB, abilityBA, err := calculateBothDirectionsUptime( - context.Background(), startTime, endTime, - liquidityFloor, statesA, statesB, - sumARemote, sumALocal, sumBRemote, sumBLocal, - mergeEventSlices(nil, nil), - 100, 50, - ) - require.NoError(t, err) - - require.Equal( - t, &ForwardingAbility{ - EffectiveUptime: 100 * time.Second, - ForwardedAmount: 100, - }, abilityAB, - ) - require.Equal( - t, &ForwardingAbility{ - // Forwards landed but BA never crossed the floor: zero - // uptime, volume still reported. - EffectiveUptime: 0, - ForwardedAmount: 50, - }, abilityBA, - ) -} - -// TestInitialStateSameSecond verifies that when multiple update events share -// the same second-resolution timestamp, getInitialChannelState seeds from the -// most recent one (highest id) rather than aborting or choosing arbitrarily. -func TestInitialStateSameSecond(t *testing.T) { - t.Parallel() - - clock := clock.NewTestClock(testTime) - store := NewTestDB(t, clock) - ctx := context.Background() - - peerID, err := store.AddPeer(ctx, testPubKey) - require.NoError(t, err) - - channelID, err := store.AddChannel( - ctx, testChanPoint1, testShortChanID1, peerID, - ) - require.NoError(t, err) - - // Two update events share the same second-resolution timestamp. The - // second insert (higher id) is the one the SQL must pick. - sameTime := testTime.Add(10 * time.Second) - err = store.AddChannelEvent( - ctx, &ChannelEvent{ - ChannelID: channelID, - EventType: EventTypeUpdate, - Timestamp: sameTime, - LocalBalance: fn.Some(btcutil.Amount(100)), - RemoteBalance: fn.Some(btcutil.Amount(900)), - }, - ) - require.NoError(t, err) - err = store.AddChannelEvent( - ctx, &ChannelEvent{ - ChannelID: channelID, - EventType: EventTypeUpdate, - Timestamp: sameTime, - LocalBalance: fn.Some(btcutil.Amount(200)), - RemoteBalance: fn.Some(btcutil.Amount(800)), - }, - ) - require.NoError(t, err) - - // An offline event shares the same second-resolution timestamp with an - // even higher ID. Replaying this offline event will set the channel - // state to offline, but the balances from the highest-ID update event - // must still be retained. - err = store.AddChannelEvent( - ctx, &ChannelEvent{ - ChannelID: channelID, - EventType: EventTypeOffline, - Timestamp: sameTime, - }, - ) - require.NoError(t, err) - - // Construct a bare analyzer. getInitialChannelState only touches the - // store, so the lnd field can stay zero. - a := &ForwardingAnalyzer{store: store} - - startTime := sameTime.Add(time.Second) - state, err := a.getInitialChannelState(ctx, startTime, channelID) - require.NoError(t, err) - require.NotNil(t, state) - require.False(t, state.online, - "replayed offline event sets state offline") - require.Equal(t, btcutil.Amount(200), state.localBalance) - require.Equal(t, btcutil.Amount(800), state.remoteBalance) -} - -// stubLndChannelClient implements the three lndclient.LightningClient methods -// the analyzer exercises. The embedded interface is nil, so any other method -// panics. Callers must not invoke methods outside the overridden set. -type stubLndChannelClient struct { - lndclient.LightningClient - - openChannels []lndclient.ChannelInfo - closedChannels []lndclient.ClosedChannel - forwardingHistory *lndclient.ForwardingHistoryResponse -} - -func (s *stubLndChannelClient) ListChannels(_ context.Context, _, _ bool, - _ ...lndclient.ListChannelsOption) ([]lndclient.ChannelInfo, error) { - - return s.openChannels, nil -} - -func (s *stubLndChannelClient) ClosedChannels(_ context.Context) ( - []lndclient.ClosedChannel, error) { - - return s.closedChannels, nil -} - -func (s *stubLndChannelClient) ForwardingHistory(_ context.Context, - req lndclient.ForwardingHistoryRequest) ( - *lndclient.ForwardingHistoryResponse, error) { - - if s.forwardingHistory == nil { - return &lndclient.ForwardingHistoryResponse{}, nil - } - - if req.Offset > 0 { - return &lndclient.ForwardingHistoryResponse{}, nil - } - - return s.forwardingHistory, nil -} - -// validPubKey1 is the open-channel peer. route.NewVertexFromStr requires a -// 33-byte compressed key (66 hex chars). The pre-existing testPubKey is 65 -// chars long and is fine for the store layer, but the lnd survivorship path -// goes through route.NewVertexFromStr so we use a valid pair here. -const ( - validPubKey1 = "028d4c6347426f2e3f5e2b8e4a1c3b9f1c" + - "4e5d6f7a8b9c0d1e2f3a4b5c6d7e8f9a" - validPubKey2 = "038d4c6347426f2e3f5e2b8e4a1c3b9f1c" + - "4e5d6f7a8b9c0d1e2f3a4b5c6d7e8f9a" -) - -// TestEffectiveUptimeIncludesClosedChannels exercises the survivorship-bias -// guarantee of EffectiveUptime: a peer whose only channel was closed before the -// analysis window must still appear in the result map. Without merging lnd's -// ClosedChannels into the considered set, the closed-channel peer would be -// invisible to the walk and the fleet's reported uptime would over-state -// reality. -func TestEffectiveUptimeIncludesClosedChannels(t *testing.T) { - t.Parallel() - - clk := clock.NewTestClock(testTime) - store := NewTestDB(t, clk) - ctx := context.Background() - - // Two peers: the open-channel peer and the closed-channel peer. - openPeerID, err := store.AddPeer(ctx, validPubKey1) - require.NoError(t, err) - closedPeerID, err := store.AddPeer(ctx, validPubKey2) - require.NoError(t, err) - - // Both channels live in the chanevents store. lnd will report the first - // via ListChannels and the second only via ClosedChannels. - openScid := testShortChanID1 - closedScid := testShortChanID2 - openChanID, err := store.AddChannel( - ctx, testChanPoint1, openScid, openPeerID, - ) - require.NoError(t, err) - closedChanID, err := store.AddChannel( - ctx, testChanPoint2, closedScid, closedPeerID, - ) - require.NoError(t, err) - - // Seed an Update event before startTime for each channel so the - // initial-state walk has a non-zero baseline. Without a baseline, the - // closed channel's online state would be false and its presence in the - // result map would not prove the survivorship code path drove it. - seedTime := testTime - for _, chanID := range []int64{openChanID, closedChanID} { - err = store.AddChannelEvent( - ctx, &ChannelEvent{ - ChannelID: chanID, - EventType: EventTypeUpdate, - Timestamp: seedTime, - LocalBalance: fn.Some(btcutil.Amount(1000)), - RemoteBalance: fn.Some(btcutil.Amount(1000)), - }, - ) - require.NoError(t, err) - } - - openVertex, err := route.NewVertexFromStr(validPubKey1) - require.NoError(t, err) - closedVertex, err := route.NewVertexFromStr(validPubKey2) - require.NoError(t, err) - - // lnd reports only the open channel via ListChannels. The closed - // channel surfaces solely through ClosedChannels. - stub := &stubLndChannelClient{ - openChannels: []lndclient.ChannelInfo{ - { - ChannelID: openScid, - PubKeyBytes: openVertex, - }, - }, - closedChannels: []lndclient.ClosedChannel{ - { - ChannelID: closedScid, - PubKeyBytes: closedVertex, - }, - }, - } - - a := NewForwardingAnalyzer(store, lndclient.LndServices{Client: stub}) - - startTime := seedTime.Add(time.Second) - endTime := startTime.Add(time.Minute) - - abilities, err := a.EffectiveUptime(ctx, startTime, endTime, 0) - require.NoError(t, err) - - // Cross-pair entries in both directions are the cleanest assertion - // that the closed-channel peer participates in the walk, not just - // indexes into it. Their presence is the survivorship guarantee - // under test: without merging lnd's ClosedChannels into the - // considered set, neither cross would appear. - require.Contains( - t, abilities, PeerPair{PeerIn: validPubKey1, PeerOut: validPubKey2}, - "closed-channel peer absent: survivorship handling skipped", - ) - require.Contains( - t, abilities, PeerPair{PeerIn: validPubKey2, PeerOut: validPubKey1}, - "closed-channel peer absent: survivorship handling skipped", - ) -} - -// TestEffectiveUptimeArgs exercises the liquidityFloor, startTime, and endTime -// arguments of EffectiveUptime, verifying that the single uniform floor governs -// effective uptime and that forwarded volume is reported regardless of uptime. -func TestEffectiveUptimeArgs(t *testing.T) { - t.Parallel() - - var ( - clk = clock.NewTestClock(testTime) - store = NewTestDB(t, clk) - ctx = context.Background() - ) - - peer1ID, err := store.AddPeer(ctx, validPubKey1) - require.NoError(t, err) - peer2ID, err := store.AddPeer(ctx, validPubKey2) - require.NoError(t, err) - - chan1ID, err := store.AddChannel( - ctx, testChanPoint1, testShortChanID1, peer1ID, - ) - require.NoError(t, err) - chan2ID, err := store.AddChannel( - ctx, testChanPoint2, testShortChanID2, peer2ID, - ) - require.NoError(t, err) - - seedTime := testTime - for _, chanID := range []int64{chan1ID, chan2ID} { - err = store.AddChannelEvent( - ctx, &ChannelEvent{ - ChannelID: chanID, - EventType: EventTypeUpdate, - Timestamp: seedTime, - LocalBalance: fn.Some( - btcutil.Amount(1_000_000), - ), - RemoteBalance: fn.Some( - btcutil.Amount(1_000_000), - ), - }, - ) - require.NoError(t, err) - } - - vertex1, err := route.NewVertexFromStr(validPubKey1) - require.NoError(t, err) - vertex2, err := route.NewVertexFromStr(validPubKey2) - require.NoError(t, err) - - // Stub lnd to return the two channels and successful forwards of 100k - // and 300k satoshis. - stub := &stubLndChannelClient{ - openChannels: []lndclient.ChannelInfo{ - { - ChannelID: testShortChanID1, - PubKeyBytes: vertex1, - }, - { - ChannelID: testShortChanID2, - PubKeyBytes: vertex2, - }, - }, - forwardingHistory: &lndclient.ForwardingHistoryResponse{ - Events: []lndclient.ForwardingEvent{ - { - ChannelIn: testShortChanID1, - ChannelOut: testShortChanID2, - AmountMsatOut: 100_000_000, // 100k sat - }, - { - ChannelIn: testShortChanID1, - ChannelOut: testShortChanID2, - AmountMsatOut: 300_000_000, // 300k sat - }, - }, - }, - } - - a := NewForwardingAnalyzer(store, lndclient.LndServices{Client: stub}) - - startTime := seedTime.Add(time.Second) - endTime := startTime.Add(time.Minute) - - // Case 1: liquidityFloor = 50k. Liquidity of 1M exceeds the floor for - // the whole 60s window, so effective uptime is the full minute and the - // forwarded volume is the 400k sat total. - abilities, err := a.EffectiveUptime(ctx, startTime, endTime, 50_000) - require.NoError(t, err) - - pair := PeerPair{PeerIn: validPubKey1, PeerOut: validPubKey2} - require.Contains(t, abilities, pair) - require.Equal(t, time.Minute, abilities[pair].EffectiveUptime) - require.Equal(t, btcutil.Amount(400_000), abilities[pair].ForwardedAmount) - - // Case 2: liquidityFloor = 1.5M, above the 1M liquidity, so the floor is - // never crossed and effective uptime is zero. The forwarded volume is - // still reported so the consumer keeps the demand signal. - abilities, err = a.EffectiveUptime(ctx, startTime, endTime, 1_500_000) - require.NoError(t, err) - - require.Contains(t, abilities, pair) - require.Zero(t, abilities[pair].EffectiveUptime) - require.Equal(t, btcutil.Amount(400_000), abilities[pair].ForwardedAmount) -} diff --git a/chanevents/chanevents.go b/chanevents/chanevents.go deleted file mode 100644 index 93d08fd..0000000 --- a/chanevents/chanevents.go +++ /dev/null @@ -1,129 +0,0 @@ -// Package chanevents contains functions for monitoring and storing channel -// events such as online/offline and balance updates. -package chanevents - -import ( - "time" - - "github.com/btcsuite/btcd/btcutil" - "github.com/lightningnetwork/lnd/fn/v2" -) - -// Config holds the configuration options for channel event pruning. See the -// README for storage sizing guidance. -type Config struct { - // MaxEvents is the maximum number of channel events to retain. Once the - // table exceeds this count, the oldest events are pruned. This operates - // as a hard ceiling on database size to prevent disk filling. A value - // of 0 disables this limit. - MaxEvents uint64 `long:"max-events" description:"The maximum number of channel events to retain before pruning the oldest events. This limit acts as a hard ceiling to prevent disk filling. A value of 0 disables pruning based on the number of events."` - - // Retention is the minimum duration of channel events to keep. Events - // older than this window are pruned, even if the max-events limit is - // not exceeded. If max-events is exceeded, newer events can still be - // pruned to enforce the size ceiling. A value of 0 disables this limit. - Retention time.Duration `long:"retention" description:"The minimum duration of channel events to keep. Events older than this window are pruned, even if the max-events limit is not exceeded. A value of 0 disables pruning based on age."` -} - -// EventType is an enum for the different types of channel events. -type EventType int16 - -const ( - // EventTypeUnknown is the unknown event type. - EventTypeUnknown EventType = 0 - - // EventTypeOnline is the online event type. - EventTypeOnline EventType = 1 - - // EventTypeOffline is the offline event type. - EventTypeOffline EventType = 2 - - // EventTypeUpdate is the balance update event type. - EventTypeUpdate EventType = 3 -) - -// String returns the string representation of the event type. -func (e EventType) String() string { - switch e { - case EventTypeOnline: - return "online" - - case EventTypeOffline: - return "offline" - - case EventTypeUpdate: - return "update" - - default: - return "unknown" - } -} - -// EventTypeFromString returns the event type from a string. -func EventTypeFromString(s string) EventType { - switch s { - case "online": - return EventTypeOnline - - case "offline": - return EventTypeOffline - - case "update": - return EventTypeUpdate - - default: - return EventTypeUnknown - } -} - -// Peer is the application-level representation of a peer. -type Peer struct { - // ID is the database ID of the peer. - ID int64 - - // PubKey is the public key of the peer. - PubKey string -} - -// Channel is the application-level representation of a channel. -type Channel struct { - // ID is the database ID of the channel. - ID int64 - - // ChannelPoint is the channel point of the channel. - ChannelPoint string - - // ShortChannelID is the short channel ID of the channel. - ShortChannelID uint64 - - // PeerID is the database ID of the peer that this channel is with. - PeerID int64 -} - -// ChannelEvent is the application-level representation of a channel event. -type ChannelEvent struct { - // ID is the database ID of the event. - ID int64 - - // ChannelID is the database ID of the channel that this event is - // associated with. - ChannelID int64 - - // EventType is the type of the event. - EventType EventType - - // Timestamp is the time that the event occurred. - Timestamp time.Time - - // LocalBalance is the local balance of the channel at the time of the - // event. This is only populated for balance update events. - LocalBalance fn.Option[btcutil.Amount] - - // RemoteBalance is the remote balance of the channel at the time of the - // event. This is only populated for balance update events. - RemoteBalance fn.Option[btcutil.Amount] - - // IsSync indicates whether this event was recorded during an initial - // sync rather than from a live subscription. - IsSync bool -} diff --git a/chanevents/log.go b/chanevents/log.go deleted file mode 100644 index 492d337..0000000 --- a/chanevents/log.go +++ /dev/null @@ -1,25 +0,0 @@ -package chanevents - -import ( - "github.com/btcsuite/btclog/v2" - "github.com/lightningnetwork/lnd/build" -) - -const Subsystem = "CHEV" - -// log is a logger that is initialized with no output filters. This -// means the package will not perform any logging by default until the caller -// requests it. -var log btclog.Logger - -// The default amount of logging is none. -func init() { - UseLogger(build.NewSubLogger(Subsystem, nil)) -} - -// UseLogger uses a specified Logger to output package logging info. -// This should be used in preference to SetLogWriter if the caller is also -// using btclog. -func UseLogger(logger btclog.Logger) { - log = logger -} diff --git a/chanevents/monitor.go b/chanevents/monitor.go deleted file mode 100644 index 1d9fa41..0000000 --- a/chanevents/monitor.go +++ /dev/null @@ -1,597 +0,0 @@ -package chanevents - -import ( - "context" - "errors" - "fmt" - "sync" - "sync/atomic" - "time" - - "github.com/btcsuite/btcd/btcutil" - "github.com/lightninglabs/lndclient" - "github.com/lightningnetwork/lnd/fn/v2" - "github.com/lightningnetwork/lnd/routing/route" -) - -const ( - // retryInterval is the time to wait before retrying after a - // transient error or while waiting for lnd to become ready. - retryInterval = 5 * time.Second - - // pruneInterval is how often the monitor enforces the channel event - // storage limits while consuming live events. - pruneInterval = time.Hour - - // minPruneInterval is the floor for the background pruning ticker. A - // tiny retention window would otherwise drive the ticker interval down - // to milliseconds and starve the CPU, so we never tick faster than - // this. - minPruneInterval = time.Second -) - -var ( - // errMonitorAlreadyStarted is returned when the monitor is already - // started. - errMonitorAlreadyStarted = errors.New("monitor already started") - - // errMonitorNotStarted is returned when the monitor is not started. - errMonitorNotStarted = errors.New("monitor not started") -) - -// Monitor is an active component that listens to LND channel events and records -// them in the database. -type Monitor struct { - started atomic.Bool - - // lnd is the lnd client that the monitor will use to subscribe to - // channel events. - lnd lndclient.LightningClient - - // store is the channel events store that the monitor will use to record - // channel events. - store *Store - - // cfg holds the channel event pruning configuration. - cfg Config - - // warnedDestructivePrune ensures the operator is warned only once that - // pruning has permanently deleted events. - warnedDestructivePrune atomic.Bool - - wg sync.WaitGroup - quit chan struct{} -} - -// NewMonitor creates a new channel events monitor. -func NewMonitor(lnd lndclient.LightningClient, store *Store, - cfg Config) *Monitor { - - return &Monitor{ - lnd: lnd, - store: store, - cfg: cfg, - quit: make(chan struct{}), - } -} - -// Start starts the channel events monitor. -func (m *Monitor) Start(ctx context.Context) error { - if !m.started.CompareAndSwap(false, true) { - return errMonitorAlreadyStarted - } - - log.Info("Starting channel events monitor") - - m.quit = make(chan struct{}) - - m.wg.Add(1) - go m.monitorLoop(ctx) - - return nil -} - -// Stop stops the channel events monitor. -func (m *Monitor) Stop() error { - if !m.started.CompareAndSwap(true, false) { - return errMonitorNotStarted - } - - log.Info("Stopping channel events monitor") - - close(m.quit) - m.wg.Wait() - - return nil -} - -// monitorLoop is the main loop of the channel events monitor. It waits for lnd -// to be fully synced, performs an initial state sync, and then subscribes to -// channel events. If the subscription fails or the stream breaks, it retries -// from the beginning. -func (m *Monitor) monitorLoop(ctx context.Context) { - defer m.wg.Done() - - log.Info("Channel events monitor starting") - - // Prune periodically while consuming live events, to bound the query - // overhead on high-frequency channels. Only arm the ticker when pruning - // is actually enabled; otherwise leave pruneChan nil so the select below - // never fires and we don't spin a ticker for nothing. - var pruneChan <-chan time.Time - if m.cfg.MaxEvents > 0 || m.cfg.Retention > 0 { - pruneIntervalToUse := pruneInterval - if m.cfg.Retention > 0 && m.cfg.Retention < pruneIntervalToUse { - pruneIntervalToUse = m.cfg.Retention - - // Never tick faster than the floor: an extremely small - // retention would otherwise spin the ticker continuously. - if pruneIntervalToUse < minPruneInterval { - pruneIntervalToUse = minPruneInterval - } - } - - pruneTicker := time.NewTicker(pruneIntervalToUse) - defer pruneTicker.Stop() - pruneChan = pruneTicker.C - } - - var synced bool - - for { - // Wait for lnd to be synced to chain, retrying on RPC errors. - if !m.waitForReady(ctx) { - return - } - - // Initial state sync, only performed once. - if !synced { - if err := m.initialSync(ctx); err != nil { - log.Errorf("Error during initial sync: %v", err) - } else { - synced = true - - // The initial sync can insert a sizeable number - // of events, so prune once it completes. - m.pruneEvents(ctx) - } - } - - // Subscribe and consume events until the stream breaks or an - // error occurs. - if !m.subscribe(ctx, pruneChan) { - return - } - - // Stream broke, wait before reconnecting. - log.Infof("Reconnecting channel event subscription...") - - select { - case <-time.After(retryInterval): - case <-m.quit: - return - case <-ctx.Done(): - return - } - } -} - -// pruneEvents enforces the configured channel event storage limits, logging -// how many events were deleted. -func (m *Monitor) pruneEvents(ctx context.Context) { - pruned, err := m.store.PruneEvents( - ctx, m.cfg.MaxEvents, m.cfg.Retention, - ) - if err != nil { - log.Errorf("Error pruning channel events: %v", err) - return - } - - if pruned == 0 { - return - } - - // Pruning permanently deletes events, so warn the first time it happens. - // This gives a clear signal to an operator who did not expect the default - // limits to remove pre-existing history. Subsequent prunes log at info - // level. - if m.warnedDestructivePrune.CompareAndSwap(false, true) { - log.Warnf("Pruned %d channel event(s) to enforce storage "+ - "limits (max-events=%d, retention=%v); pruning is "+ - "enabled by default and permanently deletes events", - pruned, m.cfg.MaxEvents, m.cfg.Retention) - } else { - log.Infof("Pruned %d channel event(s) to enforce storage "+ - "limits", pruned) - } -} - -// waitForReady polls lnd's GetInfo until it reports SyncedToChain. It retries -// on transient RPC errors. It returns true when lnd is ready, or false if the -// monitor is shutting down. -func (m *Monitor) waitForReady(ctx context.Context) bool { - for { - info, err := m.lnd.GetInfo(ctx) - if err != nil { - log.Warnf("Error getting lnd info, retrying: %v", err) - } else if info.SyncedToChain { - return true - } else { - log.Infof("Waiting for lnd to sync to chain...") - } - - select { - case <-time.After(retryInterval): - case <-m.quit: - return false - case <-ctx.Done(): - return false - } - } -} - -// subscribe subscribes to lnd channel events and processes them until the -// stream breaks or an error occurs. It returns true on transient failures -// (caller should retry) or false if the monitor is shutting down. -func (m *Monitor) subscribe(ctx context.Context, - pruneChan <-chan time.Time) bool { - - eventChan, errChan, err := m.lnd.SubscribeChannelEvents(ctx) - if err != nil { - log.Errorf("Error subscribing to channel events: %v", err) - - // Return true to signal the caller to retry. - return true - } - - for { - select { - case event, ok := <-eventChan: - if !ok { - log.Warn("Channel event stream closed") - return true - } - if err := m.handleChannelEvent(ctx, event); err != nil { - log.Errorf("Error handling channel event: %v", - err) - } - - case <-pruneChan: - // Periodically enforce the storage limits to keep the - // channel_events table bounded. - m.pruneEvents(ctx) - - case err, ok := <-errChan: - if !ok { - log.Warn("Channel event error stream " + - "closed") - - return true - } - log.Errorf("Error from channel event "+ - "subscription: %v", err) - - return true - - case <-m.quit: - log.Info("Channel events monitor stopping") - return false - - case <-ctx.Done(): - log.Info("Channel events monitor stopping") - return false - } - } -} - -// initialSync performs an initial sync of the channel state. It queries lnd for -// all known channels (open and closed) and records their current state in the -// database. This ensures that any channel events that occurred while faraday -// was offline are accounted for: even though individual events are lost, the -// latest state is captured as a baseline. Events recorded during initial sync -// are marked with IsSync=true to distinguish them from real-time events -// received via the subscription. -func (m *Monitor) initialSync(ctx context.Context) error { - log.Info("Performing initial sync of channel state") - - closedChannels, err := m.lnd.ClosedChannels(ctx) - if err != nil { - return fmt.Errorf("error listing closed channels: %w", err) - } - - for _, channel := range closedChannels { - // Abort if the context has been cancelled. - if ctx.Err() != nil { - return ctx.Err() - } - - // Channels that didn't confirm onchain will be present here, - // but don't have a channel ID. We skip those. - if channel.ChannelID == 0 { - log.Debugf("Skipping closed channel with no "+ - "channel ID: %s", channel.ChannelPoint) - - continue - } - - err := m.addChannel( - ctx, channel.PubKeyBytes, channel.ChannelPoint, - channel.ChannelID, - ) - - if err != nil { - log.Errorf("error adding closed channel %s: %v", - channel.ChannelPoint, err) - - continue - } - - dbChan, err := m.store.GetChannel(ctx, channel.ChannelPoint) - if err != nil { - log.Errorf("error getting closed channel %s from db: %v", - channel.ChannelPoint, err) - - continue - } - - if err := m.store.AddChannelEvent(ctx, &ChannelEvent{ - ChannelID: dbChan.ID, - EventType: EventTypeOffline, - IsSync: true, - }); err != nil { - log.Errorf("error adding offline event for closed "+ - "channel %s: %v", channel.ChannelPoint, err) - } - } - - channels, err := m.lnd.ListChannels(ctx, false, false) - if err != nil { - return fmt.Errorf("error listing channels: %w", err) - } - - for _, channel := range channels { - // Abort if the context has been cancelled. - if ctx.Err() != nil { - return ctx.Err() - } - - // We make sure the channel exists in the store. - err := m.addChannel( - ctx, channel.PubKeyBytes, channel.ChannelPoint, - channel.ChannelID, - ) - if err != nil { - log.Errorf("error adding channel %s: %v", - channel.ChannelPoint, err) - - continue - } - - dbChan, err := m.store.GetChannel(ctx, channel.ChannelPoint) - if err != nil { - log.Errorf("error getting channel %s from db: %v", - channel.ChannelPoint, err) - - continue - } - - eventType := EventTypeOffline - if channel.Active { - eventType = EventTypeOnline - } - - if err := m.store.AddChannelEvent(ctx, &ChannelEvent{ - ChannelID: dbChan.ID, - EventType: eventType, - IsSync: true, - }); err != nil { - log.Errorf("error adding event for channel %s: %v", - channel.ChannelPoint, err) - } - - // We add the update event separately from the online/offline - // event above, because each event type serves a different - // purpose: the online/offline event tracks channel - // availability, while the update event captures a balance - // snapshot. Keeping them as distinct records allows querying - // availability and balance history independently. - if err := m.store.AddChannelEvent(ctx, &ChannelEvent{ - ChannelID: dbChan.ID, - EventType: EventTypeUpdate, - LocalBalance: fn.Some(channel.LocalBalance), - RemoteBalance: fn.Some(channel.RemoteBalance), - IsSync: true, - }); err != nil { - log.Errorf("error adding event for channel %s: %v", - channel.ChannelPoint, err) - } - } - - return nil -} - -// addChannel adds a channel and its peer to the store. -func (m *Monitor) addChannel(ctx context.Context, pubKeyBytes route.Vertex, - channelPoint string, channelID uint64) error { - - // Check if the channel already exists. - channel, err := m.store.GetChannel(ctx, channelPoint) - if err != nil && !errors.Is(err, ErrUnknownChannel) { - return fmt.Errorf("error getting channel %s: %w", - channelPoint, err) - } - if channel != nil { - // Channel already exists, nothing to do. - return nil - } - - // Check if peer already exists. - peer, err := m.store.GetPeer(ctx, pubKeyBytes.String()) - if err != nil && !errors.Is(err, errUnknownPeer) { - return fmt.Errorf("error getting peer %s: %w", - pubKeyBytes, err) - } - - var peerID int64 - if peer != nil { - peerID = peer.ID - } else { - peerID, err = m.store.AddPeer( - ctx, pubKeyBytes.String(), - ) - if err != nil { - return fmt.Errorf("error adding peer %s: %w", - pubKeyBytes, err) - } - } - - _, err = m.store.AddChannel(ctx, channelPoint, channelID, peerID) - if err != nil { - return fmt.Errorf("error adding channel %s: %w", - channelPoint, err) - } - - log.Infof("Added channel %s to db", channelPoint) - - return nil -} - -// handleChannelEvent handles a single channel event. -func (m *Monitor) handleChannelEvent(ctx context.Context, - event *lndclient.ChannelEventUpdate) error { - - switch event.UpdateType { - case lndclient.OpenChannelUpdate: - openChannel := event.OpenedChannelInfo - if openChannel == nil { - return fmt.Errorf("open_channel event is nil") - } - - log.Debugf("Handling open channel event: %+v", openChannel) - - // We add the new channel to the store. - if err := m.addChannel( - ctx, openChannel.PubKeyBytes, openChannel.ChannelPoint, - openChannel.ChannelID, - ); err != nil { - return err - } - - // Now add the online and update events. - dbChan, err := m.store.GetChannel(ctx, openChannel.ChannelPoint) - if err != nil { - return err - } - - if err := m.store.AddChannelEvent(ctx, &ChannelEvent{ - ChannelID: dbChan.ID, - EventType: EventTypeOnline, - }); err != nil { - return err - } - - return m.addUpdateEvent(ctx, openChannel) - - case lndclient.ClosedChannelUpdate: - if event.ClosedChannelInfo == nil { - return fmt.Errorf("closed_channel event is nil") - } - - log.Debugf("Handling offline channel event: %+v", - event.ClosedChannelInfo) - - return m.addOfflineEvent(ctx, - event.ClosedChannelInfo.ChannelPoint) - - case lndclient.ActiveChannelUpdate: - log.Debugf("Handling active channel event: %v", - event.ChannelPoint) - - return m.addOnlineEvent(ctx, event.ChannelPoint.String()) - - case lndclient.InactiveChannelUpdate: - log.Debugf("Handling offline channel event: %v", - event.ChannelPoint) - - return m.addOfflineEvent(ctx, event.ChannelPoint.String()) - - case lndclient.PendingOpenChannelUpdate: - log.Debugf("Ignoring pending channel event: %v", - event.ChannelPoint) - - return nil - - case lndclient.StateChannelUpdate: - if event.UpdatedChannelInfo == nil { - return fmt.Errorf("state_update event is nil") - } - - log.Debugf("Handling channel update event: %+v", - event.UpdatedChannelInfo) - - return m.addUpdateEvent(ctx, event.UpdatedChannelInfo) - } - - return nil -} - -// addOnlineEvent adds an online event for a channel. -func (m *Monitor) addOnlineEvent(ctx context.Context, - channelPoint string) error { - - channel, err := m.store.GetChannel(ctx, channelPoint) - if err != nil { - return fmt.Errorf("error getting channel %s: %w", channelPoint, - err) - } - - log.Infof("Adding online event for channel %s", channelPoint) - - return m.store.AddChannelEvent(ctx, &ChannelEvent{ - ChannelID: channel.ID, - EventType: EventTypeOnline, - }) -} - -// addOfflineEvent adds an offline event for a channel. -func (m *Monitor) addOfflineEvent(ctx context.Context, - channelPoint string) error { - - channel, err := m.store.GetChannel(ctx, channelPoint) - if err != nil { - return fmt.Errorf("error getting channel %s: %w", channelPoint, - err) - } - - log.Infof("Adding offline event for channel %s", channelPoint) - - return m.store.AddChannelEvent(ctx, &ChannelEvent{ - ChannelID: channel.ID, - EventType: EventTypeOffline, - }) -} - -// addUpdateEvent adds an update event for a channel. -func (m *Monitor) addUpdateEvent(ctx context.Context, - channelInfo *lndclient.ChannelInfo) error { - - channel, err := m.store.GetChannel(ctx, channelInfo.ChannelPoint) - if err != nil { - return fmt.Errorf("error getting channel %s: %w", - channelInfo.ChannelPoint, err) - } - - log.Tracef("Adding update event for channel %s", - channelInfo.ChannelPoint) - - return m.store.AddChannelEvent(ctx, &ChannelEvent{ - ChannelID: channel.ID, - EventType: EventTypeUpdate, - LocalBalance: fn.Some( - btcutil.Amount(channelInfo.LocalBalance), - ), - RemoteBalance: fn.Some( - btcutil.Amount(channelInfo.RemoteBalance), - ), - }) -} diff --git a/chanevents/store.go b/chanevents/store.go deleted file mode 100644 index 1b13b3a..0000000 --- a/chanevents/store.go +++ /dev/null @@ -1,424 +0,0 @@ -package chanevents - -import ( - "context" - "database/sql" - "errors" - "fmt" - "math" - "time" - - "github.com/btcsuite/btcd/btcutil" - "github.com/lightninglabs/faraday/db/sqlc" - "github.com/lightningnetwork/lnd/clock" - "github.com/lightningnetwork/lnd/fn/v2" - "github.com/lightningnetwork/lnd/sqldb/v2" -) - -var ( - errUnknownPeer = errors.New("unknown peer") - - // ErrUnknownChannel signals that the requested channel is not - // present in the store. - ErrUnknownChannel = errors.New("unknown channel") -) - -// Queries is a subset of the sqlc.Queries interface that can be used to -// interact with the peers, channels and channel_events tables. -type Queries interface { - InsertPeer(ctx context.Context, pubkey string) (int64, error) - - GetPeerByPubKey(ctx context.Context, pubkey string) (sqlc.Peer, error) - - InsertChannel(ctx context.Context, - arg sqlc.InsertChannelParams) (int64, error) - - GetChannelByChanPoint(ctx context.Context, - channelPoint string) (sqlc.Channel, error) - - GetChannelByShortChanID(ctx context.Context, - shortChannelID int64) (sqlc.Channel, error) - - InsertChannelEvent(ctx context.Context, - arg sqlc.InsertChannelEventParams) error - - GetChannelEvents(ctx context.Context, - arg sqlc.GetChannelEventsParams) ([]sqlc.ChannelEvent, error) - - GetLatestChannelEventBefore(ctx context.Context, - arg sqlc.GetLatestChannelEventBeforeParams) ( - sqlc.ChannelEvent, - error, - ) - - GetChannels(ctx context.Context) ([]sqlc.GetChannelsRow, error) - - PruneChannelEventsBySize(ctx context.Context, offset int32) (int64, - error) - - PruneChannelEventsByAge(ctx context.Context, timestamp time.Time) ( - int64, error) -} - -// Store provides access to the db for channel events. -type Store struct { - // db is all the higher level queries that the SQLStore has access to in - // order to implement all its CRUD logic. - db BatchedSQLQueries - - // BaseDB represents the underlying database connection. - *sqldb.BaseDB - - clock clock.Clock -} - -// BatchedSQLQueries combines the SQLQueries interface with the BatchedTx -// interface, allowing for multiple queries to be executed in single SQL -// transaction. -type BatchedSQLQueries interface { - SQLQueries - - sqldb.BatchedTx[SQLQueries] -} - -// SQLQueries is a subset of the sqlc.Queries interface that can be used to -// interact with various chanevents tables. -type SQLQueries interface { - sqldb.BaseQuerier - - Queries -} - -type SQLQueriesExecutor[T sqldb.BaseQuerier] struct { - *sqldb.TransactionExecutor[T] - - SQLQueries -} - -// NewStore creates a new SQLStore instance given an open SQLQueries storage -// backend. -func NewStore(sqlDB *sqldb.BaseDB, queries *sqlc.Queries, - clock clock.Clock) *Store { - - txExecutor := sqldb.NewTransactionExecutor( - sqlDB, - func(tx *sql.Tx) SQLQueries { - return queries.WithTx(tx) - }, - ) - - executor := &SQLQueriesExecutor[SQLQueries]{ - TransactionExecutor: txExecutor, - SQLQueries: queries, - } - - return &Store{ - db: executor, - BaseDB: sqlDB, - clock: clock, - } -} - -// AddPeer adds a new peer to the database. -func (s *Store) AddPeer(ctx context.Context, pubkey string) (int64, error) { - id, err := s.db.InsertPeer(ctx, pubkey) - if err != nil { - return 0, fmt.Errorf("failed to insert peer: %w", err) - } - - return id, nil -} - -// GetPeer retrieves a peer by their public key. -func (s *Store) GetPeer(ctx context.Context, pubkey string) (*Peer, error) { - dbPeer, err := s.db.GetPeerByPubKey(ctx, pubkey) - if err != nil { - if errors.Is(err, sql.ErrNoRows) { - return nil, errUnknownPeer - } - - return nil, fmt.Errorf("failed to get peer: %w", err) - } - - return &Peer{ - ID: dbPeer.ID, - PubKey: dbPeer.Pubkey, - }, nil -} - -// int64ToSCID converts an int64 to a uint64 ShortChannelID. The BOLT spec -// encodes SCIDs as uint64, but SQL only supports signed int64. We preserve the -// bits, which means SCIDs with the high bit set will appear negative in the -// database. Direct SQL queries (e.g. ORDER BY short_channel_id) will not sort -// these correctly, but round-tripping through Go preserves the value. -func int64ToSCID(i int64) uint64 { - return uint64(i) -} - -// scidToInt64 converts a uint64 ShortChannelID to an int64 for SQL storage. -func scidToInt64(u uint64) int64 { - return int64(u) -} - -// AddChannel adds a new channel for a peer. -func (s *Store) AddChannel(ctx context.Context, channelPoint string, - shortChannelID uint64, peerID int64) (int64, error) { - - id, err := s.db.InsertChannel( - ctx, sqlc.InsertChannelParams{ - ChannelPoint: channelPoint, - ShortChannelID: scidToInt64(shortChannelID), - PeerID: peerID, - }, - ) - if err != nil { - return 0, fmt.Errorf("failed to insert channel: %w", err) - } - - return id, nil -} - -// GetChannel retrieves a channel by its channel point. -func (s *Store) GetChannel(ctx context.Context, channelPoint string) (*Channel, - error) { - - dbChannel, err := s.db.GetChannelByChanPoint(ctx, channelPoint) - if err != nil { - if errors.Is(err, sql.ErrNoRows) { - return nil, ErrUnknownChannel - } - - return nil, fmt.Errorf("failed to get channel: %w", err) - } - - return &Channel{ - ID: dbChannel.ID, - ChannelPoint: dbChannel.ChannelPoint, - ShortChannelID: int64ToSCID(dbChannel.ShortChannelID), - PeerID: dbChannel.PeerID, - }, nil -} - -// GetChannelByShortChanID retrieves a channel by its short channel ID, -// returning ErrUnknownChannel if no row matches. -func (s *Store) GetChannelByShortChanID(ctx context.Context, - shortChannelID uint64) (*Channel, error) { - - dbChannel, err := s.db.GetChannelByShortChanID( - ctx, scidToInt64(shortChannelID), - ) - if err != nil { - if errors.Is(err, sql.ErrNoRows) { - return nil, ErrUnknownChannel - } - - return nil, err - } - - return &Channel{ - ID: dbChannel.ID, - ChannelPoint: dbChannel.ChannelPoint, - ShortChannelID: int64ToSCID(dbChannel.ShortChannelID), - PeerID: dbChannel.PeerID, - }, nil -} - -// AddChannelEvent adds a new channel event. -func (s *Store) AddChannelEvent(ctx context.Context, - event *ChannelEvent) error { - - log.Tracef("Adding channel event: %+v", event) - - var localBalance sql.NullInt64 - event.LocalBalance.WhenSome( - func(b btcutil.Amount) { - localBalance.Int64 = int64(b) - localBalance.Valid = true - }, - ) - - var remoteBalance sql.NullInt64 - event.RemoteBalance.WhenSome( - func(b btcutil.Amount) { - remoteBalance.Int64 = int64(b) - remoteBalance.Valid = true - }, - ) - - timestamp := event.Timestamp.UTC() - if timestamp.IsZero() { - timestamp = s.clock.Now().UTC() - } - - err := s.db.InsertChannelEvent( - ctx, sqlc.InsertChannelEventParams{ - ChannelID: event.ChannelID, - EventType: int16(event.EventType), - Timestamp: timestamp, - LocalBalanceSat: localBalance, - RemoteBalanceSat: remoteBalance, - IsSync: event.IsSync, - }, - ) - if err != nil { - return fmt.Errorf("failed to insert channel event: %w", err) - } - - return nil -} - -// GetChannelEvents returns up to limit events for a channel where -// id > afterID AND startTime <= timestamp < endTime, ordered by id ASC. -// Pass afterID = 0 on the first call; for subsequent calls pass the -// previous page's last event id. The (startTime, endTime) bounds are -// independent filters and do not need to advance between pages. -func (s *Store) GetChannelEvents(ctx context.Context, channelID, afterID int64, - startTime, endTime time.Time, limit int32) ([]*ChannelEvent, error) { - - dbEvents, err := s.db.GetChannelEvents( - ctx, sqlc.GetChannelEventsParams{ - ChannelID: channelID, - ID: afterID, - Timestamp: startTime.UTC(), - Timestamp_2: endTime.UTC(), - Limit: limit, - }, - ) - if err != nil { - return nil, fmt.Errorf("failed to get channel events: %w", err) - } - - events := make([]*ChannelEvent, len(dbEvents)) - for i, dbEvent := range dbEvents { - events[i] = marshalChannelEvent(dbEvent) - } - - return events, nil -} - -// ScidToPeerMap returns the historic scid→peer index, including channels that -// have since closed. Unconfirmed channels (scid still zero) are not part of -// the contract. -func (s *Store) ScidToPeerMap(ctx context.Context) (map[uint64]string, error) { - dbChannels, err := s.db.GetChannels(ctx) - if err != nil { - return nil, err - } - - scidToPeer := make(map[uint64]string, len(dbChannels)) - for _, dbChannel := range dbChannels { - // The short channel ID can be zero if it's not known yet. We - // should just ignore those. - if dbChannel.ShortChannelID == 0 { - continue - } - - scidToPeer[uint64(dbChannel.ShortChannelID)] = dbChannel.Pubkey - } - - return scidToPeer, nil -} - -// GetLatestChannelUpdateBefore returns the latest channel event before a given -// time (exclusive). If no event is found, it returns (nil, nil). -func (s *Store) GetLatestChannelUpdateBefore(ctx context.Context, - channelID int64, before time.Time) (*ChannelEvent, error) { - - dbEvent, err := s.db.GetLatestChannelEventBefore( - ctx, sqlc.GetLatestChannelEventBeforeParams{ - ChannelID: channelID, - Timestamp: before.UTC(), - EventType: int16(EventTypeUpdate), - }, - ) - if err != nil { - // If there are no events before the start time, we return (nil, - // nil). - if errors.Is(err, sql.ErrNoRows) { - return nil, nil - } - - return nil, err - } - - return marshalChannelEvent(dbEvent), nil -} - -// PruneEvents enforces the size and age storage limits independently, -// returning the number of events deleted. A zero maxEvents or retention -// disables the corresponding limit, and zero for both disables pruning. -func (s *Store) PruneEvents(ctx context.Context, maxEvents uint64, - retention time.Duration) (int64, error) { - - // If both options are 0, pruning is completely disabled. - if maxEvents == 0 && retention == 0 { - return 0, nil - } - - var pruned int64 - - // Enforce the size ceiling by keeping only the newest maxEvents rows. - // An offset of (maxEvents - 1) lands on the oldest row we want to keep, - // so everything with a smaller id is deleted. - if maxEvents > 0 { - // The size limit becomes an int32 SQL OFFSET below. ValidateConfig - // already rejects an out-of-range max-events, but it is not run on - // every initialization path (e.g. when faraday runs as a - // subserver), so guard the cast here too: an overflowing value - // would wrap to a tiny offset and prune almost the entire table. - if maxEvents > math.MaxInt32 { - return pruned, fmt.Errorf("maxEvents %d exceeds maximum "+ - "allowed value %d", maxEvents, math.MaxInt32) - } - - bySize, err := s.db.PruneChannelEventsBySize( - ctx, int32(maxEvents-1), - ) - if err != nil { - return pruned, fmt.Errorf("failed to prune channel "+ - "events by size: %w", err) - } - - pruned += bySize - } - - // Enforce the retention window by deleting anything older than the - // cutoff. - if retention > 0 { - cutoff := s.clock.Now().UTC().Add(-retention) - byAge, err := s.db.PruneChannelEventsByAge(ctx, cutoff) - if err != nil { - return pruned, fmt.Errorf("failed to prune channel "+ - "events by age: %w", err) - } - - pruned += byAge - } - - return pruned, nil -} - -// marshalChannelEvent converts a db channel event into our internal type. -func marshalChannelEvent(dbEvent sqlc.ChannelEvent) *ChannelEvent { - var localBalance fn.Option[btcutil.Amount] - if dbEvent.LocalBalanceSat.Valid { - amt := btcutil.Amount(dbEvent.LocalBalanceSat.Int64) - localBalance = fn.Some(amt) - } - - var remoteBalance fn.Option[btcutil.Amount] - if dbEvent.RemoteBalanceSat.Valid { - amt := btcutil.Amount(dbEvent.RemoteBalanceSat.Int64) - remoteBalance = fn.Some(amt) - } - - return &ChannelEvent{ - ID: dbEvent.ID, - ChannelID: dbEvent.ChannelID, - EventType: EventType(dbEvent.EventType), - Timestamp: dbEvent.Timestamp.UTC(), - LocalBalance: localBalance, - RemoteBalance: remoteBalance, - IsSync: dbEvent.IsSync, - } -} diff --git a/chanevents/store_test.go b/chanevents/store_test.go deleted file mode 100644 index bb5a49c..0000000 --- a/chanevents/store_test.go +++ /dev/null @@ -1,475 +0,0 @@ -package chanevents - -import ( - "context" - "testing" - "time" - - "github.com/btcsuite/btcd/btcutil" - "github.com/lightningnetwork/lnd/clock" - "github.com/lightningnetwork/lnd/fn/v2" - "github.com/stretchr/testify/require" -) - -var ( - testPubKey = "028d4c6347426f2e3f5e2b8e4a1c3b9f1" + - "c4e5d6f7a8b9c0d1e2f3a4b5c6d7e8f9" - testChanPoint1 = "test_txid:0" - testChanPoint2 = "test_txid:1" - testShortChanID1 uint64 = 123 - testShortChanID2 uint64 = 456 - - testTime = time.Unix(1, 0) -) - -// requireEqualEvent asserts that a retrieved event matches the expected values, -// comparing only the fields that are set before insertion (ignoring the -// auto-assigned ID). -func requireEqualEvent(t *testing.T, expected *ChannelEvent, - expectedTime time.Time, actual *ChannelEvent) { - - t.Helper() - - require.Equal(t, expected.ChannelID, actual.ChannelID) - require.Equal(t, expected.EventType, actual.EventType) - require.Equal(t, expectedTime.Unix(), actual.Timestamp.Unix()) - require.Equal(t, expected.LocalBalance, actual.LocalBalance) - require.Equal(t, expected.RemoteBalance, actual.RemoteBalance) - require.Equal(t, expected.IsSync, actual.IsSync) -} - -// TestStore tests the chanevents store. -func TestStore(t *testing.T) { - t.Parallel() - - // First, create a new test database. - clock := clock.NewTestClock(testTime) - store := NewTestDB(t, clock) - ctx := context.Background() - - // *** Peers *** Add a peer. - peer := &Peer{PubKey: testPubKey} - peerID, err := store.AddPeer(ctx, peer.PubKey) - require.NoError(t, err) - require.NotZero(t, peerID) - - // Adding the same peer again violates the unique constraint. - _, err = store.AddPeer(ctx, peer.PubKey) - require.Error(t, err) - - dbPeer, err := store.GetPeer(ctx, "non_existent_pubkey") - require.ErrorIs(t, err, errUnknownPeer) - require.Nil(t, dbPeer) - - // Get the peer and assert it is the same. - dbPeer, err = store.GetPeer(ctx, peer.PubKey) - require.NoError(t, err) - require.Equal(t, peer.PubKey, dbPeer.PubKey) - - // *** Channels *** Add a channel for an unknown peer and assert an - // error is returned. - channelID, err := store.AddChannel( - ctx, testChanPoint1, testShortChanID1, 9999, - ) - require.Error(t, err) - require.Zero(t, channelID) - - // Add a channel for the peer. - channelID, err = store.AddChannel( - ctx, testChanPoint1, testShortChanID1, peerID, - ) - require.NoError(t, err) - require.NotZero(t, channelID) - - // Get a non-existent channel and assert an error is returned. - dbChannel, err := store.GetChannel(ctx, "non-existent-chan-point") - require.ErrorIs(t, err, ErrUnknownChannel) - require.Nil(t, dbChannel) - - // Get the channel and assert it is the same. - dbChannel, err = store.GetChannel(ctx, testChanPoint1) - require.NoError(t, err) - require.Equal(t, testChanPoint1, dbChannel.ChannelPoint) - require.Equal(t, testShortChanID1, dbChannel.ShortChannelID) - require.Equal(t, peerID, dbChannel.PeerID) - - // Look up the same channel by its scid; the analyzer relies on this - // inverse of AddChannel. - dbChannel, err = store.GetChannelByShortChanID(ctx, testShortChanID1) - require.NoError(t, err) - require.Equal(t, channelID, dbChannel.ID) - require.Equal(t, testChanPoint1, dbChannel.ChannelPoint) - require.Equal(t, testShortChanID1, dbChannel.ShortChannelID) - require.Equal(t, peerID, dbChannel.PeerID) - - // An unknown scid surfaces the typed sentinel, not raw sql.ErrNoRows. - dbChannel, err = store.GetChannelByShortChanID(ctx, 9999) - require.ErrorIs(t, err, ErrUnknownChannel) - require.Nil(t, dbChannel) - - // Add a second channel for the same peer. - channel2ID, err := store.AddChannel( - ctx, testChanPoint2, testShortChanID2, peerID, - ) - require.NoError(t, err) - require.NotZero(t, channel2ID) - - // Get the historic channel to peer map. - chanToPeer, err := store.ScidToPeerMap(ctx) - require.NoError(t, err) - require.Len(t, chanToPeer, 2) - require.Equal(t, testPubKey, chanToPeer[testShortChanID1]) - require.Equal(t, testPubKey, chanToPeer[testShortChanID2]) - - // Add an online event for the channel. - onlineEvent := &ChannelEvent{ - ChannelID: channelID, - EventType: EventTypeOnline, - } - err = store.AddChannelEvent(ctx, onlineEvent) - require.NoError(t, err) - - // Advance the clock for the next event. - clock.SetTime(testTime.Add(time.Second)) - - // Add an update event for the channel. - localBalance := btcutil.Amount(1000) - remoteBalance := btcutil.Amount(2000) - updateEvent := &ChannelEvent{ - ChannelID: channelID, - EventType: EventTypeUpdate, - LocalBalance: fn.Some(localBalance), - RemoteBalance: fn.Some(remoteBalance), - } - err = store.AddChannelEvent(ctx, updateEvent) - require.NoError(t, err) - - // Get the channel events and assert they are correct. - events, err := store.GetChannelEvents( - ctx, channelID, 0, time.Unix(0, 0), time.Unix(3, 0), 100, - ) - require.NoError(t, err) - require.Len(t, events, 2) - - requireEqualEvent(t, onlineEvent, testTime, events[0]) - requireEqualEvent( - t, updateEvent, testTime.Add(time.Second), events[1], - ) - updateEvent = events[1] - - // If we query a time after the update event, we'll obtain the update - // event as the latest event. - initEvent, err := store.GetLatestChannelUpdateBefore( - ctx, channelID, updateEvent.Timestamp.Add(500*time.Millisecond), - ) - require.NoError(t, err) - requireEqualEvent(t, updateEvent, testTime.Add(time.Second), initEvent) - - // If we query at the update event's timestamp, the only event before - // that is left is the online event, which is not an update. - initEvent, err = store.GetLatestChannelUpdateBefore( - ctx, channelID, updateEvent.Timestamp, - ) - require.NoError(t, err) - require.Nil(t, initEvent) - - // Advance the clock and add a sync event to verify the IsSync flag - // round-trips correctly. - clock.SetTime(testTime.Add(2 * time.Second)) - - syncEvent := &ChannelEvent{ - ChannelID: channelID, - EventType: EventTypeOnline, - IsSync: true, - } - err = store.AddChannelEvent(ctx, syncEvent) - require.NoError(t, err) - - events, err = store.GetChannelEvents( - ctx, channelID, 0, time.Unix(0, 0), time.Unix(4, 0), 100, - ) - require.NoError(t, err) - require.Len(t, events, 3) - - requireEqualEvent( - t, syncEvent, testTime.Add(2*time.Second), events[2], - ) -} - -// pruneFixture is an isolated environment for a single TestPruneEvents case. It -// holds a fresh store with two channels and a fixed clock, and exposes helpers -// to seed events and inspect the table without leaking state between cases. -type pruneFixture struct { - t *testing.T - store *Store - ctx context.Context - chan1 int64 - chan2 int64 - now time.Time - old time.Time - recent time.Time -} - -// newPruneFixture builds a fresh store with two channels on one peer and pins -// the clock to a reference point. It derives an "old" timestamp well outside -// and a "recent" timestamp well inside a 30-day retention window. -func newPruneFixture(t *testing.T) *pruneFixture { - t.Helper() - - clk := clock.NewTestClock(testTime) - store := NewTestDB(t, clk) - ctx := context.Background() - - peerID, err := store.AddPeer(ctx, testPubKey) - require.NoError(t, err) - - chan1, err := store.AddChannel( - ctx, testChanPoint1, testShortChanID1, peerID, - ) - require.NoError(t, err) - - chan2, err := store.AddChannel( - ctx, testChanPoint2, testShortChanID2, peerID, - ) - require.NoError(t, err) - - now := testTime.Add(100 * 24 * time.Hour) - clk.SetTime(now) - - return &pruneFixture{ - t: t, - store: store, - ctx: ctx, - chan1: chan1, - chan2: chan2, - now: now, - old: now.Add(-90 * 24 * time.Hour), - recent: now.Add(-5 * 24 * time.Hour), - } -} - -// addEvents inserts n update events on the given channel at timestamp ts. -func (f *pruneFixture) addEvents(channelID int64, ts time.Time, n int) { - f.t.Helper() - - for i := 0; i < n; i++ { - err := f.store.AddChannelEvent(f.ctx, &ChannelEvent{ - ChannelID: channelID, - EventType: EventTypeUpdate, - Timestamp: ts, - }) - require.NoError(f.t, err) - } -} - -// events returns all stored events for a single channel. -func (f *pruneFixture) events(channelID int64) []*ChannelEvent { - f.t.Helper() - - events, err := f.store.GetChannelEvents( - f.ctx, channelID, 0, time.Unix(0, 0), f.now.Add(time.Hour), - 1000, - ) - require.NoError(f.t, err) - - return events -} - -// count returns the total number of events across both channels. -func (f *pruneFixture) count() int { - return len(f.events(f.chan1)) + len(f.events(f.chan2)) -} - -// requireAllRecent asserts that every surviving event lies within the -// retention window, confirming age-based pruning drops the old events rather -// than the recent ones. -func (f *pruneFixture) requireAllRecent() { - f.t.Helper() - - all := append(f.events(f.chan1), f.events(f.chan2)...) - for _, e := range all { - require.Equal(f.t, f.recent.Unix(), e.Timestamp.Unix()) - } -} - -// TestPruneEvents verifies that PruneEvents enforces the max-events count and -// the retention window independently. Each case runs against its own fresh -// store so the size and age limits can be exercised in isolation. -func TestPruneEvents(t *testing.T) { - t.Parallel() - - const retention = 30 * 24 * time.Hour - - tests := []struct { - name string - seed func(f *pruneFixture) - maxEvents uint64 - retention time.Duration - wantTotal int - verify func(f *pruneFixture) - }{{ - // Pruning an empty table succeeds and deletes nothing. - name: "empty database", - maxEvents: 10, - retention: retention, - wantTotal: 0, - }, { - // A count equal to max-events is at the ceiling, not over it, - // so all events are kept. - name: "count equal to max-events keeps all", - seed: func(f *pruneFixture) { - f.addEvents(f.chan1, f.recent, 5) - }, - maxEvents: 5, - retention: retention, - wantTotal: 5, - }, { - // Both limits zero disables pruning entirely, even for events - // outside the retention window. - name: "both limits zero disables pruning", - seed: func(f *pruneFixture) { - f.addEvents(f.chan1, f.recent, 5) - f.addEvents(f.chan1, f.old, 3) - }, - maxEvents: 0, - retention: 0, - wantTotal: 8, - }, { - // The age limit alone drops events older than the window and - // keeps the recent ones. - name: "age limit prunes old events", - seed: func(f *pruneFixture) { - f.addEvents(f.chan1, f.recent, 5) - f.addEvents(f.chan1, f.old, 3) - }, - maxEvents: 0, - retention: retention, - wantTotal: 5, - verify: func(f *pruneFixture) { - f.requireAllRecent() - }, - }, { - // The size limit bounds the global table across channels and - // keeps the newest events, even when all are inside the - // retention window. Channel 2 is seeded last, so its events - // have the newest ids and must be the survivors. - name: "size limit prunes oldest across channels", - seed: func(f *pruneFixture) { - f.addEvents(f.chan1, f.recent, 5) - f.addEvents(f.chan2, f.recent, 5) - }, - maxEvents: 4, - retention: retention, - wantTotal: 4, - verify: func(f *pruneFixture) { - require.Empty(f.t, f.events(f.chan1)) - require.Len(f.t, f.events(f.chan2), 4) - }, - }, { - // With the size ceiling not exceeded, the age limit still - // prunes old events independently. - name: "age limit prunes with size headroom", - seed: func(f *pruneFixture) { - f.addEvents(f.chan2, f.recent, 4) - f.addEvents(f.chan1, f.old, 3) - }, - maxEvents: 10, - retention: retention, - wantTotal: 4, - verify: func(f *pruneFixture) { - f.requireAllRecent() - }, - }, { - // Retention zero disables the age limit. With the count under - // max-events nothing is pruned. - name: "retention zero disables age limit", - seed: func(f *pruneFixture) { - f.addEvents(f.chan2, f.recent, 4) - }, - maxEvents: 10, - retention: 0, - wantTotal: 4, - }, { - // Max-events zero disables the size limit. The age limit still - // prunes old events on its own. - name: "max-events zero leaves age limit active", - seed: func(f *pruneFixture) { - f.addEvents(f.chan2, f.recent, 4) - f.addEvents(f.chan1, f.old, 3) - }, - maxEvents: 0, - retention: retention, - wantTotal: 4, - verify: func(f *pruneFixture) { - f.requireAllRecent() - }, - }} - - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - - f := newPruneFixture(t) - if tc.seed != nil { - tc.seed(f) - } - - _, err := f.store.PruneEvents( - f.ctx, tc.maxEvents, tc.retention, - ) - require.NoError(t, err) - require.Equal(t, tc.wantTotal, f.count()) - - if tc.verify != nil { - tc.verify(f) - } - }) - } -} - -// TestPagination verifies that the keyset cursor advances correctly across -// events sharing one second-resolution timestamp. -func TestPagination(t *testing.T) { - t.Parallel() - - clock := clock.NewTestClock(testTime) - store := NewTestDB(t, clock) - ctx := context.Background() - - peerID, err := store.AddPeer(ctx, testPubKey) - require.NoError(t, err) - - channelID, err := store.AddChannel( - ctx, testChanPoint1, testShortChanID1, peerID, - ) - require.NoError(t, err) - - sameTime := testTime.Add(10 * time.Second) - for i := 0; i < 5; i++ { - err = store.AddChannelEvent(ctx, &ChannelEvent{ - ChannelID: channelID, - EventType: EventTypeUpdate, - Timestamp: sameTime, - LocalBalance: fn.Some(btcutil.Amount(i)), - }) - require.NoError(t, err) - } - - endTime := sameTime.Add(time.Hour) - - page1, err := store.GetChannelEvents( - ctx, channelID, 0, time.Unix(0, 0), endTime, 3, - ) - require.NoError(t, err) - require.Len(t, page1, 3) - - page2, err := store.GetChannelEvents( - ctx, channelID, page1[len(page1)-1].ID, - time.Unix(0, 0), endTime, 3, - ) - require.NoError(t, err) - require.Len(t, page2, 2) - - require.Equal(t, btcutil.Amount(3), page2[0].LocalBalance.UnwrapOr(0)) - require.Equal(t, btcutil.Amount(4), page2[1].LocalBalance.UnwrapOr(0)) -} diff --git a/chanevents/test_postgres.go b/chanevents/test_postgres.go deleted file mode 100644 index 5277a02..0000000 --- a/chanevents/test_postgres.go +++ /dev/null @@ -1,29 +0,0 @@ -//go:build test_db_postgres - -package chanevents - -import ( - "testing" - - "github.com/lightninglabs/faraday/db" - "github.com/lightningnetwork/lnd/clock" - "github.com/stretchr/testify/require" -) - -// NewTestDB creates a new test chanevents.Store backed by a postgres DB. -func NewTestDB(t testing.TB, clock clock.Clock) *Store { - // We'll create a new test database. The call to NewTestPostgresDB will - // automatically create the DB and apply the migrations. - testDB := db.NewTestPostgresDB(t) - - // Now, we'll create the FaradayDB instance from the test database. The - // FaradayDB is the main database object that holds the connection and - // the generated querier. - faradayDB := createStore(t, testDB.BaseDB, clock) - - t.Cleanup(func() { - require.NoError(t, faradayDB.Close()) - }) - - return faradayDB -} diff --git a/chanevents/test_sql.go b/chanevents/test_sql.go deleted file mode 100644 index 9ff7a93..0000000 --- a/chanevents/test_sql.go +++ /dev/null @@ -1,18 +0,0 @@ -package chanevents - -import ( - "testing" - - "github.com/lightninglabs/faraday/db/sqlc" - "github.com/lightningnetwork/lnd/clock" - "github.com/lightningnetwork/lnd/sqldb/v2" -) - -// createStore is a helper function that creates a new Store. -func createStore(t testing.TB, sqlDB *sqldb.BaseDB, clock clock.Clock) *Store { - queries := sqlc.NewForType(sqlDB, sqlDB.BackendType) - - store := NewStore(sqlDB, queries, clock) - - return store -} diff --git a/chanevents/test_sqlite.go b/chanevents/test_sqlite.go deleted file mode 100644 index 7cbf7f5..0000000 --- a/chanevents/test_sqlite.go +++ /dev/null @@ -1,30 +0,0 @@ -//go:build !test_db_postgres - -package chanevents - -import ( - "testing" - - "github.com/lightninglabs/faraday/db" - "github.com/lightningnetwork/lnd/clock" - "github.com/lightningnetwork/lnd/sqldb/v2" - "github.com/stretchr/testify/require" -) - -// NewTestDB creates a new test chanevents.Store backed by a sqlite DB. -func NewTestDB(t testing.TB, clock clock.Clock) *Store { - // We'll create a new test database. The call to NewTestSqliteDB will - // automatically create the DB and apply the migrations. - testDB := sqldb.NewTestSqliteDB(t, db.FaradayMigrationSets) - - // Now, we'll create the FaradayDB instance from the test database. The - // FaradayDB is the main database object that holds the connection and - // the generated querier. - faradayDB := createStore(t, testDB.BaseDB, clock) - - t.Cleanup(func() { - require.NoError(t, faradayDB.Close()) - }) - - return faradayDB -} diff --git a/cmd/frcli/chan_events.go b/cmd/frcli/chan_events.go deleted file mode 100644 index 3cf771b..0000000 --- a/cmd/frcli/chan_events.go +++ /dev/null @@ -1,97 +0,0 @@ -package main - -import ( - "context" - "fmt" - - "github.com/lightninglabs/faraday/frdrpc" - "github.com/urfave/cli" -) - -var chanEventsCommand = cli.Command{ - Name: "chanevents", - Category: "reporting", - Usage: "Get a report of channel events.", - Description: ` - Get a report for a channel which provides a detailed account of its - lifecycle events. The server caps each response; if has_more is true, - fetch the next page by re-running with --last_id set to the previous - response's last_id. Stop when has_more is false. --start_time and - --end_time are independent filters and do not need to advance between - paginated calls.`, - ArgsUsage: "funding_txid [output_index]", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "funding_txid", - Usage: "the txid of the channel's funding transaction", - }, - cli.IntFlag{ - Name: "output_index", - Usage: "the output index for the funding output of " + - "the funding transaction", - }, - cli.Int64Flag{ - Name: "start_time", - Usage: "start time of the query range as a unix timestamp", - }, - cli.Int64Flag{ - Name: "end_time", - Usage: "end time of the query range as a unix " + - "timestamp; zero defaults to the server's " + - "current time", - }, - cli.UintFlag{ - Name: "max_events", - Usage: "maximum number of events to return; zero " + - "uses the server default (capped server-side)", - }, - cli.Int64Flag{ - Name: "last_id", - Usage: "pagination cursor; pass the previous " + - "response's last_id to continue, or zero " + - "for the first page", - }, - }, - Action: queryChanEvents, -} - -func queryChanEvents(ctx *cli.Context) error { - client, cleanup := getClient(ctx) - defer cleanup() - - // Show command help if the channel point was not provided. - if ctx.NArg() == 0 && ctx.String("funding_txid") == "" { - return cli.ShowCommandHelp(ctx, "chanevents") - } - - outpoint, err := parseChannelPoint(ctx) - if err != nil { - return err - } - - startTime := ctx.Int64("start_time") - endTime := ctx.Int64("end_time") - if startTime < 0 || endTime < 0 { - return fmt.Errorf("start_time and end_time must be >= 0") - } - if endTime != 0 && startTime > endTime { - return fmt.Errorf("start_time must be <= end_time") - } - - req := &frdrpc.ChannelEventsRequest{ - ChanPoint: outpoint.String(), - StartTime: startTime, - EndTime: endTime, - MaxEvents: uint32(ctx.Uint("max_events")), - LastId: ctx.Int64("last_id"), - } - - rpcCtx := context.Background() - report, err := client.GetChannelEvents(rpcCtx, req) - if err != nil { - return err - } - - printRespJSON(report) - return nil -} diff --git a/cmd/frcli/fiat_estimate.go b/cmd/frcli/fiat_estimate.go index 79cf4d7..ad16142 100644 --- a/cmd/frcli/fiat_estimate.go +++ b/cmd/frcli/fiat_estimate.go @@ -15,11 +15,11 @@ import ( var fiatBackendFlag = cli.StringFlag{ Name: "fiat_backend", Usage: fmt.Sprintf("fiat backend to be used. Options include: '%v' "+ - "(default), '%v', `%v`, `%v` or `%v`, which allows custom "+ - "price data to be used. The `%v` option requires the "+ + "(default), '%v', `%v` or `%v`, which allows custom price "+ + "data to be used. The `%v` option requires the "+ "`prices_csv_path` and `custom_price_currency` options to be "+ "set", fiat.CoinDeskPriceBackend, fiat.CoinCapPriceBackend, - fiat.CoinGeckoPriceBackend, fiat.BitfinexPriceBackend, + fiat.CoinGeckoPriceBackend, fiat.CustomPriceBackend, fiat.CustomPriceBackend), } diff --git a/cmd/frcli/forwarding_ability.go b/cmd/frcli/forwarding_ability.go deleted file mode 100644 index f956708..0000000 --- a/cmd/frcli/forwarding_ability.go +++ /dev/null @@ -1,122 +0,0 @@ -package main - -import ( - "context" - "sort" - - "github.com/lightninglabs/faraday/frdrpc" - "github.com/urfave/cli" -) - -var forwardingAbilityCommand = cli.Command{ - Name: "forwardingability", - Category: "insights", - Usage: "Get forwarding ability analysis of peer pairs.", - Flags: []cli.Flag{ - cli.Uint64Flag{ - Name: "start_time", - Usage: "start time of the query range as a unix " + - "timestamp", - }, - cli.Uint64Flag{ - Name: "end_time", - Usage: "end time of the query range as a unix " + - "timestamp; zero defaults to the server's " + - "current time", - }, - cli.Uint64Flag{ - Name: "liquidity_floor_sat", - Usage: "the minimum directional liquidity in " + - "satoshis for a pair to count as " + - "economically forwardable; zero uses the " + - "server default", - }, - cli.Float64Flag{ - Name: "uptime_threshold", - Usage: "the uptime fraction in [0,1] at or above " + - "which a non-forwarding pair is reported as " + - "up but idle; zero uses the server default", - }, - }, - Action: queryForwardingAbility, -} - -type pairView struct { - PeerIn string `json:"peer_in"` - PeerOut string `json:"peer_out"` - EffectiveUptimeS int64 `json:"effective_uptime_s"` - ForwardedSat int64 `json:"forwarded_sat"` - UptimeFraction float64 `json:"uptime_fraction"` - Velocity float64 `json:"velocity"` -} - -func queryForwardingAbility(ctx *cli.Context) error { - client, cleanup := getClient(ctx) - defer cleanup() - - req := &frdrpc.ForwardingAbilityRequest{ - StartTime: ctx.Uint64("start_time"), - EndTime: ctx.Uint64("end_time"), - LiquidityFloorSat: ctx.Uint64("liquidity_floor_sat"), - UptimeThreshold: ctx.Float64("uptime_threshold"), - } - - rpcCtx := context.Background() - resp, err := client.ForwardingAbility(rpcCtx, req) - if err != nil { - return err - } - - abilities, err := frdrpc.DecodeForwardingAbility(resp) - if err != nil { - return err - } - - // The metrics are raw, so derive uptime fraction and velocity here from - // the window the server reported. - windowSeconds := resp.EndTime - resp.StartTime - - var views []pairView - for inPeer, outMap := range abilities { - for outPeer, ability := range outMap { - var uptimeFraction, velocity float64 - if windowSeconds > 0 { - uptimeFraction = float64( - ability.EffectiveUptimeS, - ) / float64(windowSeconds) - } - - if ability.EffectiveUptimeS > 0 { - velocity = float64(ability.ForwardedSat) / - float64(ability.EffectiveUptimeS) - } - - views = append( - views, pairView{ - PeerIn: inPeer, - PeerOut: outPeer, - EffectiveUptimeS: ability.EffectiveUptimeS, - ForwardedSat: ability.ForwardedSat, - UptimeFraction: uptimeFraction, - Velocity: velocity, - }, - ) - } - } - - // Stable sort by PeerIn, then PeerOut. - sort.SliceStable( - views, - func(i, j int) bool { - if views[i].PeerIn != views[j].PeerIn { - return views[i].PeerIn < views[j].PeerIn - } - - return views[i].PeerOut < views[j].PeerOut - }, - ) - - printJSON(views) - - return nil -} diff --git a/cmd/frcli/main.go b/cmd/frcli/main.go index 264d7e4..7cbff99 100644 --- a/cmd/frcli/main.go +++ b/cmd/frcli/main.go @@ -57,8 +57,6 @@ func main() { fiatEstimateCommand, onChainReportCommand, closeReportCommand, - chanEventsCommand, - forwardingAbilityCommand, } if err := app.Run(os.Args); err != nil { diff --git a/cmd/frcli/utils.go b/cmd/frcli/utils.go index 1ff7ca7..b603970 100644 --- a/cmd/frcli/utils.go +++ b/cmd/frcli/utils.go @@ -22,13 +22,13 @@ import ( "github.com/lightninglabs/faraday/frdrpc" "github.com/lightninglabs/faraday/utils" "github.com/lightninglabs/lndclient" + "github.com/lightninglabs/protobuf-hex-display/jsonpb" + "github.com/lightninglabs/protobuf-hex-display/proto" "github.com/lightningnetwork/lnd/lncfg" - "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/macaroons" "github.com/urfave/cli" "google.golang.org/grpc" "google.golang.org/grpc/credentials" - "google.golang.org/protobuf/proto" "gopkg.in/macaroon.v2" ) @@ -50,13 +50,19 @@ func fatal(err error) { // printRespJSON prints a proto message as json. func printRespJSON(resp proto.Message) { - jsonBytes, err := lnrpc.ProtoJSONMarshalOpts.Marshal(resp) + jsonMarshaler := &jsonpb.Marshaler{ + OrigName: true, + EmitDefaults: true, + Indent: " ", + } + + jsonStr, err := jsonMarshaler.MarshalToString(resp) if err != nil { fmt.Println("unable to decode response: ", err) return } - fmt.Println(string(jsonBytes)) + fmt.Println(jsonStr) } func printJSON(resp interface{}) { @@ -159,23 +165,12 @@ func extractPathArgs(ctx *cli.Context) (string, string, error) { if faradayDir != faraday.FaradayDirBase || networkStr != faraday.DefaultNetwork { - // Only overwrite the tls cert path if the user has not - // explicitly defined it. - if !ctx.GlobalIsSet(tlsCertFlag.Name) { - tlsCertPath = filepath.Join( - faradayDir, networkStr, - faraday.DefaultTLSCertFilename, - ) - } - - // Only overwrite the macaroon path if the user has not - // explicitly defined it. - if !ctx.GlobalIsSet(macaroonPathFlag.Name) { - macPath = filepath.Join( - faradayDir, networkStr, - faraday.DefaultMacaroonFilename, - ) - } + tlsCertPath = filepath.Join( + faradayDir, networkStr, faraday.DefaultTLSCertFilename, + ) + macPath = filepath.Join( + faradayDir, networkStr, faraday.DefaultMacaroonFilename, + ) } return tlsCertPath, macPath, nil @@ -288,11 +283,6 @@ func parseChannelPoint(ctx *cli.Context) (*wire.OutPoint, error) { return channelPoint, nil } -// fiatBackendBitfinex is the rpc enum value for BITFINEX. -// TODO: Replace with frdrpc.FiatBackend_BITFINEX once the frdrpc module is -// tagged and the dependency is bumped. -const fiatBackendBitfinex = frdrpc.FiatBackend(5) - // parseFiatBackend parses the user chosen fiat backend into a FiatBackend type. func parseFiatBackend(fiatBackend string) (frdrpc.FiatBackend, error) { switch fiatBackend { @@ -311,9 +301,6 @@ func parseFiatBackend(fiatBackend string) (frdrpc.FiatBackend, error) { case fiat.CoinGeckoPriceBackend.String(): return frdrpc.FiatBackend_COINGECKO, nil - case fiat.BitfinexPriceBackend.String(): - return fiatBackendBitfinex, nil - default: return frdrpc.FiatBackend_UNKNOWN_FIATBACKEND, fmt.Errorf( "unknown fiat backend", diff --git a/cmd/frcli/utils_test.go b/cmd/frcli/utils_test.go index 4c117b9..6bf3309 100644 --- a/cmd/frcli/utils_test.go +++ b/cmd/frcli/utils_test.go @@ -3,9 +3,7 @@ package main import ( "testing" - "github.com/lightninglabs/faraday/fiat" "github.com/lightninglabs/faraday/frdrpc" - "github.com/stretchr/testify/require" ) // TestFilterPrices checks that the filterPrices function correctly filters @@ -120,64 +118,3 @@ func TestFilterPrices(t *testing.T) { }) } } - -// TestParseFiatBackend checks that known backend strings map to expected -// rpc enum values. -func TestParseFiatBackend(t *testing.T) { - t.Parallel() - - tests := []struct { - name string - backendStr string - expected frdrpc.FiatBackend - expectErr bool - }{ - { - name: "empty uses unknown", - backendStr: "", - expected: frdrpc.FiatBackend_UNKNOWN_FIATBACKEND, - }, - { - name: "coincap", - backendStr: fiat.CoinCapPriceBackend.String(), - expected: frdrpc.FiatBackend_COINCAP, - }, - { - name: "coindesk", - backendStr: fiat.CoinDeskPriceBackend.String(), - expected: frdrpc.FiatBackend_COINDESK, - }, - { - name: "custom", - backendStr: fiat.CustomPriceBackend.String(), - expected: frdrpc.FiatBackend_CUSTOM, - }, - { - name: "coingecko", - backendStr: fiat.CoinGeckoPriceBackend.String(), - expected: frdrpc.FiatBackend_COINGECKO, - }, - { - name: "bitfinex", - backendStr: fiat.BitfinexPriceBackend.String(), - expected: fiatBackendBitfinex, - }, - { - name: "unknown backend", - backendStr: "not-a-backend", - expectErr: true, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - backend, err := parseFiatBackend(test.backendStr) - if test.expectErr { - require.Error(t, err) - } else { - require.NoError(t, err) - require.Equal(t, test.expected, backend) - } - }) - } -} diff --git a/config.go b/config.go index c8002c4..475af83 100644 --- a/config.go +++ b/config.go @@ -4,7 +4,6 @@ import ( "crypto/tls" "crypto/x509" "fmt" - "math" "os" "path" "path/filepath" @@ -12,16 +11,10 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/lightninglabs/faraday/chain" - "github.com/lightninglabs/faraday/chanevents" - "github.com/lightninglabs/faraday/db" - "github.com/lightninglabs/faraday/db/sqlc" "github.com/lightninglabs/lndclient" - "github.com/lightningnetwork/lnd/build" "github.com/lightningnetwork/lnd/cert" - "github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/lncfg" "github.com/lightningnetwork/lnd/lnrpc" - "github.com/lightningnetwork/lnd/sqldb/v2" "google.golang.org/grpc/credentials" ) @@ -37,32 +30,10 @@ const ( // we can serve basic functionality by default. defaultChainConn = false - // defaultTLSCertDuration is the default validity of a self-signed + // DefaultAutogenValidity is the default validity of a self-signed // certificate. The value corresponds to 14 months // (14 months * 30 days * 24 hours). - defaultTLSCertDuration = 14 * 30 * 24 * time.Hour - - // DatabaseBackendSqlite is the name of the SQLite database backend. - DatabaseBackendSqlite = "sqlite" - - // DatabaseBackendPostgres is the name of the Postgres database backend. - DatabaseBackendPostgres = "postgres" - - // defaultSqliteDatabaseFileName is the default name of the SQLite - // database file. - defaultSqliteDatabaseFileName = "faraday.db" - - // defaultChanEventsMaxEvents is the default maximum number of channel - // events to retain. At roughly 140 bytes per event this acts as a hard - // ceiling of approximately 1 GB. A value of 0 disables the size-based - // limit. - defaultChanEventsMaxEvents = 7000000 - - // defaultChanEventsRetention is the default retention window for channel - // events. Age-based pruning is disabled by default (0): out of the box - // only the max-events size ceiling bounds the table, and operators opt - // into a retention window explicitly. - defaultChanEventsRetention = 0 + DefaultAutogenValidity = 14 * 30 * 24 * time.Hour ) var ( @@ -135,9 +106,6 @@ type LndConfig struct { // TLSCertPath is the path to the tls cert that faraday should use. TLSCertPath string `long:"tlscertpath" description:"Path to TLS cert"` - - // RequestTimeout is the maximum time to wait for a response from lnd. - RequestTimeout time.Duration `long:"requesttimeout" description:"The maximum time to wait for a response from lnd, if not set the default of 30 seconds will be used."` } type Config struct { //nolint:maligned @@ -156,19 +124,18 @@ type Config struct { //nolint:maligned MinimumMonitored time.Duration `long:"min_monitored" description:"The minimum amount of time that a channel must be monitored for before recommending termination. Valid time units are {s, m, h}."` // Network is a string containing the network we're running on. - Network string `long:"network" description:"The network to run on." choice:"regtest" choice:"testnet" choice:"mainnet" choice:"simnet" choice:"signet" ` + Network string `long:"network" description:"The network to run on." choice:"regtest" choice:"testnet" choice:"mainnet" choice:"simnet"` // DebugLevel is a string defining the log level for the service either // for all subsystems the same or individual level by subsystem. DebugLevel string `long:"debuglevel" description:"Debug level for faraday and its subsystems."` - TLSCertPath string `long:"tlscertpath" description:"Path to write the TLS certificate for faraday's RPC and REST services."` - TLSKeyPath string `long:"tlskeypath" description:"Path to write the TLS private key for faraday's RPC and REST services."` - TLSExtraIPs []string `long:"tlsextraip" description:"Adds an extra IP to the generated certificate."` - TLSExtraDomains []string `long:"tlsextradomain" description:"Adds an extra domain to the generated certificate."` - TLSAutoRefresh bool `long:"tlsautorefresh" description:"Re-generate TLS certificate and key if the IPs or domains are changed."` - TLSDisableAutofill bool `long:"tlsdisableautofill" description:"Do not include the interface IPs or the system hostname in TLS certificate, use first --tlsextradomain as Common Name instead, if set."` - TLSCertDuration time.Duration `long:"tlscertduration" description:"The duration for which the auto-generated TLS certificate will be valid for."` + TLSCertPath string `long:"tlscertpath" description:"Path to write the TLS certificate for faraday's RPC and REST services."` + TLSKeyPath string `long:"tlskeypath" description:"Path to write the TLS private key for faraday's RPC and REST services."` + TLSExtraIPs []string `long:"tlsextraip" description:"Adds an extra IP to the generated certificate."` + TLSExtraDomains []string `long:"tlsextradomain" description:"Adds an extra domain to the generated certificate."` + TLSAutoRefresh bool `long:"tlsautorefresh" description:"Re-generate TLS certificate and key if the IPs or domains are changed."` + TLSDisableAutofill bool `long:"tlsdisableautofill" description:"Do not include the interface IPs or the system hostname in TLS certificate, use first --tlsextradomain as Common Name instead, if set."` MacaroonPath string `long:"macaroonpath" description:"Path to write the macaroon for faraday's RPC and REST services if it doesn't exist."` @@ -183,24 +150,6 @@ type Config struct { //nolint:maligned // Bitcoin is the configuration required to connect to a bitcoin node. Bitcoin *chain.BitcoinConfig `group:"bitcoin" namespace:"bitcoin"` - - // Logging controls various aspects of pool logging. - Logging *build.LogConfig `group:"logging" namespace:"logging"` - - // DatabaseBackend is the database backend we will use for storing all - // liveness data. - DatabaseBackend string `long:"databasebackend" description:"The database backend to use for storing all liveness data." choice:"sqlite" choice:"postgres"` - - // Sqlite holds the configuration options for a SQLite database - // backend. - Sqlite *db.SqliteConfig `group:"sqlite" namespace:"sqlite"` - - // Postgres holds the configuration options for a Postgres database - Postgres *sqldb.PostgresConfig `group:"postgres" namespace:"postgres"` - - // ChanEvents holds the configuration options for channel event safety - // pruning. - ChanEvents *chanevents.Config `group:"chanevents" namespace:"chanevents"` } // DefaultConfig returns all default values for the Config struct. @@ -216,20 +165,10 @@ func DefaultConfig() Config { DebugLevel: defaultDebugLevel, TLSCertPath: DefaultTLSCertPath, TLSKeyPath: DefaultTLSKeyPath, - TLSCertDuration: defaultTLSCertDuration, MacaroonPath: DefaultMacaroonPath, RPCListen: defaultRPCListen, ChainConn: defaultChainConn, Bitcoin: chain.DefaultConfig, - Logging: build.DefaultLogConfig(), - DatabaseBackend: DatabaseBackendSqlite, - Sqlite: &db.SqliteConfig{ - DatabaseFileName: defaultSqliteDatabaseFileName, - }, - ChanEvents: &chanevents.Config{ - MaxEvents: defaultChanEventsMaxEvents, - Retention: defaultChanEventsRetention, - }, } } @@ -248,10 +187,6 @@ func ValidateConfig(config *Config) error { config.TLSKeyPath = lncfg.CleanAndExpandPath(config.TLSKeyPath) config.MacaroonPath = lncfg.CleanAndExpandPath(config.MacaroonPath) - // Before adding the network namespace below, check if the user has - // overwritten the default faraday directory. - faradayDirSet := config.FaradayDir != FaradayDirBase - // Append the network type to faraday directory so they are "namespaced" // per network. config.FaradayDir = filepath.Join(config.FaradayDir, config.Network) @@ -265,6 +200,7 @@ func ValidateConfig(config *Config) error { // values, make sure that they are not set when faraday dir is set. We // fail hard here rather than overwriting and potentially confusing the // user. + faradayDirSet := config.FaradayDir != FaradayDirBase if faradayDirSet { tlsCertPathSet := config.TLSCertPath != DefaultTLSCertPath tlsKeyPathSet := config.TLSKeyPath != DefaultTLSKeyPath @@ -364,25 +300,6 @@ func ValidateConfig(config *Config) error { config.Lnd.TLSCertPath, ) - if config.ChanEvents != nil { - // The channel event size limit becomes an int32 SQL OFFSET - // during pruning, so reject values that would overflow it and - // silently corrupt the prune bound. - if config.ChanEvents.MaxEvents > math.MaxInt32 { - return fmt.Errorf("chanevents.max-events must not "+ - "exceed %d", math.MaxInt32) - } - - // A negative retention is silently ignored by the prune checks, - // which only treat a strictly positive duration as enabling - // age-based pruning. Reject it so a misconfigured window fails - // loudly instead of disabling pruning unexpectedly. - if config.ChanEvents.Retention < 0 { - return fmt.Errorf("chanevents.retention must not be " + - "negative") - } - } - return nil } @@ -446,7 +363,7 @@ func loadCertWithCreate(cfg *Config) (tls.Certificate, *x509.Certificate, certBytes, keyBytes, err := cert.GenCertPair( defaultSelfSignedOrganization, cfg.TLSExtraIPs, cfg.TLSExtraDomains, cfg.TLSDisableAutofill, - cfg.TLSCertDuration, + DefaultAutogenValidity, ) if err != nil { return tls.Certificate{}, nil, err @@ -466,99 +383,3 @@ func loadCertWithCreate(cfg *Config) (tls.Certificate, *x509.Certificate, return cert.LoadCert(cfg.TLSCertPath, cfg.TLSKeyPath) } - -// stores holds a collection of the DB stores that are used by faraday. -type stores struct { - // ChanEventsStore is used to watch for channel events. - ChanEventsStore *chanevents.Store - - // closeFns holds various callbacks that can be used to close any open - // stores in the stores struct. - closeFns map[string]func() error -} - -// NewStores creates a new stores instance based on the chosen database backend. -func NewStores(cfg Config, clock clock.Clock) (*stores, error) { - var ( - stores = &stores{ - closeFns: make(map[string]func() error), - } - ) - - switch cfg.DatabaseBackend { - case DatabaseBackendSqlite: - dbPath := filepath.Join( - cfg.FaradayDir, cfg.Sqlite.DatabaseFileName, - ) - - sqlStore, err := sqldb.NewSqliteStore(&sqldb.SqliteConfig{ - SkipMigrations: cfg.Sqlite.SkipMigrations, - SkipMigrationDbBackup: cfg.Sqlite.SkipMigrationDbBackup, - }, dbPath) - if err != nil { - return stores, err - } - - if !cfg.Sqlite.SkipMigrations { - err = sqldb.ApplyAllMigrations( - sqlStore, db.FaradayMigrationSets, - ) - if err != nil { - return stores, fmt.Errorf("error applying "+ - "migrations to SQLite store: %w", err, - ) - } - } - - queries := sqlc.NewForType(sqlStore, sqlStore.BackendType) - - stores.ChanEventsStore = chanevents.NewStore( - sqlStore.BaseDB, queries, clock, - ) - - stores.closeFns["sqlite"] = sqlStore.Close - - case DatabaseBackendPostgres: - sqlStore, err := sqldb.NewPostgresStore(cfg.Postgres) - if err != nil { - return stores, err - } - - if !cfg.Postgres.SkipMigrations { - err = sqldb.ApplyAllMigrations( - sqlStore, db.FaradayMigrationSets, - ) - if err != nil { - return stores, fmt.Errorf("error applying "+ - "migrations to Postgres store: %w", err, - ) - } - } - - queries := sqlc.NewForType(sqlStore, sqlStore.BackendType) - - stores.ChanEventsStore = chanevents.NewStore( - sqlStore.BaseDB, queries, clock, - ) - - stores.closeFns["postgres"] = sqlStore.Close - - default: - return nil, fmt.Errorf("unsupported database backend: "+ - "%s", cfg.DatabaseBackend) - } - - return stores, nil -} - -// Close closes all the stores. -func (s *stores) Close() error { - for name, closeFn := range s.closeFns { - err := closeFn() - if err != nil { - return fmt.Errorf("error closing %s store: %v", name, err) - } - } - - return nil -} diff --git a/dataset/log.go b/dataset/log.go index 22dffcc..69dac8f 100644 --- a/dataset/log.go +++ b/dataset/log.go @@ -1,7 +1,7 @@ package dataset import ( - "github.com/btcsuite/btclog/v2" + "github.com/btcsuite/btclog" "github.com/lightningnetwork/lnd/build" ) diff --git a/db/interfaces.go b/db/interfaces.go deleted file mode 100644 index d8fd37a..0000000 --- a/db/interfaces.go +++ /dev/null @@ -1,22 +0,0 @@ -package db - -// QueriesTxOptions defines the set of db txn options the SQLQueries -// understands. -type QueriesTxOptions struct { - // readOnly governs if a read only transaction is needed or not. - readOnly bool -} - -// ReadOnly returns true if the transaction should be read only. -// -// NOTE: This implements the TxOptions. -func (a *QueriesTxOptions) ReadOnly() bool { - return a.readOnly -} - -// NewQueryReadTx creates a new read transaction option set. -func NewQueryReadTx() QueriesTxOptions { - return QueriesTxOptions{ - readOnly: true, - } -} diff --git a/db/migrations.go b/db/migrations.go deleted file mode 100644 index 6520dd3..0000000 --- a/db/migrations.go +++ /dev/null @@ -1,10 +0,0 @@ -package db - -const ( - // LatestMigrationVersion is the latest migration version of the - // database. This is used to implement downgrade protection for the - // daemon. - // - // NOTE: This MUST be updated when a new migration is added. - LatestMigrationVersion = 2 -) diff --git a/db/migrations_test.go b/db/migrations_test.go deleted file mode 100644 index d87826e..0000000 --- a/db/migrations_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package db - -import ( - "strconv" - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -// TestLatestMigrationVersion ensures that LatestMigrationVersion stays in sync -// with the highest-numbered .up.sql file in the migrations directory. Each -// migration — whether pure SQL or programmatic (with a dummy SQL file) — gets -// its own numbered file pair, so the max file number must equal the constant. -func TestLatestMigrationVersion(t *testing.T) { - entries, err := sqlSchemas.ReadDir("sqlc/migrations") - require.NoError(t, err) - - var maxVersion uint - for _, entry := range entries { - if !strings.HasSuffix(entry.Name(), ".up.sql") { - continue - } - - parts := strings.SplitN(entry.Name(), "_", 2) - require.NotEmpty(t, parts) - - v, err := strconv.ParseUint(parts[0], 10, 64) - require.NoError(t, err) - - if uint(v) > maxVersion { - maxVersion = uint(v) - } - } - - require.EqualValues( - t, maxVersion, LatestMigrationVersion, - "LatestMigrationVersion is out of date, update "+ - "db/migrations.go", - ) -} diff --git a/db/postgres.go b/db/postgres.go deleted file mode 100644 index 8cc42b0..0000000 --- a/db/postgres.go +++ /dev/null @@ -1,25 +0,0 @@ -package db - -import ( - "testing" - - _ "github.com/golang-migrate/migrate/v4/source/file" - "github.com/lightningnetwork/lnd/sqldb/v2" -) - -// NewTestPostgresDB is a helper function that creates a Postgres database for -// testing. -func NewTestPostgresDB(t testing.TB) *sqldb.PostgresStore { - t.Helper() - - t.Logf("Creating new Postgres DB for testing") - - sqlFixture := sqldb.NewTestPgFixture( - t, sqldb.DefaultPostgresFixtureLifetime, - ) - t.Cleanup(func() { - sqlFixture.TearDown(t) - }) - - return sqldb.NewTestPostgresDB(t, sqlFixture, FaradayMigrationSets) -} diff --git a/db/schemas.go b/db/schemas.go deleted file mode 100644 index 1a7a209..0000000 --- a/db/schemas.go +++ /dev/null @@ -1,9 +0,0 @@ -package db - -import ( - "embed" - _ "embed" -) - -//go:embed sqlc/migrations/*.*.sql -var sqlSchemas embed.FS diff --git a/db/sql_migrations.go b/db/sql_migrations.go deleted file mode 100644 index 52a7e7c..0000000 --- a/db/sql_migrations.go +++ /dev/null @@ -1,30 +0,0 @@ -package db - -import ( - "github.com/golang-migrate/migrate/v4" - "github.com/golang-migrate/migrate/v4/database/pgx/v5" - "github.com/lightningnetwork/lnd/sqldb/v2" -) - -var ( - FaradayMigrationSet = sqldb.MigrationSet{ - TrackingTableName: pgx.DefaultMigrationsTable, - SQLFileDirectory: "sqlc/migrations", - SQLFiles: sqlSchemas, - - // LatestMigrationVersion is the latest migration version of the - // database. This is used to implement downgrade protection for - // the daemon. - // - // NOTE: This MUST be updated when a new migration is added. - LatestMigrationVersion: LatestMigrationVersion, - - MakeProgrammaticMigrations: func( - db *sqldb.BaseDB, - ) (map[uint]migrate.ProgrammaticMigrEntry, error) { - - return make(map[uint]migrate.ProgrammaticMigrEntry), nil - }, - } - FaradayMigrationSets = []sqldb.MigrationSet{FaradayMigrationSet} -) diff --git a/db/sqlc/chanevents.sql.go b/db/sqlc/chanevents.sql.go deleted file mode 100644 index 77a05c7..0000000 --- a/db/sqlc/chanevents.sql.go +++ /dev/null @@ -1,267 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. -// versions: -// sqlc v1.25.0 -// source: chanevents.sql - -package sqlc - -import ( - "context" - "database/sql" - "time" -) - -const getChannelByChanPoint = `-- name: GetChannelByChanPoint :one -SELECT id, channel_point, short_channel_id, peer_id FROM channels WHERE channel_point = $1 -` - -func (q *Queries) GetChannelByChanPoint(ctx context.Context, channelPoint string) (Channel, error) { - row := q.db.QueryRowContext(ctx, getChannelByChanPoint, channelPoint) - var i Channel - err := row.Scan( - &i.ID, - &i.ChannelPoint, - &i.ShortChannelID, - &i.PeerID, - ) - return i, err -} - -const getChannelByShortChanID = `-- name: GetChannelByShortChanID :one -SELECT id, channel_point, short_channel_id, peer_id FROM channels WHERE short_channel_id = $1 -` - -func (q *Queries) GetChannelByShortChanID(ctx context.Context, shortChannelID int64) (Channel, error) { - row := q.db.QueryRowContext(ctx, getChannelByShortChanID, shortChannelID) - var i Channel - err := row.Scan( - &i.ID, - &i.ChannelPoint, - &i.ShortChannelID, - &i.PeerID, - ) - return i, err -} - -const getChannelEvents = `-- name: GetChannelEvents :many -SELECT id, channel_id, event_type, timestamp, local_balance_sat, remote_balance_sat, is_sync FROM channel_events -WHERE channel_id = $1 - AND id > $2 - AND timestamp >= $3 - AND timestamp < $4 -ORDER BY id ASC -LIMIT $5 -` - -type GetChannelEventsParams struct { - ChannelID int64 - ID int64 - Timestamp time.Time - Timestamp_2 time.Time - Limit int32 -} - -func (q *Queries) GetChannelEvents(ctx context.Context, arg GetChannelEventsParams) ([]ChannelEvent, error) { - rows, err := q.db.QueryContext(ctx, getChannelEvents, - arg.ChannelID, - arg.ID, - arg.Timestamp, - arg.Timestamp_2, - arg.Limit, - ) - if err != nil { - return nil, err - } - defer rows.Close() - var items []ChannelEvent - for rows.Next() { - var i ChannelEvent - if err := rows.Scan( - &i.ID, - &i.ChannelID, - &i.EventType, - &i.Timestamp, - &i.LocalBalanceSat, - &i.RemoteBalanceSat, - &i.IsSync, - ); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Close(); err != nil { - return nil, err - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const getChannels = `-- name: GetChannels :many -SELECT c.id, c.short_channel_id, p.pubkey -FROM channels c -JOIN peers p ON c.peer_id = p.id -` - -type GetChannelsRow struct { - ID int64 - ShortChannelID int64 - Pubkey string -} - -func (q *Queries) GetChannels(ctx context.Context) ([]GetChannelsRow, error) { - rows, err := q.db.QueryContext(ctx, getChannels) - if err != nil { - return nil, err - } - defer rows.Close() - var items []GetChannelsRow - for rows.Next() { - var i GetChannelsRow - if err := rows.Scan(&i.ID, &i.ShortChannelID, &i.Pubkey); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Close(); err != nil { - return nil, err - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const getLatestChannelEventBefore = `-- name: GetLatestChannelEventBefore :one -SELECT id, channel_id, event_type, timestamp, local_balance_sat, remote_balance_sat, is_sync FROM channel_events -WHERE channel_id = $1 AND event_type = $2 AND timestamp < $3 -ORDER BY timestamp DESC, id DESC -LIMIT 1 -` - -type GetLatestChannelEventBeforeParams struct { - ChannelID int64 - EventType int16 - Timestamp time.Time -} - -func (q *Queries) GetLatestChannelEventBefore(ctx context.Context, arg GetLatestChannelEventBeforeParams) (ChannelEvent, error) { - row := q.db.QueryRowContext(ctx, getLatestChannelEventBefore, arg.ChannelID, arg.EventType, arg.Timestamp) - var i ChannelEvent - err := row.Scan( - &i.ID, - &i.ChannelID, - &i.EventType, - &i.Timestamp, - &i.LocalBalanceSat, - &i.RemoteBalanceSat, - &i.IsSync, - ) - return i, err -} - -const getPeerByPubKey = `-- name: GetPeerByPubKey :one -SELECT id, pubkey FROM peers WHERE pubkey = $1 -` - -func (q *Queries) GetPeerByPubKey(ctx context.Context, pubkey string) (Peer, error) { - row := q.db.QueryRowContext(ctx, getPeerByPubKey, pubkey) - var i Peer - err := row.Scan(&i.ID, &i.Pubkey) - return i, err -} - -const insertChannel = `-- name: InsertChannel :one -INSERT INTO channels (channel_point, short_channel_id, peer_id) VALUES ($1, $2, $3) RETURNING id -` - -type InsertChannelParams struct { - ChannelPoint string - ShortChannelID int64 - PeerID int64 -} - -func (q *Queries) InsertChannel(ctx context.Context, arg InsertChannelParams) (int64, error) { - row := q.db.QueryRowContext(ctx, insertChannel, arg.ChannelPoint, arg.ShortChannelID, arg.PeerID) - var id int64 - err := row.Scan(&id) - return id, err -} - -const insertChannelEvent = `-- name: InsertChannelEvent :exec -INSERT INTO channel_events ( - channel_id, event_type, timestamp, local_balance_sat, remote_balance_sat, - is_sync -) VALUES ($1, $2, $3, $4, $5, $6) -` - -type InsertChannelEventParams struct { - ChannelID int64 - EventType int16 - Timestamp time.Time - LocalBalanceSat sql.NullInt64 - RemoteBalanceSat sql.NullInt64 - IsSync bool -} - -func (q *Queries) InsertChannelEvent(ctx context.Context, arg InsertChannelEventParams) error { - _, err := q.db.ExecContext(ctx, insertChannelEvent, - arg.ChannelID, - arg.EventType, - arg.Timestamp, - arg.LocalBalanceSat, - arg.RemoteBalanceSat, - arg.IsSync, - ) - return err -} - -const insertPeer = `-- name: InsertPeer :one -INSERT INTO peers (pubkey) VALUES ($1) RETURNING id -` - -func (q *Queries) InsertPeer(ctx context.Context, pubkey string) (int64, error) { - row := q.db.QueryRowContext(ctx, insertPeer, pubkey) - var id int64 - err := row.Scan(&id) - return id, err -} - -const pruneChannelEventsByAge = `-- name: PruneChannelEventsByAge :execrows -DELETE FROM channel_events -WHERE channel_events.timestamp < $1 -` - -// PruneChannelEventsByAge enforces the retention window on the channel_events -// table, returning the number of rows deleted. It deletes any row whose -// timestamp predates the given cutoff. -func (q *Queries) PruneChannelEventsByAge(ctx context.Context, timestamp time.Time) (int64, error) { - result, err := q.db.ExecContext(ctx, pruneChannelEventsByAge, timestamp) - if err != nil { - return 0, err - } - return result.RowsAffected() -} - -const pruneChannelEventsBySize = `-- name: PruneChannelEventsBySize :execrows -DELETE FROM channel_events -WHERE channel_events.id < COALESCE(( - SELECT id FROM channel_events - ORDER BY id DESC - LIMIT 1 OFFSET $1 -), 0) -` - -// PruneChannelEventsBySize enforces the size ceiling on the channel_events -// table, returning the number of rows deleted. It keeps the newest rows by -// deleting everything with a smaller (earlier-inserted) id than the id found at -// the given offset from the newest row, so an offset of (max-events - 1) keeps -// exactly max-events rows. -func (q *Queries) PruneChannelEventsBySize(ctx context.Context, offset int32) (int64, error) { - result, err := q.db.ExecContext(ctx, pruneChannelEventsBySize, offset) - if err != nil { - return 0, err - } - return result.RowsAffected() -} diff --git a/db/sqlc/db.go b/db/sqlc/db.go deleted file mode 100644 index 8ed64d1..0000000 --- a/db/sqlc/db.go +++ /dev/null @@ -1,31 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. -// versions: -// sqlc v1.25.0 - -package sqlc - -import ( - "context" - "database/sql" -) - -type DBTX interface { - ExecContext(context.Context, string, ...interface{}) (sql.Result, error) - PrepareContext(context.Context, string) (*sql.Stmt, error) - QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) - QueryRowContext(context.Context, string, ...interface{}) *sql.Row -} - -func New(db DBTX) *Queries { - return &Queries{db: db} -} - -type Queries struct { - db DBTX -} - -func (q *Queries) WithTx(tx *sql.Tx) *Queries { - return &Queries{ - db: tx, - } -} diff --git a/db/sqlc/db_custom.go b/db/sqlc/db_custom.go deleted file mode 100644 index 00b8afb..0000000 --- a/db/sqlc/db_custom.go +++ /dev/null @@ -1,34 +0,0 @@ -// Package sqlc provides a set of custom database queries and utilities -// for interacting with the SQL database used in the application. It includes -// generated code from sqlc as well as custom wrappers to handle different -// database backends. -package sqlc - -import ( - "github.com/lightningnetwork/lnd/sqldb/v2" -) - -// wrappedTX is a wrapper around a DBTX that also stores the database backend -// type. -type wrappedTX struct { - DBTX - - backendType sqldb.BackendType -} - -// Backend returns the type of database backend we're using. -func (q *Queries) Backend() sqldb.BackendType { - wtx, ok := q.db.(*wrappedTX) - if !ok { - // Shouldn't happen unless a new database backend type is added - // but not initialized correctly. - return sqldb.BackendTypeUnknown - } - - return wtx.backendType -} - -// NewForType creates a new Queries instance for the given database type. -func NewForType(db DBTX, typ sqldb.BackendType) *Queries { - return &Queries{db: &wrappedTX{db, typ}} -} diff --git a/db/sqlc/migrations/000001_chanevents.down.sql b/db/sqlc/migrations/000001_chanevents.down.sql deleted file mode 100644 index c755663..0000000 --- a/db/sqlc/migrations/000001_chanevents.down.sql +++ /dev/null @@ -1,6 +0,0 @@ -DROP INDEX IF EXISTS channel_events_chan_id_id_idx; -DROP INDEX IF EXISTS channel_events_chan_id_ts_idx; -DROP TABLE IF EXISTS channel_events; -DROP INDEX IF EXISTS channel_peer_idx; -DROP TABLE IF EXISTS channels; -DROP TABLE IF EXISTS peers; diff --git a/db/sqlc/migrations/000001_chanevents.up.sql b/db/sqlc/migrations/000001_chanevents.up.sql deleted file mode 100644 index 9ed6995..0000000 --- a/db/sqlc/migrations/000001_chanevents.up.sql +++ /dev/null @@ -1,53 +0,0 @@ --- The peers table stores all the peers that we have channels with. -CREATE TABLE IF NOT EXISTS peers ( - -- The auto incrementing primary key. - id INTEGER PRIMARY KEY, - -- The public key of the peer. - pubkey TEXT NOT NULL UNIQUE -); - --- The channels table stores all the channels that we have with our peers. -CREATE TABLE IF NOT EXISTS channels ( - -- The auto incrementing primary key. - id INTEGER PRIMARY KEY, - -- The channel point, as a 'txid:output_index' string. - channel_point TEXT NOT NULL UNIQUE, - -- The short channel ID. - short_channel_id BIGINT NOT NULL UNIQUE, - -- The peer that this channel is with. - peer_id BIGINT NOT NULL REFERENCES peers(id) ON DELETE CASCADE -); -CREATE INDEX IF NOT EXISTS channel_peer_idx ON channels (peer_id); - --- The channel_events table stores all the events that are associated with a --- particular channel. -CREATE TABLE IF NOT EXISTS channel_events ( - -- The auto incrementing primary key. - id INTEGER PRIMARY KEY, - -- The channel that this event is associated with. - channel_id BIGINT NOT NULL REFERENCES channels(id) ON DELETE CASCADE, - -- The type of event. - event_type SMALLINT NOT NULL, - -- The time the event occurred. - timestamp TIMESTAMP NOT NULL, - -- The local balance of the channel at the time of the event. - -- This is only populated for balance update events. - local_balance_sat BIGINT CHECK (local_balance_sat >= 0), - -- The remote balance of the channel at the time of the event. - -- This is only populated for balance update events. - remote_balance_sat BIGINT CHECK (remote_balance_sat >= 0), - -- Whether this event was recorded during an initial sync rather than - -- from a live subscription. - is_sync BOOLEAN NOT NULL DEFAULT FALSE -); - --- This composite index supports the chronological access patterns --- (GetChannelEventsIter, GetLatestChannelEventBefore): events for a given --- channel sorted by time, with a per-channel time-range scan. -CREATE INDEX IF NOT EXISTS channel_events_chan_id_ts_idx ON channel_events (channel_id, timestamp); - --- This composite index supports the public GetChannelEvents query, which --- walks events for a given channel by id-keyset cursor (ORDER BY id ASC, --- WHERE id > $cursor). Without it, the planner would scan every event with --- id > $cursor across all channels and filter by channel_id afterwards. -CREATE INDEX IF NOT EXISTS channel_events_chan_id_id_idx ON channel_events (channel_id, id); diff --git a/db/sqlc/migrations/000002_chanevents_ts_idx.down.sql b/db/sqlc/migrations/000002_chanevents_ts_idx.down.sql deleted file mode 100644 index 0c18632..0000000 --- a/db/sqlc/migrations/000002_chanevents_ts_idx.down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP INDEX IF EXISTS channel_events_ts_idx; diff --git a/db/sqlc/migrations/000002_chanevents_ts_idx.up.sql b/db/sqlc/migrations/000002_chanevents_ts_idx.up.sql deleted file mode 100644 index 9f3aa6c..0000000 --- a/db/sqlc/migrations/000002_chanevents_ts_idx.up.sql +++ /dev/null @@ -1,6 +0,0 @@ --- This standalone timestamp index supports the global age-based prune in --- PruneChannelEvents, which deletes across all channels by timestamp with no --- channel_id predicate. The composite (channel_id, timestamp) index cannot --- serve that query because its leading column is channel_id, so without this --- index every retention prune would scan the full channel_events table. -CREATE INDEX IF NOT EXISTS channel_events_ts_idx ON channel_events (timestamp); diff --git a/db/sqlc/models.go b/db/sqlc/models.go deleted file mode 100644 index fa20db0..0000000 --- a/db/sqlc/models.go +++ /dev/null @@ -1,32 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. -// versions: -// sqlc v1.25.0 - -package sqlc - -import ( - "database/sql" - "time" -) - -type Channel struct { - ID int64 - ChannelPoint string - ShortChannelID int64 - PeerID int64 -} - -type ChannelEvent struct { - ID int64 - ChannelID int64 - EventType int16 - Timestamp time.Time - LocalBalanceSat sql.NullInt64 - RemoteBalanceSat sql.NullInt64 - IsSync bool -} - -type Peer struct { - ID int64 - Pubkey string -} diff --git a/db/sqlc/querier.go b/db/sqlc/querier.go deleted file mode 100644 index 5870af6..0000000 --- a/db/sqlc/querier.go +++ /dev/null @@ -1,34 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. -// versions: -// sqlc v1.25.0 - -package sqlc - -import ( - "context" - "time" -) - -type Querier interface { - GetChannelByChanPoint(ctx context.Context, channelPoint string) (Channel, error) - GetChannelByShortChanID(ctx context.Context, shortChannelID int64) (Channel, error) - GetChannelEvents(ctx context.Context, arg GetChannelEventsParams) ([]ChannelEvent, error) - GetChannels(ctx context.Context) ([]GetChannelsRow, error) - GetLatestChannelEventBefore(ctx context.Context, arg GetLatestChannelEventBeforeParams) (ChannelEvent, error) - GetPeerByPubKey(ctx context.Context, pubkey string) (Peer, error) - InsertChannel(ctx context.Context, arg InsertChannelParams) (int64, error) - InsertChannelEvent(ctx context.Context, arg InsertChannelEventParams) error - InsertPeer(ctx context.Context, pubkey string) (int64, error) - // PruneChannelEventsByAge enforces the retention window on the channel_events - // table, returning the number of rows deleted. It deletes any row whose - // timestamp predates the given cutoff. - PruneChannelEventsByAge(ctx context.Context, timestamp time.Time) (int64, error) - // PruneChannelEventsBySize enforces the size ceiling on the channel_events - // table, returning the number of rows deleted. It keeps the newest rows by - // deleting everything with a smaller (earlier-inserted) id than the id found at - // the given offset from the newest row, so an offset of (max-events - 1) keeps - // exactly max-events rows. - PruneChannelEventsBySize(ctx context.Context, offset int32) (int64, error) -} - -var _ Querier = (*Queries)(nil) diff --git a/db/sqlc/queries/chanevents.sql b/db/sqlc/queries/chanevents.sql deleted file mode 100644 index d32498d..0000000 --- a/db/sqlc/queries/chanevents.sql +++ /dev/null @@ -1,60 +0,0 @@ --- name: InsertPeer :one -INSERT INTO peers (pubkey) VALUES ($1) RETURNING id; - --- name: GetPeerByPubKey :one -SELECT * FROM peers WHERE pubkey = $1; - --- name: InsertChannel :one -INSERT INTO channels (channel_point, short_channel_id, peer_id) VALUES ($1, $2, $3) RETURNING id; - --- name: GetChannelByChanPoint :one -SELECT * FROM channels WHERE channel_point = $1; - --- name: GetChannelByShortChanID :one -SELECT * FROM channels WHERE short_channel_id = $1; - --- name: InsertChannelEvent :exec -INSERT INTO channel_events ( - channel_id, event_type, timestamp, local_balance_sat, remote_balance_sat, - is_sync -) VALUES ($1, $2, $3, $4, $5, $6); - --- name: GetChannelEvents :many -SELECT * FROM channel_events -WHERE channel_id = $1 - AND id > $2 - AND timestamp >= $3 - AND timestamp < $4 -ORDER BY id ASC -LIMIT $5; - --- name: GetLatestChannelEventBefore :one -SELECT * FROM channel_events -WHERE channel_id = $1 AND event_type = $2 AND timestamp < $3 -ORDER BY timestamp DESC, id DESC -LIMIT 1; - --- name: GetChannels :many -SELECT c.id, c.short_channel_id, p.pubkey -FROM channels c -JOIN peers p ON c.peer_id = p.id; - --- name: PruneChannelEventsBySize :execrows --- PruneChannelEventsBySize enforces the size ceiling on the channel_events --- table, returning the number of rows deleted. It keeps the newest rows by --- deleting everything with a smaller (earlier-inserted) id than the id found at --- the given offset from the newest row, so an offset of (max-events - 1) keeps --- exactly max-events rows. -DELETE FROM channel_events -WHERE channel_events.id < COALESCE(( - SELECT id FROM channel_events - ORDER BY id DESC - LIMIT 1 OFFSET $1 -), 0); - --- name: PruneChannelEventsByAge :execrows --- PruneChannelEventsByAge enforces the retention window on the channel_events --- table, returning the number of rows deleted. It deletes any row whose --- timestamp predates the given cutoff. -DELETE FROM channel_events -WHERE channel_events.timestamp < $1; diff --git a/db/sqlite.go b/db/sqlite.go deleted file mode 100644 index 4e831a0..0000000 --- a/db/sqlite.go +++ /dev/null @@ -1,23 +0,0 @@ -package db - -import ( - _ "modernc.org/sqlite" // Register relevant drivers. -) - -// SqliteConfig holds all the config arguments needed to interact with our -// sqlite DB. -// -// nolint: lll -type SqliteConfig struct { - // SkipMigrations if true, then all the tables will be created on start - // up if they don't already exist. - SkipMigrations bool `long:"skipmigrations" description:"Skip applying migrations on startup."` - - // SkipMigrationDbBackup if true, then a backup of the database will not - // be created before applying migrations. - SkipMigrationDbBackup bool `long:"skipmigrationdbbackup" description:"Skip creating a backup of the database before applying migrations."` - - // DatabaseFileName is the full file path where the database file can be - // found. - DatabaseFileName string `long:"dbfile" description:"The full path to the database."` -} diff --git a/docs/accounting.md b/docs/accounting.md index 0e083ab..cfbad51 100644 --- a/docs/accounting.md +++ b/docs/accounting.md @@ -1,30 +1,19 @@ # Accounting Reports Faraday produces accounting reports on a node's on chain and off chain activity. -These reports are formatted using the [Harmony Reporting -Standard](https://github.com/harmony-csv/harmony). +These reports are formatted using the [Harmony Reporting Standard](https://github.com/harmony-csv/harmony). This document provides a description of the entries in these reports. ## Bitcoin Backend -It is strongly recommended that Faraday is run with a connection to a Bitcoin -node when these reports are generated. This is required to lookup fee entries -for channel close transactions and sweep fees. If a connection to a bitcoin node -is not provided, warnings will be logged for the transactions that do not have -fee entries. +It is strongly recommended that Faraday is run with a connection to a Bitcon node when these reports are generated. This is required to lookup fee entries for channel close transactions and sweep fees. If a connection to a bitcoin node is not provided, warnings will be logged for the transactions that do not have fee entries. ## Common Fields -For brevity, the following fields which have the same meaning for each entry -will be omitted: -- Timestamp: The timestamp of the block that the channel open transaction - appeared in. -- Fiat: The value of the amount field in specified currency. Note that values - less than one satoshi will be rounded down to zero. +For brevity, the following fields which have the same meaning for each entry will be omitted: +- Timestamp: The timestamp of the block that the channel open transaction appeared in. +- Fiat: The value of the amount field in specified currency. Note that values less than one satoshi will be rounded down to zero. - OnChain: Whether the transaction occurred off chain, or on chain. -- Credit: True when an entry increased our balances, false when an entry - decreased our balances. +- Credit: True when an entry increased our balances, false when an entry decreased our balances. -Note that fee entries reference the entry they are associated with by appending -a fee marker (:-1) to the original reference. The fee entry will have a -reference formatted as follows: `original reference:-1`. +Note that fee entries reference the entry they are associated with by appending a fee marker (:-1) to the original reference. The fee entry will have a reference formatted as follows: `original reference:-1`. ## On Chain Reports @@ -33,9 +22,8 @@ Local channel open entry types represent channel opens that were initiated by our node. These entries are accompanied by a separate Channel Open Fees entry, because the opening party pays on chain fees. -- Amount: The amount in millisatoshis that we added to the channel, excluding on - chain fees. -- TXID: The on chain transaction ID for the channel open. +- Amount: The amount in millisatoshis that we added to the channel, excluding on chain fees. +- TxID: The on chain transaction ID for the channel open. - Reference: The unique channel ID assigned to the channel. - Note: A note with details of who opened the channel. @@ -54,113 +42,82 @@ The fees paid to open a channel that we initiated. Remote channel open entry types represent channels that were opened by remote peers. -- Amount: Zero, our balance is unaffected by remote channel creation, except for - a push amount listed below. -- TXID: The on chain transaction ID for the channel open. +- Amount: Zero, our balance is unaffected by remote channel creation, with the exception of a push amount listed below. +- TxID: The on chain transaction ID for the channel open. - Reference: The unique channel ID assigned to the channel. - Note: A note containing the pubkey of the peer that opened a channel to us. Known Omissions: -- Remote peers may push balance to our node as part of the funding flow. This - amount is not currently included in these reports. +- Remote peers may push balance to our node as part of the funding flow. This amount is not currently included in these reports. ### Channel Close Channel close entries represent the on chain close of a channel. -- Amount: The amount in millisatoshis that was paid out to us immediately on - channel close. -- TXID: The on chain transaction ID for the channel close. +- Amount: The amount in millisatoshis that was paid out to us immediately on channel close. +- TxID: The on chain transaction ID for the channel close. - Reference: The channel close transaction ID. - Note: A note indicating the type of channel close, and who initiated it. Known Omissions: -- If our balance is encumbered behind a timelock, or in an unresolved HTLC, it - will not be paid out as part of this transaction and must be resolved by - follow up on chain transactions. +- If our balance is encumbered behind a timelock, or in an unresolved htlc, it will not be paid out as part of this transaction and must be resolved by follow up on chain transactions. ### Channel Close Fee -Channel close fee entries represent the fees we paid on chain to close channels -that we initiated. Note that this includes the case where we opened the channel -but the remote party closed the channel. +Channel close fee entries represent the fees we paid on chain to close channels that we initiated. Note that this includes the case where we opened the channel but the remote party closed the channel. -- Amount: The amount in millisatoshis that we paid in on chain fees to close the - channel. -- TXID: The on chain transaction ID for the channel close. +- Amount: The amount in millisatoshis that we paid in on chain fees to close the channel. +- TxID: The on chain transaction ID for the channel close. - Reference: The channel close transaction ID:-1. - Note: Not set for close fees. Known Omissions: -- If a channel was closed before we started saving our channel information for - use after close (:/hist - bitfinexHistoryAPI = "https://api-pub.bitfinex.com" + - "/v2/candles/trade:%s:%s/hist" - - // bitfinexDefaultPair is the trading pair used to obtain BTC/USD - // prices. Trading pair symbols are formed prepending a "t". - bitfinexDefaultPair = "tBTCUSD" - - // bitfinexDefaultCurrency is the fiat currency returned. - bitfinexDefaultCurrency = "USD" - - // bitfinexCandleCap is the maximum number of candles the API returns - // per request. - bitfinexCandleCap = 10000 -) - -// bitfinexTimeframe maps a Granularity to the Bitfinex candle key string. -var bitfinexTimeframe = map[Granularity]string{ - GranularityHour: "1h", - GranularityDay: "1D", -} - -// bitfinexAPI implements the fiatBackend interface using the Bitfinex v2 -// public candles endpoint. -type bitfinexAPI struct { - // granularity controls the candle bucket size (hour or day). - granularity Granularity - - // pair is the Bitfinex symbol, e.g. "tBTCUSD". - pair string - - // client is the HTTP client used to make requests. - client *http.Client -} - -// newBitfinexAPI returns a bitfinexAPI that satisfies fiatBackend. -func newBitfinexAPI(g Granularity) *bitfinexAPI { - return &bitfinexAPI{ - granularity: g, - pair: bitfinexDefaultPair, - client: &http.Client{ - Timeout: 10 * time.Second, - }, - } -} - -// queryBitfinex performs one HTTP request for a single window of up to -// bitfinexCandleCap candles. Timestamps are in milliseconds. The sort=1 -// parameter requests ascending order. -func queryBitfinex(start, end time.Time, pair, timeframe string, - cl *http.Client) ([]byte, error) { - - base := fmt.Sprintf(bitfinexHistoryAPI, timeframe, pair) - params := url.Values{} - params.Set("limit", strconv.Itoa(bitfinexCandleCap)) - params.Set("start", strconv.FormatInt(start.UnixMilli(), 10)) - params.Set("end", strconv.FormatInt(end.UnixMilli(), 10)) - params.Set("sort", "1") - - // #nosec G107 – public data - resp, err := cl.Get(base + "?" + params.Encode()) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - return io.ReadAll(resp.Body) -} - -// parseBitfinexData parses the JSON response from the Bitfinex candles -// endpoint. -// -// Bitfinex v2 public candles endpoint -// -// GET https://api-pub.bitfinex.com -// /v2/candles/trade::/hist -// -// Response body -- array of fixed-width arrays (when sort=1, ascending): -// -// [ -// [ MTS, OPEN, CLOSE, HIGH, LOW, VOLUME ], -// ... -// ] -// -// Field meanings: -// - MTS -- millisecond timestamp (bucket open). -// - OPEN -- first execution price during the bucket interval. -// - CLOSE -- last execution price during the bucket interval. -// - HIGH -- highest execution price during the bucket interval. -// - LOW -- lowest execution price during the bucket interval. -// - VOLUME -- quantity of base asset traded during the bucket interval. -// -// We use the CLOSE price (index 2) to be consistent with the other -// backends. -func parseBitfinexData(data []byte) ([]*Price, error) { - var raw [][]float64 - if err := json.Unmarshal(data, &raw); err != nil { - return nil, err - } - - prices := make([]*Price, 0, len(raw)) - for _, c := range raw { - if len(c) < 3 { - continue - } - - ts := time.UnixMilli(int64(c[0])).UTC() - closePx := decimal.NewFromFloat(c[2]) - - prices = append(prices, &Price{ - Timestamp: ts, - Price: closePx, - Currency: bitfinexDefaultCurrency, - }) - } - - return prices, nil -} - -// rawPriceData satisfies the fiatBackend interface. -func (b *bitfinexAPI) rawPriceData(ctx context.Context, - startTime, endTime time.Time) ([]*Price, error) { - - tf, ok := bitfinexTimeframe[b.granularity] - if !ok { - return nil, fmt.Errorf("bitfinex: unsupported granularity %v", - b.granularity.label) - } - - // Each request returns at most bitfinexCandleCap candles. We page - // forward by advancing start past the last received timestamp. - chunk := b.granularity.aggregation * bitfinexCandleCap - start := startTime.Truncate(b.granularity.aggregation) - end := start.Add(chunk) - if end.After(endTime) { - end = endTime - } - - var all []*Price - seen := make(map[int64]struct{}) - for start.Before(endTime) { - queryStart, queryEnd := start, end - query := func() ([]byte, error) { - return queryBitfinex( - queryStart, queryEnd, b.pair, tf, b.client, - ) - } - - records, err := retryQuery(ctx, query, parseBitfinexData) - if err != nil { - return nil, err - } - - // Bitfinex candles can include boundary timestamps for both - // start and end. Filter duplicates across page boundaries by - // timestamp. - for _, record := range records { - ts := record.Timestamp.UnixMilli() - if _, ok := seen[ts]; ok { - continue - } - - seen[ts] = struct{}{} - all = append(all, record) - } - - start = end - end = start.Add(chunk) - if end.After(endTime) { - end = endTime - } - } - - return all, nil -} diff --git a/fiat/bitfinex_api_test.go b/fiat/bitfinex_api_test.go deleted file mode 100644 index 7f3089a..0000000 --- a/fiat/bitfinex_api_test.go +++ /dev/null @@ -1,172 +0,0 @@ -package fiat - -import ( - "context" - "fmt" - "net/http" - "strconv" - "testing" - "time" - - "github.com/jarcoal/httpmock" - "github.com/shopspring/decimal" - "github.com/stretchr/testify/require" -) - -// TestParseBitfinexData tests parsing of the candle array format returned -// by the Bitfinex v2 public candles endpoint. -func TestParseBitfinexData(t *testing.T) { - t.Parallel() - - // Bitfinex returns: [MTS, OPEN, CLOSE, HIGH, LOW, VOLUME]. - // We use the CLOSE field (index 2). - ts1 := time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC) - ts2 := time.Date(2024, 1, 1, 1, 0, 0, 0, time.UTC) - - input := []byte(`[ - [` + fmt.Sprintf("%d", ts1.UnixMilli()) + - `, 42000.0, 42100.5, 42200.0, 41900.0, 12.5], - [` + fmt.Sprintf("%d", ts2.UnixMilli()) + - `, 42100.0, 42300.0, 42400.0, 42050.0, 8.3] - ]`) - - prices, err := parseBitfinexData(input) - require.NoError(t, err) - - expected := []*Price{ - { - Timestamp: ts1, - Price: decimal.NewFromFloat(42100.5), - Currency: "USD", - }, - { - Timestamp: ts2, - Price: decimal.NewFromFloat(42300.0), - Currency: "USD", - }, - } - require.Equal(t, expected, prices) -} - -// TestParseBitfinexDataShortRow verifies that rows with fewer than 3 -// elements are silently skipped. -func TestParseBitfinexDataShortRow(t *testing.T) { - t.Parallel() - - input := []byte(`[[1700000000000, 42000.0], [1700003600000, ` + - `42100.0, 42200.0, 42300.0, 42050.0, 5.0]]`) - prices, err := parseBitfinexData(input) - require.NoError(t, err) - require.Len(t, prices, 1) - require.Equal(t, decimal.NewFromFloat(42200.0), prices[0].Price) -} - -// TestBitfinexRawPriceData tests the paging logic of rawPriceData using a -// mocked HTTP transport. -func TestBitfinexRawPriceData(t *testing.T) { - now := time.Now().UTC().Truncate(time.Hour) - start := now.Add(-time.Hour * 4) - - mock := httpmock.NewMockTransport() - client := &http.Client{Transport: mock} - - const numCandles = 4 - candles := make([][]float64, numCandles) - for i := range candles { - ts := start.Add(time.Duration(i) * time.Hour) - candles[i] = []float64{ - float64(ts.UnixMilli()), - float64(45000 + i), // open - float64(50000 + i), // close - float64(55000 + i), // high - float64(44000 + i), // low - 1.0, // volume - } - } - - expected := make([]*Price, numCandles) - for i := range expected { - expected[i] = &Price{ - Timestamp: start.Add(time.Hour * time.Duration(i)), - Price: decimal.NewFromFloat(float64(50000 + i)), - Currency: "USD", - } - } - - mock.RegisterResponder( - "GET", `=~https://api-pub.bitfinex.com/.*`, - httpmock.NewJsonResponderOrPanic(200, candles), - ) - - api := newBitfinexAPI(GranularityHour) - api.client = client - - ctx := context.Background() - out, err := api.rawPriceData(ctx, start, now) - require.NoError(t, err) - require.EqualValues(t, expected, out) -} - -// TestBitfinexRawPriceDataNoDuplicateBoundaries verifies that page boundaries -// do not produce duplicate timestamps when multiple requests are made. -func TestBitfinexRawPriceDataNoDuplicateBoundaries(t *testing.T) { - t.Parallel() - - end := time.Now().UTC().Truncate(time.Hour) - start := end.Add(-time.Duration(bitfinexCandleCap+1) * time.Hour) - - mock := httpmock.NewMockTransport() - client := &http.Client{Transport: mock} - - var calls int - mock.RegisterResponder( - "GET", `=~https://api-pub.bitfinex.com/.*`, - func(req *http.Request) (*http.Response, error) { - calls++ - - query := req.URL.Query() - startMS, err := strconv.ParseInt( - query.Get("start"), 10, 64, - ) - if err != nil { - return nil, err - } - - endMS, err := strconv.ParseInt(query.Get("end"), 10, 64) - if err != nil { - return nil, err - } - - // Simulate an inclusive API that returns both - // boundaries. - candles := [][]float64{ - { - float64(startMS), 0, float64(startMS), - 0, 0, 1, - }, - { - float64(endMS), 0, float64(endMS), - 0, 0, 1, - }, - } - - return httpmock.NewJsonResponse(200, candles) - }, - ) - - api := newBitfinexAPI(GranularityHour) - api.client = client - - out, err := api.rawPriceData(context.Background(), start, end) - require.NoError(t, err) - require.GreaterOrEqual(t, calls, 2, "expected paging to occur") - - seen := make(map[int64]struct{}, len(out)) - for _, price := range out { - ts := price.Timestamp.UnixMilli() - _, ok := seen[ts] - require.False(t, ok, "duplicate timestamp: %v", price.Timestamp) - - seen[ts] = struct{}{} - } -} diff --git a/fiat/coinbase_api.go b/fiat/coinbase_api.go deleted file mode 100644 index 622e6bc..0000000 --- a/fiat/coinbase_api.go +++ /dev/null @@ -1,161 +0,0 @@ -package fiat - -import ( - "context" - "encoding/json" - "fmt" - "io" - "net/http" - "time" - - "github.com/shopspring/decimal" -) - -const ( - coinbaseHistoryAPI = "https://api.exchange.coinbase.com/products/%s/candles" - coinbaseDefaultPair = "BTC-USD" - coinbaseCandleCap = 300 // max buckets. - coinbaseGranHourSec = 3600 // 1‑hour buckets. - coinbaseGranDaySec = 86400 // 1‑day buckets. - coinbaseDefaultCurr = "USD" -) - -type coinbaseAPI struct { - // granularity is the price granularity (must be GranularityHour or - // GranularityDay for coinbase). - granularity Granularity - - // product is the Coinbase product pair (e.g. BTC-USD). - product string - - // client is the HTTP client used to make requests. - client *http.Client -} - -// newCoinbaseAPI returns an implementation that satisfies fiatBackend. -func newCoinbaseAPI(g Granularity) *coinbaseAPI { - return &coinbaseAPI{ - granularity: g, - product: coinbaseDefaultPair, - client: &http.Client{ - Timeout: 10 * time.Second, - }, - } -} - -// queryCoinbase performs one HTTP request for a single <300‑bucket window. -func queryCoinbase(start, end time.Time, product string, - g Granularity, cl *http.Client) ([]byte, error) { - - url := fmt.Sprintf(coinbaseHistoryAPI, product) + - fmt.Sprintf("?start=%s&end=%s&granularity=%d", - start.Format(time.RFC3339), - end.Format(time.RFC3339), - int(g.aggregation.Seconds())) - - // #nosec G107 – public data - resp, err := cl.Get(url) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - return io.ReadAll(resp.Body) -} - -// parseCoinbaseData parses the JSON response from Coinbase's candles endpoint. -// -// Coinbase “product candles” endpoint -// -// GET https://api.exchange.coinbase.com/products//candles -// -// Response body ─ array of fixed‑width arrays: -// -// [ -// [ time, low, high, open, close, volume ], -// ... -// ] -// -// Field meanings (per Coinbase docs [1]): -// - time – UNIX epoch **seconds** marking the *start* of the bucket (UTC). -// - low – lowest trade price during the bucket interval. -// - high – highest trade price during the bucket interval. -// - open – price of the first trade in the interval. -// - close – price of the last trade in the interval. -// - volume – amount of the base‑asset traded during the interval. -// -// Additional quirks -// - Candles are returned in *reverse‑chronological* order (newest‑first). -// - `granularity` must be one of 60, 300, 900, 3600, 21600, 86400 seconds. -// - A single request can return at most 300 buckets; larger spans must be -// paged by adjusting `start`/`end` query parameters. -// -// Example (1‑hour granularity, newest‑first): -// -// [ -// [1714632000, 64950.12, 65080.00, 65010.55, 65075.00, 84.213], -// [1714628400, 64890.00, 65020.23, 64900.00, 64950.12, 92.441], -// ... -// ] -// -// [1] https://docs.cdp.coinbase.com/exchange/reference/exchangerestapi_getproductcandles -func parseCoinbaseData(data []byte) ([]*Price, error) { - var raw [][]float64 - if err := json.Unmarshal(data, &raw); err != nil { - return nil, err - } - - prices := make([]*Price, 0, len(raw)) - for _, c := range raw { - // Historical rate data may be incomplete. No data is published - // for intervals where there are no ticks. - if len(c) < 5 { - continue - } - ts := time.Unix(int64(c[0]), 0).UTC() - closePx := decimal.NewFromFloat(c[4]) - - prices = append(prices, &Price{ - Timestamp: ts, - Price: closePx, - Currency: coinbaseDefaultCurr, - }) - } - return prices, nil -} - -// rawPriceData satisfies the fiatBackend interface. -func (c *coinbaseAPI) rawPriceData(ctx context.Context, - startTime, endTime time.Time) ([]*Price, error) { - - // Coinbase cap = 300 * granularity. - chunk := c.granularity.aggregation * coinbaseCandleCap - start := startTime.Truncate(c.granularity.aggregation) - end := start.Add(chunk) - if end.After(endTime) { - end = endTime - } - - var all []*Price - for start.Before(endTime) { - query := func() ([]byte, error) { - return queryCoinbase( - start, end, c.product, c.granularity, c.client, - ) - } - - records, err := retryQuery(ctx, query, parseCoinbaseData) - if err != nil { - return nil, err - } - all = append(all, records...) - - start = end - end = start.Add(chunk) - if end.After(endTime) { - end = endTime - } - } - - return all, nil -} diff --git a/fiat/log.go b/fiat/log.go index d2811fc..7e06cd7 100644 --- a/fiat/log.go +++ b/fiat/log.go @@ -1,7 +1,7 @@ package fiat import ( - "github.com/btcsuite/btclog/v2" + "github.com/btcsuite/btclog" "github.com/lightningnetwork/lnd/build" ) diff --git a/fiat/prices.go b/fiat/prices.go index 00cd1c2..97e4f18 100644 --- a/fiat/prices.go +++ b/fiat/prices.go @@ -105,26 +105,6 @@ func (cfg *PriceSourceConfig) validatePriceSourceConfig() error { if len(cfg.PricePoints) == 0 { return errPricePointsRequired } - - case CoinbasePriceBackend: - if cfg.Granularity == nil || - (*cfg.Granularity != GranularityHour && - *cfg.Granularity != GranularityDay) { - - return fmt.Errorf("%w: coinbase supports hourly or "+ - "daily granularity only", - errGranularityUnsupported) - } - - case BitfinexPriceBackend: - if cfg.Granularity == nil || - (*cfg.Granularity != GranularityHour && - *cfg.Granularity != GranularityDay) { - - return fmt.Errorf("%w: bitfinex supports hourly or "+ - "daily granularity only", - errGranularityUnsupported) - } } return nil @@ -182,12 +162,6 @@ const ( // CoinGeckoPriceBackend uses CoinGecko's API for fiat price data. CoinGeckoPriceBackend - - // CoinbasePriceBackend uses Coinbase's API for fiat price data. - CoinbasePriceBackend - - // BitfinexPriceBackend uses Bitfinex's API for fiat price data. - BitfinexPriceBackend ) var priceBackendNames = map[PriceBackend]string{ @@ -196,8 +170,6 @@ var priceBackendNames = map[PriceBackend]string{ CoinDeskPriceBackend: "coindesk", CustomPriceBackend: "custom", CoinGeckoPriceBackend: "coingecko", - CoinbasePriceBackend: "coinbase", - BitfinexPriceBackend: "bitfinex", } // String returns the string representation of a price backend. @@ -240,16 +212,6 @@ func NewPriceSource(cfg *PriceSourceConfig) (*PriceSource, error) { return &PriceSource{ impl: &coinGeckoAPI{}, }, nil - - case CoinbasePriceBackend: - return &PriceSource{ - impl: newCoinbaseAPI(*cfg.Granularity), - }, nil - - case BitfinexPriceBackend: - return &PriceSource{ - impl: newBitfinexAPI(*cfg.Granularity), - }, nil } return nil, errUnknownPriceBackend diff --git a/fiat/prices_test.go b/fiat/prices_test.go index 7b30c08..12668f9 100644 --- a/fiat/prices_test.go +++ b/fiat/prices_test.go @@ -1,13 +1,10 @@ package fiat import ( - "context" "errors" - "net/http" "testing" "time" - "github.com/jarcoal/httpmock" "github.com/lightningnetwork/lnd/lnwire" "github.com/shopspring/decimal" "github.com/stretchr/testify/require" @@ -232,35 +229,6 @@ func TestValidatePriceSourceConfig(t *testing.T) { }, expectedErr: errGranularityUnsupported, }, - { - name: "bitfinex hourly granularity", - cfg: &PriceSourceConfig{ - Backend: BitfinexPriceBackend, - Granularity: &GranularityHour, - }, - }, - { - name: "bitfinex daily granularity", - cfg: &PriceSourceConfig{ - Backend: BitfinexPriceBackend, - Granularity: &GranularityDay, - }, - }, - { - name: "bitfinex no granularity disallowed", - cfg: &PriceSourceConfig{ - Backend: BitfinexPriceBackend, - }, - expectedErr: errGranularityUnsupported, - }, - { - name: "bitfinex minute granularity disallowed", - cfg: &PriceSourceConfig{ - Backend: BitfinexPriceBackend, - Granularity: &GranularityMinute, - }, - expectedErr: errGranularityUnsupported, - }, } for _, test := range tests { @@ -277,57 +245,3 @@ func TestValidatePriceSourceConfig(t *testing.T) { }) } } - -// TestCoinbaseRawPriceData tests the rawPriceData method of the Coinbase API -// implementation. -func TestCoinbaseRawPriceData(t *testing.T) { - now := time.Now().UTC().Truncate(time.Hour) - start := now.Add(-time.Hour * 4) - - // Stub HTTP client with httpmock (same pattern as CoinCap tests). - mock := httpmock.NewMockTransport() - client := &http.Client{Transport: mock} - - // JSON response for the Coinbase API. - const numCandles = 4 - candles := make([][]float64, numCandles) - - for i := range candles { - timestamp := start.Add(time.Duration(i) * time.Hour).Unix() - - // Example values; tweak as needed. - low := 45_000 + float64(i) - high := 55_000 + float64(i) - open := 0.0 - close := 50_000 + float64(i) - vol := 0.0 - - candles[i] = []float64{ - float64(timestamp), low, high, open, close, vol, - } - } - - expected := make([]*Price, numCandles) - for i := range expected { - expected[i] = &Price{ - Timestamp: start.Add(time.Hour * time.Duration(i)), - Price: decimal.NewFromFloat(float64(50_000 + i)), - Currency: "USD", - } - } - - // Four hourly candles (close = 50000) returned. - mock.RegisterResponder( - "GET", `=~https://api.exchange.coinbase.com/.*`, - httpmock.NewJsonResponderOrPanic(200, candles), - ) - - api := newCoinbaseAPI(GranularityHour) - api.client = client - - ctx := context.Background() - out, err := api.rawPriceData(ctx, start, now) - require.NoError(t, err) - - require.EqualValues(t, expected, out) -} diff --git a/frdrpc/Dockerfile b/frdrpc/Dockerfile index 9cfb571..0ae7b5e 100644 --- a/frdrpc/Dockerfile +++ b/frdrpc/Dockerfile @@ -1,9 +1,9 @@ -FROM golang:1.25.10-bookworm +FROM golang:1.19.4-buster RUN apt-get update && apt-get install -y \ git \ - protobuf-compiler='3.21.12*' \ - clang-format='1:14.0*' + protobuf-compiler='3.6.1*' \ + clang-format='1:7.0*' # We don't want any default values for these variables to make sure they're # explicitly provided by parsing the go.mod file. Otherwise we might forget to diff --git a/frdrpc/faraday.pb.go b/frdrpc/faraday.pb.go index e854008..eecf269 100644 --- a/frdrpc/faraday.pb.go +++ b/frdrpc/faraday.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.2 -// protoc v3.21.12 +// protoc-gen-go v1.27.1 +// protoc v3.6.1 // source: faraday.proto package frdrpc @@ -109,10 +109,6 @@ const ( // This API is reached through the following URL: // https://api.coingecko.com/api/v3/coins/bitcoin/market_chart FiatBackend_COINGECKO FiatBackend = 4 - // Use the Bitfinex API for fiat price information. - // This API is reached through the following URL: - // https://api-pub.bitfinex.com/v2/candles/trade:1h:tBTCUSD/hist - FiatBackend_BITFINEX FiatBackend = 5 ) // Enum value maps for FiatBackend. @@ -123,7 +119,6 @@ var ( 2: "COINDESK", 3: "CUSTOM", 4: "COINGECKO", - 5: "BITFINEX", } FiatBackend_value = map[string]int32{ "UNKNOWN_FIATBACKEND": 0, @@ -131,7 +126,6 @@ var ( "COINDESK": 2, "CUSTOM": 3, "COINGECKO": 4, - "BITFINEX": 5, } ) @@ -267,62 +261,6 @@ func (EntryType) EnumDescriptor() ([]byte, []int) { return file_faraday_proto_rawDescGZIP(), []int{2} } -type ChannelEventType int32 - -const ( - // An unknown event type. - ChannelEventType_CHAN_EVENT_UNKNOWN ChannelEventType = 0 - // An online event. - ChannelEventType_CHAN_EVENT_ONLINE ChannelEventType = 1 - // An offline event. - ChannelEventType_CHAN_EVENT_OFFLINE ChannelEventType = 2 - // A channel balance update event. - ChannelEventType_CHAN_EVENT_UPDATE ChannelEventType = 3 -) - -// Enum value maps for ChannelEventType. -var ( - ChannelEventType_name = map[int32]string{ - 0: "CHAN_EVENT_UNKNOWN", - 1: "CHAN_EVENT_ONLINE", - 2: "CHAN_EVENT_OFFLINE", - 3: "CHAN_EVENT_UPDATE", - } - ChannelEventType_value = map[string]int32{ - "CHAN_EVENT_UNKNOWN": 0, - "CHAN_EVENT_ONLINE": 1, - "CHAN_EVENT_OFFLINE": 2, - "CHAN_EVENT_UPDATE": 3, - } -) - -func (x ChannelEventType) Enum() *ChannelEventType { - p := new(ChannelEventType) - *p = x - return p -} - -func (x ChannelEventType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (ChannelEventType) Descriptor() protoreflect.EnumDescriptor { - return file_faraday_proto_enumTypes[3].Descriptor() -} - -func (ChannelEventType) Type() protoreflect.EnumType { - return &file_faraday_proto_enumTypes[3] -} - -func (x ChannelEventType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use ChannelEventType.Descriptor instead. -func (ChannelEventType) EnumDescriptor() ([]byte, []int) { - return file_faraday_proto_rawDescGZIP(), []int{3} -} - type CloseRecommendationRequest_Metric int32 const ( @@ -365,11 +303,11 @@ func (x CloseRecommendationRequest_Metric) String() string { } func (CloseRecommendationRequest_Metric) Descriptor() protoreflect.EnumDescriptor { - return file_faraday_proto_enumTypes[4].Descriptor() + return file_faraday_proto_enumTypes[3].Descriptor() } func (CloseRecommendationRequest_Metric) Type() protoreflect.EnumType { - return &file_faraday_proto_enumTypes[4] + return &file_faraday_proto_enumTypes[3] } func (x CloseRecommendationRequest_Metric) Number() protoreflect.EnumNumber { @@ -1968,505 +1906,6 @@ func (x *CloseReportResponse) GetCloseFee() string { return "" } -type ChannelEventsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The channel point of the channel to get events for, formatted txid:outpoint. - ChanPoint string `protobuf:"bytes,1,opt,name=chan_point,json=chanPoint,proto3" json:"chan_point,omitempty"` - // Lower time bound, inclusive, as Unix seconds. Independent filter — does - // not need to advance between paginated calls. Zero means no lower bound. - StartTime int64 `protobuf:"varint,2,opt,name=start_time,json=startTime,proto3" json:"start_time,omitempty"` - // Upper time bound, exclusive, as Unix seconds. Must be greater than or - // equal to start_time. Zero means "use the server's current time". - EndTime int64 `protobuf:"varint,3,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty"` - // The maximum number of events to return. If zero, the server default is - // used. The server enforces a hard cap; values above the cap are clamped. - MaxEvents uint32 `protobuf:"varint,4,opt,name=max_events,json=maxEvents,proto3" json:"max_events,omitempty"` - // Pagination cursor: id of the last event from the previous response. - // Pass zero on the first call; for subsequent calls pass the response's - // last_id to resume past already-returned events. - LastId int64 `protobuf:"varint,5,opt,name=last_id,json=lastId,proto3" json:"last_id,omitempty"` -} - -func (x *ChannelEventsRequest) Reset() { - *x = ChannelEventsRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_faraday_proto_msgTypes[22] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ChannelEventsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ChannelEventsRequest) ProtoMessage() {} - -func (x *ChannelEventsRequest) ProtoReflect() protoreflect.Message { - mi := &file_faraday_proto_msgTypes[22] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ChannelEventsRequest.ProtoReflect.Descriptor instead. -func (*ChannelEventsRequest) Descriptor() ([]byte, []int) { - return file_faraday_proto_rawDescGZIP(), []int{22} -} - -func (x *ChannelEventsRequest) GetChanPoint() string { - if x != nil { - return x.ChanPoint - } - return "" -} - -func (x *ChannelEventsRequest) GetStartTime() int64 { - if x != nil { - return x.StartTime - } - return 0 -} - -func (x *ChannelEventsRequest) GetEndTime() int64 { - if x != nil { - return x.EndTime - } - return 0 -} - -func (x *ChannelEventsRequest) GetMaxEvents() uint32 { - if x != nil { - return x.MaxEvents - } - return 0 -} - -func (x *ChannelEventsRequest) GetLastId() int64 { - if x != nil { - return x.LastId - } - return 0 -} - -type ChannelEventsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The list of channel events. - Events []*ChannelEvent `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"` - // Id of the last event returned, suitable as the next request's last_id. - // Zero when events is empty. - LastId int64 `protobuf:"varint,2,opt,name=last_id,json=lastId,proto3" json:"last_id,omitempty"` - // True when the page filled to the requested limit and more events may be - // available; callers should keep paginating until this is false. - HasMore bool `protobuf:"varint,3,opt,name=has_more,json=hasMore,proto3" json:"has_more,omitempty"` -} - -func (x *ChannelEventsResponse) Reset() { - *x = ChannelEventsResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_faraday_proto_msgTypes[23] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ChannelEventsResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ChannelEventsResponse) ProtoMessage() {} - -func (x *ChannelEventsResponse) ProtoReflect() protoreflect.Message { - mi := &file_faraday_proto_msgTypes[23] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ChannelEventsResponse.ProtoReflect.Descriptor instead. -func (*ChannelEventsResponse) Descriptor() ([]byte, []int) { - return file_faraday_proto_rawDescGZIP(), []int{23} -} - -func (x *ChannelEventsResponse) GetEvents() []*ChannelEvent { - if x != nil { - return x.Events - } - return nil -} - -func (x *ChannelEventsResponse) GetLastId() int64 { - if x != nil { - return x.LastId - } - return 0 -} - -func (x *ChannelEventsResponse) GetHasMore() bool { - if x != nil { - return x.HasMore - } - return false -} - -type ChannelEvent struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The timestamp of the event, as Unix seconds. - Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - // The type of the event. - EventType ChannelEventType `protobuf:"varint,2,opt,name=event_type,json=eventType,proto3,enum=frdrpc.ChannelEventType" json:"event_type,omitempty"` - // The channel's local balance at the time of the event in sat. - LocalBalance uint64 `protobuf:"varint,3,opt,name=local_balance,json=localBalance,proto3" json:"local_balance,omitempty"` - // The channel's remote balance at the time of the event in sat. - RemoteBalance uint64 `protobuf:"varint,4,opt,name=remote_balance,json=remoteBalance,proto3" json:"remote_balance,omitempty"` - // Server-assigned monotonic identity. Echo this back as the next - // request's last_id when paginating. - Id int64 `protobuf:"varint,5,opt,name=id,proto3" json:"id,omitempty"` -} - -func (x *ChannelEvent) Reset() { - *x = ChannelEvent{} - if protoimpl.UnsafeEnabled { - mi := &file_faraday_proto_msgTypes[24] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ChannelEvent) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ChannelEvent) ProtoMessage() {} - -func (x *ChannelEvent) ProtoReflect() protoreflect.Message { - mi := &file_faraday_proto_msgTypes[24] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ChannelEvent.ProtoReflect.Descriptor instead. -func (*ChannelEvent) Descriptor() ([]byte, []int) { - return file_faraday_proto_rawDescGZIP(), []int{24} -} - -func (x *ChannelEvent) GetTimestamp() int64 { - if x != nil { - return x.Timestamp - } - return 0 -} - -func (x *ChannelEvent) GetEventType() ChannelEventType { - if x != nil { - return x.EventType - } - return ChannelEventType_CHAN_EVENT_UNKNOWN -} - -func (x *ChannelEvent) GetLocalBalance() uint64 { - if x != nil { - return x.LocalBalance - } - return 0 -} - -func (x *ChannelEvent) GetRemoteBalance() uint64 { - if x != nil { - return x.RemoteBalance - } - return 0 -} - -func (x *ChannelEvent) GetId() int64 { - if x != nil { - return x.Id - } - return 0 -} - -type ForwardingAbilityRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The start time of the query range as unix seconds. A value of 0 means - // the earliest available data. - StartTime uint64 `protobuf:"varint,1,opt,name=start_time,json=startTime,proto3" json:"start_time,omitempty"` - // The end time of the query range as unix seconds. A value of 0 means the - // server's current time. - EndTime uint64 `protobuf:"varint,2,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty"` - // The minimum directional liquidity in satoshis for a peer pair to count as - // economically forwardable. A value of 0 selects the server default. Hold - // this constant across calls for comparable series. - LiquidityFloorSat uint64 `protobuf:"varint,3,opt,name=liquidity_floor_sat,json=liquidityFloorSat,proto3" json:"liquidity_floor_sat,omitempty"` - // The uptime fraction in [0, 1] at or above which a peer pair that did not - // forward is reported compactly as a single bit in up_but_idle_bitmask - // rather than as a full entry. A value of 0 selects the server default. - // Pairs below this threshold that also did not forward are omitted - // entirely. If no pair meets the threshold the server returns a - // FailedPrecondition error, since that indicates the node itself was down - // for the window and the data carries no signal. - UptimeThreshold float64 `protobuf:"fixed64,4,opt,name=uptime_threshold,json=uptimeThreshold,proto3" json:"uptime_threshold,omitempty"` -} - -func (x *ForwardingAbilityRequest) Reset() { - *x = ForwardingAbilityRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_faraday_proto_msgTypes[25] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ForwardingAbilityRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ForwardingAbilityRequest) ProtoMessage() {} - -func (x *ForwardingAbilityRequest) ProtoReflect() protoreflect.Message { - mi := &file_faraday_proto_msgTypes[25] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ForwardingAbilityRequest.ProtoReflect.Descriptor instead. -func (*ForwardingAbilityRequest) Descriptor() ([]byte, []int) { - return file_faraday_proto_rawDescGZIP(), []int{25} -} - -func (x *ForwardingAbilityRequest) GetStartTime() uint64 { - if x != nil { - return x.StartTime - } - return 0 -} - -func (x *ForwardingAbilityRequest) GetEndTime() uint64 { - if x != nil { - return x.EndTime - } - return 0 -} - -func (x *ForwardingAbilityRequest) GetLiquidityFloorSat() uint64 { - if x != nil { - return x.LiquidityFloorSat - } - return 0 -} - -func (x *ForwardingAbilityRequest) GetUptimeThreshold() float64 { - if x != nil { - return x.UptimeThreshold - } - return 0 -} - -type ForwardingAbilityResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Sorted list of unique compressed 33-byte public keys of the peers. - Peers [][]byte `protobuf:"bytes,1,rep,name=peers,proto3" json:"peers,omitempty"` - // Sparse list of forwarding ability entries. An entry is present only for a - // pair that forwarded volume, carrying its exact effective_uptime_s and - // forwarded_sat. Pairs that did not forward are never listed here; they are - // either flagged in quiet_uptime_bitmask or absent. Entries take precedence - // over the bitmask for the same pair. - Entries []*ForwardingAbilityEntry `protobuf:"bytes,2,rep,name=entries,proto3" json:"entries,omitempty"` - // The start of the window the metrics cover, as unix seconds. - StartTime int64 `protobuf:"varint,3,opt,name=start_time,json=startTime,proto3" json:"start_time,omitempty"` - // The end of the window the metrics cover, as unix seconds. - EndTime int64 `protobuf:"varint,4,opt,name=end_time,json=endTime,proto3" json:"end_time,omitempty"` - // A packed bitmask over the n*n ordered peer pairs, where n is the length - // of peers. The bit at index in*n+out is set when that pair held at least - // the uptime_threshold fraction of effective uptime over the window but did - // not forward: the dense "up but idle" population. A pair with a forwarded - // entry is never flagged here. A pair that is neither listed in entries nor - // flagged here had sub-threshold uptime and no forwards: treat it as zero. - UpButIdleBitmask []byte `protobuf:"bytes,5,opt,name=up_but_idle_bitmask,json=upButIdleBitmask,proto3" json:"up_but_idle_bitmask,omitempty"` - // The uptime fraction in [0, 1] used to populate up_but_idle_bitmask, - // echoed back so consumers know the threshold the server applied. - UptimeThreshold float64 `protobuf:"fixed64,6,opt,name=uptime_threshold,json=uptimeThreshold,proto3" json:"uptime_threshold,omitempty"` -} - -func (x *ForwardingAbilityResponse) Reset() { - *x = ForwardingAbilityResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_faraday_proto_msgTypes[26] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ForwardingAbilityResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ForwardingAbilityResponse) ProtoMessage() {} - -func (x *ForwardingAbilityResponse) ProtoReflect() protoreflect.Message { - mi := &file_faraday_proto_msgTypes[26] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ForwardingAbilityResponse.ProtoReflect.Descriptor instead. -func (*ForwardingAbilityResponse) Descriptor() ([]byte, []int) { - return file_faraday_proto_rawDescGZIP(), []int{26} -} - -func (x *ForwardingAbilityResponse) GetPeers() [][]byte { - if x != nil { - return x.Peers - } - return nil -} - -func (x *ForwardingAbilityResponse) GetEntries() []*ForwardingAbilityEntry { - if x != nil { - return x.Entries - } - return nil -} - -func (x *ForwardingAbilityResponse) GetStartTime() int64 { - if x != nil { - return x.StartTime - } - return 0 -} - -func (x *ForwardingAbilityResponse) GetEndTime() int64 { - if x != nil { - return x.EndTime - } - return 0 -} - -func (x *ForwardingAbilityResponse) GetUpButIdleBitmask() []byte { - if x != nil { - return x.UpButIdleBitmask - } - return nil -} - -func (x *ForwardingAbilityResponse) GetUptimeThreshold() float64 { - if x != nil { - return x.UptimeThreshold - } - return 0 -} - -type ForwardingAbilityEntry struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The indices of the incoming and outgoing peers packed into a single - // 32-bit integer: packed_idx = (in << 16) | out. This caps the peer set at - // 65535 peers per direction. - PackedIdx uint32 `protobuf:"varint,1,opt,name=packed_idx,json=packedIdx,proto3" json:"packed_idx,omitempty"` - // Seconds the peer pair held at least the requested liquidity floor of - // directional forwardable liquidity over the window. - EffectiveUptimeS int64 `protobuf:"varint,2,opt,name=effective_uptime_s,json=effectiveUptimeS,proto3" json:"effective_uptime_s,omitempty"` - // Total successfully forwarded amount over the window, in satoshis. - ForwardedSat int64 `protobuf:"varint,3,opt,name=forwarded_sat,json=forwardedSat,proto3" json:"forwarded_sat,omitempty"` -} - -func (x *ForwardingAbilityEntry) Reset() { - *x = ForwardingAbilityEntry{} - if protoimpl.UnsafeEnabled { - mi := &file_faraday_proto_msgTypes[27] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ForwardingAbilityEntry) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ForwardingAbilityEntry) ProtoMessage() {} - -func (x *ForwardingAbilityEntry) ProtoReflect() protoreflect.Message { - mi := &file_faraday_proto_msgTypes[27] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ForwardingAbilityEntry.ProtoReflect.Descriptor instead. -func (*ForwardingAbilityEntry) Descriptor() ([]byte, []int) { - return file_faraday_proto_rawDescGZIP(), []int{27} -} - -func (x *ForwardingAbilityEntry) GetPackedIdx() uint32 { - if x != nil { - return x.PackedIdx - } - return 0 -} - -func (x *ForwardingAbilityEntry) GetEffectiveUptimeS() int64 { - if x != nil { - return x.EffectiveUptimeS - } - return 0 -} - -func (x *ForwardingAbilityEntry) GetForwardedSat() int64 { - if x != nil { - return x.ForwardedSat - } - return 0 -} - var File_faraday_proto protoreflect.FileDescriptor var file_faraday_proto_rawDesc = []byte{ @@ -2699,167 +2138,82 @@ var file_faraday_proto_rawDesc = []byte{ 0x6e, 0x5f, 0x66, 0x65, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x70, 0x65, 0x6e, 0x46, 0x65, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x5f, 0x66, 0x65, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x46, 0x65, - 0x65, 0x22, 0xa7, 0x01, 0x0a, 0x14, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x68, - 0x61, 0x6e, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x63, 0x68, 0x61, 0x6e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, - 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x73, - 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, - 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x54, - 0x69, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x61, 0x78, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x6d, 0x61, 0x78, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x06, 0x6c, 0x61, 0x73, 0x74, 0x49, 0x64, 0x22, 0x79, 0x0a, 0x15, 0x43, - 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, - 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x06, 0x6c, 0x61, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x68, - 0x61, 0x73, 0x5f, 0x6d, 0x6f, 0x72, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x68, - 0x61, 0x73, 0x4d, 0x6f, 0x72, 0x65, 0x22, 0xc1, 0x01, 0x0a, 0x0c, 0x43, 0x68, 0x61, 0x6e, 0x6e, - 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x37, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, - 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x66, 0x72, 0x64, 0x72, - 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, - 0x79, 0x70, 0x65, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x23, - 0x0a, 0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x61, 0x6c, 0x61, - 0x6e, 0x63, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x62, 0x61, - 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x72, 0x65, 0x6d, - 0x6f, 0x74, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x22, 0xaf, 0x01, 0x0a, 0x18, 0x46, - 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, - 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x73, 0x74, 0x61, - 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, - 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, - 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x6c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x5f, 0x66, - 0x6c, 0x6f, 0x6f, 0x72, 0x5f, 0x73, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, - 0x6c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x46, 0x6c, 0x6f, 0x6f, 0x72, 0x53, 0x61, - 0x74, 0x12, 0x29, 0x0a, 0x10, 0x75, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x68, 0x72, 0x65, - 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0f, 0x75, 0x70, 0x74, - 0x69, 0x6d, 0x65, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x22, 0xff, 0x01, 0x0a, - 0x19, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x62, 0x69, 0x6c, 0x69, - 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x65, - 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, - 0x12, 0x38, 0x0a, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x1e, 0x2e, 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, 0x77, 0x61, - 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, - 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, - 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x6e, 0x64, - 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x65, 0x6e, 0x64, - 0x54, 0x69, 0x6d, 0x65, 0x12, 0x2d, 0x0a, 0x13, 0x75, 0x70, 0x5f, 0x62, 0x75, 0x74, 0x5f, 0x69, - 0x64, 0x6c, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x10, 0x75, 0x70, 0x42, 0x75, 0x74, 0x49, 0x64, 0x6c, 0x65, 0x42, 0x69, 0x74, 0x6d, - 0x61, 0x73, 0x6b, 0x12, 0x29, 0x0a, 0x10, 0x75, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x68, - 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0f, 0x75, - 0x70, 0x74, 0x69, 0x6d, 0x65, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x22, 0x8a, - 0x01, 0x0a, 0x16, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x63, - 0x6b, 0x65, 0x64, 0x5f, 0x69, 0x64, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x70, - 0x61, 0x63, 0x6b, 0x65, 0x64, 0x49, 0x64, 0x78, 0x12, 0x2c, 0x0a, 0x12, 0x65, 0x66, 0x66, 0x65, - 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x75, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x73, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x55, - 0x70, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, - 0x64, 0x65, 0x64, 0x5f, 0x73, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x66, - 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x64, 0x53, 0x61, 0x74, 0x2a, 0xa1, 0x01, 0x0a, 0x0b, - 0x47, 0x72, 0x61, 0x6e, 0x75, 0x6c, 0x61, 0x72, 0x69, 0x74, 0x79, 0x12, 0x17, 0x0a, 0x13, 0x55, - 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x47, 0x52, 0x41, 0x4e, 0x55, 0x4c, 0x41, 0x52, 0x49, - 0x54, 0x59, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x49, 0x4e, 0x55, 0x54, 0x45, 0x10, 0x01, - 0x12, 0x10, 0x0a, 0x0c, 0x46, 0x49, 0x56, 0x45, 0x5f, 0x4d, 0x49, 0x4e, 0x55, 0x54, 0x45, 0x53, - 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x46, 0x49, 0x46, 0x54, 0x45, 0x45, 0x4e, 0x5f, 0x4d, 0x49, - 0x4e, 0x55, 0x54, 0x45, 0x53, 0x10, 0x03, 0x12, 0x12, 0x0a, 0x0e, 0x54, 0x48, 0x49, 0x52, 0x54, - 0x59, 0x5f, 0x4d, 0x49, 0x4e, 0x55, 0x54, 0x45, 0x53, 0x10, 0x04, 0x12, 0x08, 0x0a, 0x04, 0x48, - 0x4f, 0x55, 0x52, 0x10, 0x05, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x49, 0x58, 0x5f, 0x48, 0x4f, 0x55, - 0x52, 0x53, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x57, 0x45, 0x4c, 0x56, 0x45, 0x5f, 0x48, - 0x4f, 0x55, 0x52, 0x53, 0x10, 0x07, 0x12, 0x07, 0x0a, 0x03, 0x44, 0x41, 0x59, 0x10, 0x08, 0x2a, - 0x6a, 0x0a, 0x0b, 0x46, 0x69, 0x61, 0x74, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x12, 0x17, - 0x0a, 0x13, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x46, 0x49, 0x41, 0x54, 0x42, 0x41, - 0x43, 0x4b, 0x45, 0x4e, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x4f, 0x49, 0x4e, 0x43, - 0x41, 0x50, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x4f, 0x49, 0x4e, 0x44, 0x45, 0x53, 0x4b, - 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x55, 0x53, 0x54, 0x4f, 0x4d, 0x10, 0x03, 0x12, 0x0d, - 0x0a, 0x09, 0x43, 0x4f, 0x49, 0x4e, 0x47, 0x45, 0x43, 0x4b, 0x4f, 0x10, 0x04, 0x12, 0x0c, 0x0a, - 0x08, 0x42, 0x49, 0x54, 0x46, 0x49, 0x4e, 0x45, 0x58, 0x10, 0x05, 0x2a, 0xa2, 0x02, 0x0a, 0x09, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, - 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x4f, 0x43, 0x41, 0x4c, 0x5f, - 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x10, 0x01, 0x12, 0x17, - 0x0a, 0x13, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, - 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x10, 0x02, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x48, 0x41, 0x4e, 0x4e, - 0x45, 0x4c, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x5f, 0x46, 0x45, 0x45, 0x10, 0x03, 0x12, 0x11, 0x0a, - 0x0d, 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x5f, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0x10, 0x04, - 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x45, 0x43, 0x45, 0x49, 0x50, 0x54, 0x10, 0x05, 0x12, 0x0b, 0x0a, - 0x07, 0x50, 0x41, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x10, 0x06, 0x12, 0x07, 0x0a, 0x03, 0x46, 0x45, - 0x45, 0x10, 0x07, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x49, 0x52, 0x43, 0x55, 0x4c, 0x41, 0x52, 0x5f, - 0x52, 0x45, 0x43, 0x45, 0x49, 0x50, 0x54, 0x10, 0x08, 0x12, 0x0b, 0x0a, 0x07, 0x46, 0x4f, 0x52, - 0x57, 0x41, 0x52, 0x44, 0x10, 0x09, 0x12, 0x0f, 0x0a, 0x0b, 0x46, 0x4f, 0x52, 0x57, 0x41, 0x52, - 0x44, 0x5f, 0x46, 0x45, 0x45, 0x10, 0x0a, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x49, 0x52, 0x43, 0x55, - 0x4c, 0x41, 0x52, 0x5f, 0x50, 0x41, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x10, 0x0b, 0x12, 0x10, 0x0a, - 0x0c, 0x43, 0x49, 0x52, 0x43, 0x55, 0x4c, 0x41, 0x52, 0x5f, 0x46, 0x45, 0x45, 0x10, 0x0c, 0x12, - 0x09, 0x0a, 0x05, 0x53, 0x57, 0x45, 0x45, 0x50, 0x10, 0x0d, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x57, - 0x45, 0x45, 0x50, 0x5f, 0x46, 0x45, 0x45, 0x10, 0x0e, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x48, 0x41, - 0x4e, 0x4e, 0x45, 0x4c, 0x5f, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0x5f, 0x46, 0x45, 0x45, 0x10, 0x0f, - 0x2a, 0x70, 0x0a, 0x10, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x43, 0x48, 0x41, 0x4e, 0x5f, 0x45, 0x56, 0x45, - 0x4e, 0x54, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, - 0x43, 0x48, 0x41, 0x4e, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x4f, 0x4e, 0x4c, 0x49, 0x4e, - 0x45, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x43, 0x48, 0x41, 0x4e, 0x5f, 0x45, 0x56, 0x45, 0x4e, - 0x54, 0x5f, 0x4f, 0x46, 0x46, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x43, - 0x48, 0x41, 0x4e, 0x5f, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, - 0x10, 0x03, 0x32, 0x83, 0x06, 0x0a, 0x0d, 0x46, 0x61, 0x72, 0x61, 0x64, 0x61, 0x79, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x12, 0x65, 0x0a, 0x16, 0x4f, 0x75, 0x74, 0x6c, 0x69, 0x65, 0x72, 0x52, - 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, - 0x2e, 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x75, 0x74, 0x6c, 0x69, 0x65, 0x72, 0x52, - 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, 0x2e, 0x43, - 0x6c, 0x6f, 0x73, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x18, 0x54, - 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x52, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, - 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x27, 0x2e, 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, - 0x2e, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x52, 0x65, 0x63, 0x6f, 0x6d, 0x6d, - 0x65, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x24, 0x2e, 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x52, - 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x0d, 0x52, 0x65, 0x76, 0x65, 0x6e, 0x75, - 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1c, 0x2e, 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, - 0x2e, 0x52, 0x65, 0x76, 0x65, 0x6e, 0x75, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, 0x2e, 0x52, - 0x65, 0x76, 0x65, 0x6e, 0x75, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0f, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x49, - 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x73, 0x12, 0x1e, 0x2e, 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, - 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, - 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0c, 0x45, 0x78, 0x63, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x52, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x2e, 0x66, 0x72, 0x64, 0x72, 0x70, - 0x63, 0x2e, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x61, 0x74, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, 0x2e, 0x45, - 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x09, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x75, 0x64, 0x69, 0x74, - 0x12, 0x18, 0x2e, 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x75, - 0x64, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x66, 0x72, 0x64, - 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x75, 0x64, 0x69, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0b, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x52, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x2e, 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, - 0x6f, 0x73, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1b, 0x2e, 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x52, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, - 0x10, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x73, 0x12, 0x1c, 0x2e, 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, - 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1d, 0x2e, 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, - 0x0a, 0x11, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x62, 0x69, 0x6c, - 0x69, 0x74, 0x79, 0x12, 0x20, 0x2e, 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, - 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, 0x2e, 0x46, - 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x29, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, - 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x66, 0x61, 0x72, 0x61, 0x64, 0x61, 0x79, 0x2f, 0x66, 0x72, 0x64, - 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x2a, 0xa1, 0x01, 0x0a, 0x0b, 0x47, 0x72, 0x61, 0x6e, 0x75, 0x6c, 0x61, 0x72, 0x69, 0x74, + 0x79, 0x12, 0x17, 0x0a, 0x13, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x47, 0x52, 0x41, + 0x4e, 0x55, 0x4c, 0x41, 0x52, 0x49, 0x54, 0x59, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x49, + 0x4e, 0x55, 0x54, 0x45, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x46, 0x49, 0x56, 0x45, 0x5f, 0x4d, + 0x49, 0x4e, 0x55, 0x54, 0x45, 0x53, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x46, 0x49, 0x46, 0x54, + 0x45, 0x45, 0x4e, 0x5f, 0x4d, 0x49, 0x4e, 0x55, 0x54, 0x45, 0x53, 0x10, 0x03, 0x12, 0x12, 0x0a, + 0x0e, 0x54, 0x48, 0x49, 0x52, 0x54, 0x59, 0x5f, 0x4d, 0x49, 0x4e, 0x55, 0x54, 0x45, 0x53, 0x10, + 0x04, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x4f, 0x55, 0x52, 0x10, 0x05, 0x12, 0x0d, 0x0a, 0x09, 0x53, + 0x49, 0x58, 0x5f, 0x48, 0x4f, 0x55, 0x52, 0x53, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x57, + 0x45, 0x4c, 0x56, 0x45, 0x5f, 0x48, 0x4f, 0x55, 0x52, 0x53, 0x10, 0x07, 0x12, 0x07, 0x0a, 0x03, + 0x44, 0x41, 0x59, 0x10, 0x08, 0x2a, 0x5c, 0x0a, 0x0b, 0x46, 0x69, 0x61, 0x74, 0x42, 0x61, 0x63, + 0x6b, 0x65, 0x6e, 0x64, 0x12, 0x17, 0x0a, 0x13, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, + 0x46, 0x49, 0x41, 0x54, 0x42, 0x41, 0x43, 0x4b, 0x45, 0x4e, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, + 0x07, 0x43, 0x4f, 0x49, 0x4e, 0x43, 0x41, 0x50, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x4f, + 0x49, 0x4e, 0x44, 0x45, 0x53, 0x4b, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x55, 0x53, 0x54, + 0x4f, 0x4d, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x49, 0x4e, 0x47, 0x45, 0x43, 0x4b, + 0x4f, 0x10, 0x04, 0x2a, 0xa2, 0x02, 0x0a, 0x09, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x16, + 0x0a, 0x12, 0x4c, 0x4f, 0x43, 0x41, 0x4c, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x5f, + 0x4f, 0x50, 0x45, 0x4e, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, + 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x10, 0x02, 0x12, + 0x14, 0x0a, 0x10, 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x5f, 0x4f, 0x50, 0x45, 0x4e, 0x5f, + 0x46, 0x45, 0x45, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, + 0x5f, 0x43, 0x4c, 0x4f, 0x53, 0x45, 0x10, 0x04, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x45, 0x43, 0x45, + 0x49, 0x50, 0x54, 0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x41, 0x59, 0x4d, 0x45, 0x4e, 0x54, + 0x10, 0x06, 0x12, 0x07, 0x0a, 0x03, 0x46, 0x45, 0x45, 0x10, 0x07, 0x12, 0x14, 0x0a, 0x10, 0x43, + 0x49, 0x52, 0x43, 0x55, 0x4c, 0x41, 0x52, 0x5f, 0x52, 0x45, 0x43, 0x45, 0x49, 0x50, 0x54, 0x10, + 0x08, 0x12, 0x0b, 0x0a, 0x07, 0x46, 0x4f, 0x52, 0x57, 0x41, 0x52, 0x44, 0x10, 0x09, 0x12, 0x0f, + 0x0a, 0x0b, 0x46, 0x4f, 0x52, 0x57, 0x41, 0x52, 0x44, 0x5f, 0x46, 0x45, 0x45, 0x10, 0x0a, 0x12, + 0x14, 0x0a, 0x10, 0x43, 0x49, 0x52, 0x43, 0x55, 0x4c, 0x41, 0x52, 0x5f, 0x50, 0x41, 0x59, 0x4d, + 0x45, 0x4e, 0x54, 0x10, 0x0b, 0x12, 0x10, 0x0a, 0x0c, 0x43, 0x49, 0x52, 0x43, 0x55, 0x4c, 0x41, + 0x52, 0x5f, 0x46, 0x45, 0x45, 0x10, 0x0c, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x57, 0x45, 0x45, 0x50, + 0x10, 0x0d, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x57, 0x45, 0x45, 0x50, 0x5f, 0x46, 0x45, 0x45, 0x10, + 0x0e, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x5f, 0x43, 0x4c, 0x4f, + 0x53, 0x45, 0x5f, 0x46, 0x45, 0x45, 0x10, 0x0f, 0x32, 0xd8, 0x04, 0x0a, 0x0d, 0x46, 0x61, 0x72, + 0x61, 0x64, 0x61, 0x79, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x65, 0x0a, 0x16, 0x4f, 0x75, + 0x74, 0x6c, 0x69, 0x65, 0x72, 0x52, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x2e, 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x75, + 0x74, 0x6c, 0x69, 0x65, 0x72, 0x52, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x66, 0x72, + 0x64, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x6d, 0x6d, + 0x65, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x69, 0x0a, 0x18, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x52, 0x65, + 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x27, 0x2e, + 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, + 0x52, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, 0x2e, + 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x0d, + 0x52, 0x65, 0x76, 0x65, 0x6e, 0x75, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1c, 0x2e, + 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x76, 0x65, 0x6e, 0x75, 0x65, 0x52, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x66, 0x72, + 0x64, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x76, 0x65, 0x6e, 0x75, 0x65, 0x52, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0f, 0x43, 0x68, + 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x73, 0x12, 0x1e, 0x2e, + 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x49, 0x6e, + 0x73, 0x69, 0x67, 0x68, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, + 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x49, 0x6e, + 0x73, 0x69, 0x67, 0x68, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, + 0x0a, 0x0c, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x61, 0x74, 0x65, 0x12, 0x1b, + 0x2e, 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x52, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x66, 0x72, + 0x64, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x61, 0x74, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x09, 0x4e, 0x6f, 0x64, + 0x65, 0x41, 0x75, 0x64, 0x69, 0x74, 0x12, 0x18, 0x2e, 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, 0x2e, + 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x75, 0x64, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x19, 0x2e, 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x41, 0x75, + 0x64, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0b, 0x43, + 0x6c, 0x6f, 0x73, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x2e, 0x66, 0x72, 0x64, + 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, 0x2e, + 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x42, 0x29, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x6c, 0x61, 0x62, 0x73, 0x2f, + 0x66, 0x61, 0x72, 0x61, 0x64, 0x61, 0x79, 0x2f, 0x66, 0x72, 0x64, 0x72, 0x70, 0x63, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2874,91 +2228,77 @@ func file_faraday_proto_rawDescGZIP() []byte { return file_faraday_proto_rawDescData } -var file_faraday_proto_enumTypes = make([]protoimpl.EnumInfo, 5) -var file_faraday_proto_msgTypes = make([]protoimpl.MessageInfo, 29) -var file_faraday_proto_goTypes = []any{ +var file_faraday_proto_enumTypes = make([]protoimpl.EnumInfo, 4) +var file_faraday_proto_msgTypes = make([]protoimpl.MessageInfo, 23) +var file_faraday_proto_goTypes = []interface{}{ (Granularity)(0), // 0: frdrpc.Granularity (FiatBackend)(0), // 1: frdrpc.FiatBackend (EntryType)(0), // 2: frdrpc.EntryType - (ChannelEventType)(0), // 3: frdrpc.ChannelEventType - (CloseRecommendationRequest_Metric)(0), // 4: frdrpc.CloseRecommendationRequest.Metric - (*CloseRecommendationRequest)(nil), // 5: frdrpc.CloseRecommendationRequest - (*OutlierRecommendationsRequest)(nil), // 6: frdrpc.OutlierRecommendationsRequest - (*ThresholdRecommendationsRequest)(nil), // 7: frdrpc.ThresholdRecommendationsRequest - (*CloseRecommendationsResponse)(nil), // 8: frdrpc.CloseRecommendationsResponse - (*Recommendation)(nil), // 9: frdrpc.Recommendation - (*RevenueReportRequest)(nil), // 10: frdrpc.RevenueReportRequest - (*RevenueReportResponse)(nil), // 11: frdrpc.RevenueReportResponse - (*RevenueReport)(nil), // 12: frdrpc.RevenueReport - (*PairReport)(nil), // 13: frdrpc.PairReport - (*ChannelInsightsRequest)(nil), // 14: frdrpc.ChannelInsightsRequest - (*ChannelInsightsResponse)(nil), // 15: frdrpc.ChannelInsightsResponse - (*ChannelInsight)(nil), // 16: frdrpc.ChannelInsight - (*ExchangeRateRequest)(nil), // 17: frdrpc.ExchangeRateRequest - (*ExchangeRateResponse)(nil), // 18: frdrpc.ExchangeRateResponse - (*BitcoinPrice)(nil), // 19: frdrpc.BitcoinPrice - (*ExchangeRate)(nil), // 20: frdrpc.ExchangeRate - (*NodeAuditRequest)(nil), // 21: frdrpc.NodeAuditRequest - (*CustomCategory)(nil), // 22: frdrpc.CustomCategory - (*ReportEntry)(nil), // 23: frdrpc.ReportEntry - (*NodeAuditResponse)(nil), // 24: frdrpc.NodeAuditResponse - (*CloseReportRequest)(nil), // 25: frdrpc.CloseReportRequest - (*CloseReportResponse)(nil), // 26: frdrpc.CloseReportResponse - (*ChannelEventsRequest)(nil), // 27: frdrpc.ChannelEventsRequest - (*ChannelEventsResponse)(nil), // 28: frdrpc.ChannelEventsResponse - (*ChannelEvent)(nil), // 29: frdrpc.ChannelEvent - (*ForwardingAbilityRequest)(nil), // 30: frdrpc.ForwardingAbilityRequest - (*ForwardingAbilityResponse)(nil), // 31: frdrpc.ForwardingAbilityResponse - (*ForwardingAbilityEntry)(nil), // 32: frdrpc.ForwardingAbilityEntry - nil, // 33: frdrpc.RevenueReport.PairReportsEntry + (CloseRecommendationRequest_Metric)(0), // 3: frdrpc.CloseRecommendationRequest.Metric + (*CloseRecommendationRequest)(nil), // 4: frdrpc.CloseRecommendationRequest + (*OutlierRecommendationsRequest)(nil), // 5: frdrpc.OutlierRecommendationsRequest + (*ThresholdRecommendationsRequest)(nil), // 6: frdrpc.ThresholdRecommendationsRequest + (*CloseRecommendationsResponse)(nil), // 7: frdrpc.CloseRecommendationsResponse + (*Recommendation)(nil), // 8: frdrpc.Recommendation + (*RevenueReportRequest)(nil), // 9: frdrpc.RevenueReportRequest + (*RevenueReportResponse)(nil), // 10: frdrpc.RevenueReportResponse + (*RevenueReport)(nil), // 11: frdrpc.RevenueReport + (*PairReport)(nil), // 12: frdrpc.PairReport + (*ChannelInsightsRequest)(nil), // 13: frdrpc.ChannelInsightsRequest + (*ChannelInsightsResponse)(nil), // 14: frdrpc.ChannelInsightsResponse + (*ChannelInsight)(nil), // 15: frdrpc.ChannelInsight + (*ExchangeRateRequest)(nil), // 16: frdrpc.ExchangeRateRequest + (*ExchangeRateResponse)(nil), // 17: frdrpc.ExchangeRateResponse + (*BitcoinPrice)(nil), // 18: frdrpc.BitcoinPrice + (*ExchangeRate)(nil), // 19: frdrpc.ExchangeRate + (*NodeAuditRequest)(nil), // 20: frdrpc.NodeAuditRequest + (*CustomCategory)(nil), // 21: frdrpc.CustomCategory + (*ReportEntry)(nil), // 22: frdrpc.ReportEntry + (*NodeAuditResponse)(nil), // 23: frdrpc.NodeAuditResponse + (*CloseReportRequest)(nil), // 24: frdrpc.CloseReportRequest + (*CloseReportResponse)(nil), // 25: frdrpc.CloseReportResponse + nil, // 26: frdrpc.RevenueReport.PairReportsEntry } var file_faraday_proto_depIdxs = []int32{ - 4, // 0: frdrpc.CloseRecommendationRequest.metric:type_name -> frdrpc.CloseRecommendationRequest.Metric - 5, // 1: frdrpc.OutlierRecommendationsRequest.rec_request:type_name -> frdrpc.CloseRecommendationRequest - 5, // 2: frdrpc.ThresholdRecommendationsRequest.rec_request:type_name -> frdrpc.CloseRecommendationRequest - 9, // 3: frdrpc.CloseRecommendationsResponse.recommendations:type_name -> frdrpc.Recommendation - 12, // 4: frdrpc.RevenueReportResponse.reports:type_name -> frdrpc.RevenueReport - 33, // 5: frdrpc.RevenueReport.pair_reports:type_name -> frdrpc.RevenueReport.PairReportsEntry - 16, // 6: frdrpc.ChannelInsightsResponse.channel_insights:type_name -> frdrpc.ChannelInsight + 3, // 0: frdrpc.CloseRecommendationRequest.metric:type_name -> frdrpc.CloseRecommendationRequest.Metric + 4, // 1: frdrpc.OutlierRecommendationsRequest.rec_request:type_name -> frdrpc.CloseRecommendationRequest + 4, // 2: frdrpc.ThresholdRecommendationsRequest.rec_request:type_name -> frdrpc.CloseRecommendationRequest + 8, // 3: frdrpc.CloseRecommendationsResponse.recommendations:type_name -> frdrpc.Recommendation + 11, // 4: frdrpc.RevenueReportResponse.reports:type_name -> frdrpc.RevenueReport + 26, // 5: frdrpc.RevenueReport.pair_reports:type_name -> frdrpc.RevenueReport.PairReportsEntry + 15, // 6: frdrpc.ChannelInsightsResponse.channel_insights:type_name -> frdrpc.ChannelInsight 0, // 7: frdrpc.ExchangeRateRequest.granularity:type_name -> frdrpc.Granularity 1, // 8: frdrpc.ExchangeRateRequest.fiat_backend:type_name -> frdrpc.FiatBackend - 19, // 9: frdrpc.ExchangeRateRequest.custom_prices:type_name -> frdrpc.BitcoinPrice - 20, // 10: frdrpc.ExchangeRateResponse.rates:type_name -> frdrpc.ExchangeRate - 19, // 11: frdrpc.ExchangeRate.btc_price:type_name -> frdrpc.BitcoinPrice + 18, // 9: frdrpc.ExchangeRateRequest.custom_prices:type_name -> frdrpc.BitcoinPrice + 19, // 10: frdrpc.ExchangeRateResponse.rates:type_name -> frdrpc.ExchangeRate + 18, // 11: frdrpc.ExchangeRate.btc_price:type_name -> frdrpc.BitcoinPrice 0, // 12: frdrpc.NodeAuditRequest.granularity:type_name -> frdrpc.Granularity - 22, // 13: frdrpc.NodeAuditRequest.custom_categories:type_name -> frdrpc.CustomCategory + 21, // 13: frdrpc.NodeAuditRequest.custom_categories:type_name -> frdrpc.CustomCategory 1, // 14: frdrpc.NodeAuditRequest.fiat_backend:type_name -> frdrpc.FiatBackend - 19, // 15: frdrpc.NodeAuditRequest.custom_prices:type_name -> frdrpc.BitcoinPrice + 18, // 15: frdrpc.NodeAuditRequest.custom_prices:type_name -> frdrpc.BitcoinPrice 2, // 16: frdrpc.ReportEntry.type:type_name -> frdrpc.EntryType - 19, // 17: frdrpc.ReportEntry.btc_price:type_name -> frdrpc.BitcoinPrice - 23, // 18: frdrpc.NodeAuditResponse.reports:type_name -> frdrpc.ReportEntry - 29, // 19: frdrpc.ChannelEventsResponse.events:type_name -> frdrpc.ChannelEvent - 3, // 20: frdrpc.ChannelEvent.event_type:type_name -> frdrpc.ChannelEventType - 32, // 21: frdrpc.ForwardingAbilityResponse.entries:type_name -> frdrpc.ForwardingAbilityEntry - 13, // 22: frdrpc.RevenueReport.PairReportsEntry.value:type_name -> frdrpc.PairReport - 6, // 23: frdrpc.FaradayServer.OutlierRecommendations:input_type -> frdrpc.OutlierRecommendationsRequest - 7, // 24: frdrpc.FaradayServer.ThresholdRecommendations:input_type -> frdrpc.ThresholdRecommendationsRequest - 10, // 25: frdrpc.FaradayServer.RevenueReport:input_type -> frdrpc.RevenueReportRequest - 14, // 26: frdrpc.FaradayServer.ChannelInsights:input_type -> frdrpc.ChannelInsightsRequest - 17, // 27: frdrpc.FaradayServer.ExchangeRate:input_type -> frdrpc.ExchangeRateRequest - 21, // 28: frdrpc.FaradayServer.NodeAudit:input_type -> frdrpc.NodeAuditRequest - 25, // 29: frdrpc.FaradayServer.CloseReport:input_type -> frdrpc.CloseReportRequest - 27, // 30: frdrpc.FaradayServer.GetChannelEvents:input_type -> frdrpc.ChannelEventsRequest - 30, // 31: frdrpc.FaradayServer.ForwardingAbility:input_type -> frdrpc.ForwardingAbilityRequest - 8, // 32: frdrpc.FaradayServer.OutlierRecommendations:output_type -> frdrpc.CloseRecommendationsResponse - 8, // 33: frdrpc.FaradayServer.ThresholdRecommendations:output_type -> frdrpc.CloseRecommendationsResponse - 11, // 34: frdrpc.FaradayServer.RevenueReport:output_type -> frdrpc.RevenueReportResponse - 15, // 35: frdrpc.FaradayServer.ChannelInsights:output_type -> frdrpc.ChannelInsightsResponse - 18, // 36: frdrpc.FaradayServer.ExchangeRate:output_type -> frdrpc.ExchangeRateResponse - 24, // 37: frdrpc.FaradayServer.NodeAudit:output_type -> frdrpc.NodeAuditResponse - 26, // 38: frdrpc.FaradayServer.CloseReport:output_type -> frdrpc.CloseReportResponse - 28, // 39: frdrpc.FaradayServer.GetChannelEvents:output_type -> frdrpc.ChannelEventsResponse - 31, // 40: frdrpc.FaradayServer.ForwardingAbility:output_type -> frdrpc.ForwardingAbilityResponse - 32, // [32:41] is the sub-list for method output_type - 23, // [23:32] is the sub-list for method input_type - 23, // [23:23] is the sub-list for extension type_name - 23, // [23:23] is the sub-list for extension extendee - 0, // [0:23] is the sub-list for field type_name + 18, // 17: frdrpc.ReportEntry.btc_price:type_name -> frdrpc.BitcoinPrice + 22, // 18: frdrpc.NodeAuditResponse.reports:type_name -> frdrpc.ReportEntry + 12, // 19: frdrpc.RevenueReport.PairReportsEntry.value:type_name -> frdrpc.PairReport + 5, // 20: frdrpc.FaradayServer.OutlierRecommendations:input_type -> frdrpc.OutlierRecommendationsRequest + 6, // 21: frdrpc.FaradayServer.ThresholdRecommendations:input_type -> frdrpc.ThresholdRecommendationsRequest + 9, // 22: frdrpc.FaradayServer.RevenueReport:input_type -> frdrpc.RevenueReportRequest + 13, // 23: frdrpc.FaradayServer.ChannelInsights:input_type -> frdrpc.ChannelInsightsRequest + 16, // 24: frdrpc.FaradayServer.ExchangeRate:input_type -> frdrpc.ExchangeRateRequest + 20, // 25: frdrpc.FaradayServer.NodeAudit:input_type -> frdrpc.NodeAuditRequest + 24, // 26: frdrpc.FaradayServer.CloseReport:input_type -> frdrpc.CloseReportRequest + 7, // 27: frdrpc.FaradayServer.OutlierRecommendations:output_type -> frdrpc.CloseRecommendationsResponse + 7, // 28: frdrpc.FaradayServer.ThresholdRecommendations:output_type -> frdrpc.CloseRecommendationsResponse + 10, // 29: frdrpc.FaradayServer.RevenueReport:output_type -> frdrpc.RevenueReportResponse + 14, // 30: frdrpc.FaradayServer.ChannelInsights:output_type -> frdrpc.ChannelInsightsResponse + 17, // 31: frdrpc.FaradayServer.ExchangeRate:output_type -> frdrpc.ExchangeRateResponse + 23, // 32: frdrpc.FaradayServer.NodeAudit:output_type -> frdrpc.NodeAuditResponse + 25, // 33: frdrpc.FaradayServer.CloseReport:output_type -> frdrpc.CloseReportResponse + 27, // [27:34] is the sub-list for method output_type + 20, // [20:27] is the sub-list for method input_type + 20, // [20:20] is the sub-list for extension type_name + 20, // [20:20] is the sub-list for extension extendee + 0, // [0:20] is the sub-list for field type_name } func init() { file_faraday_proto_init() } @@ -2967,7 +2307,7 @@ func file_faraday_proto_init() { return } if !protoimpl.UnsafeEnabled { - file_faraday_proto_msgTypes[0].Exporter = func(v any, i int) any { + file_faraday_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CloseRecommendationRequest); i { case 0: return &v.state @@ -2979,7 +2319,7 @@ func file_faraday_proto_init() { return nil } } - file_faraday_proto_msgTypes[1].Exporter = func(v any, i int) any { + file_faraday_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*OutlierRecommendationsRequest); i { case 0: return &v.state @@ -2991,7 +2331,7 @@ func file_faraday_proto_init() { return nil } } - file_faraday_proto_msgTypes[2].Exporter = func(v any, i int) any { + file_faraday_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ThresholdRecommendationsRequest); i { case 0: return &v.state @@ -3003,7 +2343,7 @@ func file_faraday_proto_init() { return nil } } - file_faraday_proto_msgTypes[3].Exporter = func(v any, i int) any { + file_faraday_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CloseRecommendationsResponse); i { case 0: return &v.state @@ -3015,7 +2355,7 @@ func file_faraday_proto_init() { return nil } } - file_faraday_proto_msgTypes[4].Exporter = func(v any, i int) any { + file_faraday_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Recommendation); i { case 0: return &v.state @@ -3027,7 +2367,7 @@ func file_faraday_proto_init() { return nil } } - file_faraday_proto_msgTypes[5].Exporter = func(v any, i int) any { + file_faraday_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RevenueReportRequest); i { case 0: return &v.state @@ -3039,7 +2379,7 @@ func file_faraday_proto_init() { return nil } } - file_faraday_proto_msgTypes[6].Exporter = func(v any, i int) any { + file_faraday_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RevenueReportResponse); i { case 0: return &v.state @@ -3051,7 +2391,7 @@ func file_faraday_proto_init() { return nil } } - file_faraday_proto_msgTypes[7].Exporter = func(v any, i int) any { + file_faraday_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RevenueReport); i { case 0: return &v.state @@ -3063,7 +2403,7 @@ func file_faraday_proto_init() { return nil } } - file_faraday_proto_msgTypes[8].Exporter = func(v any, i int) any { + file_faraday_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PairReport); i { case 0: return &v.state @@ -3075,7 +2415,7 @@ func file_faraday_proto_init() { return nil } } - file_faraday_proto_msgTypes[9].Exporter = func(v any, i int) any { + file_faraday_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ChannelInsightsRequest); i { case 0: return &v.state @@ -3087,7 +2427,7 @@ func file_faraday_proto_init() { return nil } } - file_faraday_proto_msgTypes[10].Exporter = func(v any, i int) any { + file_faraday_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ChannelInsightsResponse); i { case 0: return &v.state @@ -3099,7 +2439,7 @@ func file_faraday_proto_init() { return nil } } - file_faraday_proto_msgTypes[11].Exporter = func(v any, i int) any { + file_faraday_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ChannelInsight); i { case 0: return &v.state @@ -3111,7 +2451,7 @@ func file_faraday_proto_init() { return nil } } - file_faraday_proto_msgTypes[12].Exporter = func(v any, i int) any { + file_faraday_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ExchangeRateRequest); i { case 0: return &v.state @@ -3123,7 +2463,7 @@ func file_faraday_proto_init() { return nil } } - file_faraday_proto_msgTypes[13].Exporter = func(v any, i int) any { + file_faraday_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ExchangeRateResponse); i { case 0: return &v.state @@ -3135,7 +2475,7 @@ func file_faraday_proto_init() { return nil } } - file_faraday_proto_msgTypes[14].Exporter = func(v any, i int) any { + file_faraday_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BitcoinPrice); i { case 0: return &v.state @@ -3147,7 +2487,7 @@ func file_faraday_proto_init() { return nil } } - file_faraday_proto_msgTypes[15].Exporter = func(v any, i int) any { + file_faraday_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ExchangeRate); i { case 0: return &v.state @@ -3159,7 +2499,7 @@ func file_faraday_proto_init() { return nil } } - file_faraday_proto_msgTypes[16].Exporter = func(v any, i int) any { + file_faraday_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*NodeAuditRequest); i { case 0: return &v.state @@ -3171,7 +2511,7 @@ func file_faraday_proto_init() { return nil } } - file_faraday_proto_msgTypes[17].Exporter = func(v any, i int) any { + file_faraday_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CustomCategory); i { case 0: return &v.state @@ -3183,7 +2523,7 @@ func file_faraday_proto_init() { return nil } } - file_faraday_proto_msgTypes[18].Exporter = func(v any, i int) any { + file_faraday_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ReportEntry); i { case 0: return &v.state @@ -3195,7 +2535,7 @@ func file_faraday_proto_init() { return nil } } - file_faraday_proto_msgTypes[19].Exporter = func(v any, i int) any { + file_faraday_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*NodeAuditResponse); i { case 0: return &v.state @@ -3207,7 +2547,7 @@ func file_faraday_proto_init() { return nil } } - file_faraday_proto_msgTypes[20].Exporter = func(v any, i int) any { + file_faraday_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CloseReportRequest); i { case 0: return &v.state @@ -3219,7 +2559,7 @@ func file_faraday_proto_init() { return nil } } - file_faraday_proto_msgTypes[21].Exporter = func(v any, i int) any { + file_faraday_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CloseReportResponse); i { case 0: return &v.state @@ -3231,86 +2571,14 @@ func file_faraday_proto_init() { return nil } } - file_faraday_proto_msgTypes[22].Exporter = func(v any, i int) any { - switch v := v.(*ChannelEventsRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_faraday_proto_msgTypes[23].Exporter = func(v any, i int) any { - switch v := v.(*ChannelEventsResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_faraday_proto_msgTypes[24].Exporter = func(v any, i int) any { - switch v := v.(*ChannelEvent); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_faraday_proto_msgTypes[25].Exporter = func(v any, i int) any { - switch v := v.(*ForwardingAbilityRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_faraday_proto_msgTypes[26].Exporter = func(v any, i int) any { - switch v := v.(*ForwardingAbilityResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_faraday_proto_msgTypes[27].Exporter = func(v any, i int) any { - switch v := v.(*ForwardingAbilityEntry); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_faraday_proto_rawDesc, - NumEnums: 5, - NumMessages: 29, + NumEnums: 4, + NumMessages: 23, NumExtensions: 0, NumServices: 1, }, diff --git a/frdrpc/faraday.pb.gw.go b/frdrpc/faraday.pb.gw.go index 539fe5b..082c1be 100644 --- a/frdrpc/faraday.pb.gw.go +++ b/frdrpc/faraday.pb.gw.go @@ -121,7 +121,11 @@ func request_FaradayServer_OutlierRecommendations_1(ctx context.Context, marshal var protoReq OutlierRecommendationsRequest var metadata runtime.ServerMetadata - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -159,7 +163,11 @@ func local_request_FaradayServer_OutlierRecommendations_1(ctx context.Context, m var protoReq OutlierRecommendationsRequest var metadata runtime.ServerMetadata - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -283,7 +291,11 @@ func request_FaradayServer_ThresholdRecommendations_1(ctx context.Context, marsh var protoReq ThresholdRecommendationsRequest var metadata runtime.ServerMetadata - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -321,7 +333,11 @@ func local_request_FaradayServer_ThresholdRecommendations_1(ctx context.Context, var protoReq ThresholdRecommendationsRequest var metadata runtime.ServerMetadata - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -395,7 +411,11 @@ func request_FaradayServer_RevenueReport_1(ctx context.Context, marshaler runtim var protoReq RevenueReportRequest var metadata runtime.ServerMetadata - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -408,7 +428,11 @@ func local_request_FaradayServer_RevenueReport_1(ctx context.Context, marshaler var protoReq RevenueReportRequest var metadata runtime.ServerMetadata - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -475,7 +499,11 @@ func request_FaradayServer_ExchangeRate_1(ctx context.Context, marshaler runtime var protoReq ExchangeRateRequest var metadata runtime.ServerMetadata - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -488,7 +516,11 @@ func local_request_FaradayServer_ExchangeRate_1(ctx context.Context, marshaler r var protoReq ExchangeRateRequest var metadata runtime.ServerMetadata - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -537,7 +569,11 @@ func request_FaradayServer_NodeAudit_1(ctx context.Context, marshaler runtime.Ma var protoReq NodeAuditRequest var metadata runtime.ServerMetadata - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -550,7 +586,11 @@ func local_request_FaradayServer_NodeAudit_1(ctx context.Context, marshaler runt var protoReq NodeAuditRequest var metadata runtime.ServerMetadata - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } @@ -595,37 +635,10 @@ func local_request_FaradayServer_CloseReport_0(ctx context.Context, marshaler ru } -func request_FaradayServer_GetChannelEvents_0(ctx context.Context, marshaler runtime.Marshaler, client FaradayServerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ChannelEventsRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.GetChannelEvents(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_FaradayServer_GetChannelEvents_0(ctx context.Context, marshaler runtime.Marshaler, server FaradayServerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq ChannelEventsRequest - var metadata runtime.ServerMetadata - - if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.GetChannelEvents(ctx, &protoReq) - return msg, metadata, err - -} - // RegisterFaradayServerHandlerServer registers the http handlers for service FaradayServer to "mux". // UnaryRPC :call FaradayServerServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterFaradayServerHandlerFromEndpoint instead. -// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. func RegisterFaradayServerHandlerServer(ctx context.Context, mux *runtime.ServeMux, server FaradayServerServer) error { mux.Handle("GET", pattern_FaradayServer_OutlierRecommendations_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { @@ -634,22 +647,20 @@ func RegisterFaradayServerHandlerServer(ctx context.Context, mux *runtime.ServeM var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/frdrpc.FaradayServer/OutlierRecommendations", runtime.WithHTTPPathPattern("/v1/faraday/outliers/{rec_request.metric}")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/frdrpc.FaradayServer/OutlierRecommendations", runtime.WithHTTPPathPattern("/v1/faraday/outliers/{rec_request.metric}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_FaradayServer_OutlierRecommendations_0(annotatedContext, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_FaradayServer_OutlierRecommendations_0(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_FaradayServer_OutlierRecommendations_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_FaradayServer_OutlierRecommendations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -659,22 +670,20 @@ func RegisterFaradayServerHandlerServer(ctx context.Context, mux *runtime.ServeM var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/frdrpc.FaradayServer/OutlierRecommendations", runtime.WithHTTPPathPattern("/v1/faraday/outliers/{rec_request.metric}")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/frdrpc.FaradayServer/OutlierRecommendations", runtime.WithHTTPPathPattern("/v1/faraday/outliers/{rec_request.metric}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_FaradayServer_OutlierRecommendations_1(annotatedContext, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_FaradayServer_OutlierRecommendations_1(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_FaradayServer_OutlierRecommendations_1(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_FaradayServer_OutlierRecommendations_1(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -684,22 +693,20 @@ func RegisterFaradayServerHandlerServer(ctx context.Context, mux *runtime.ServeM var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/frdrpc.FaradayServer/ThresholdRecommendations", runtime.WithHTTPPathPattern("/v1/faraday/threshold/{rec_request.metric}")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/frdrpc.FaradayServer/ThresholdRecommendations", runtime.WithHTTPPathPattern("/v1/faraday/threshold/{rec_request.metric}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_FaradayServer_ThresholdRecommendations_0(annotatedContext, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_FaradayServer_ThresholdRecommendations_0(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_FaradayServer_ThresholdRecommendations_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_FaradayServer_ThresholdRecommendations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -709,22 +716,20 @@ func RegisterFaradayServerHandlerServer(ctx context.Context, mux *runtime.ServeM var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/frdrpc.FaradayServer/ThresholdRecommendations", runtime.WithHTTPPathPattern("/v1/faraday/threshold/{rec_request.metric}")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/frdrpc.FaradayServer/ThresholdRecommendations", runtime.WithHTTPPathPattern("/v1/faraday/threshold/{rec_request.metric}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_FaradayServer_ThresholdRecommendations_1(annotatedContext, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_FaradayServer_ThresholdRecommendations_1(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_FaradayServer_ThresholdRecommendations_1(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_FaradayServer_ThresholdRecommendations_1(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -734,22 +739,20 @@ func RegisterFaradayServerHandlerServer(ctx context.Context, mux *runtime.ServeM var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/frdrpc.FaradayServer/RevenueReport", runtime.WithHTTPPathPattern("/v1/faraday/revenue")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/frdrpc.FaradayServer/RevenueReport", runtime.WithHTTPPathPattern("/v1/faraday/revenue")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_FaradayServer_RevenueReport_0(annotatedContext, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_FaradayServer_RevenueReport_0(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_FaradayServer_RevenueReport_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_FaradayServer_RevenueReport_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -759,22 +762,20 @@ func RegisterFaradayServerHandlerServer(ctx context.Context, mux *runtime.ServeM var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/frdrpc.FaradayServer/RevenueReport", runtime.WithHTTPPathPattern("/v1/faraday/revenue")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/frdrpc.FaradayServer/RevenueReport", runtime.WithHTTPPathPattern("/v1/faraday/revenue")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_FaradayServer_RevenueReport_1(annotatedContext, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_FaradayServer_RevenueReport_1(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_FaradayServer_RevenueReport_1(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_FaradayServer_RevenueReport_1(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -784,22 +785,20 @@ func RegisterFaradayServerHandlerServer(ctx context.Context, mux *runtime.ServeM var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/frdrpc.FaradayServer/ChannelInsights", runtime.WithHTTPPathPattern("/v1/faraday/insights")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/frdrpc.FaradayServer/ChannelInsights", runtime.WithHTTPPathPattern("/v1/faraday/insights")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_FaradayServer_ChannelInsights_0(annotatedContext, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_FaradayServer_ChannelInsights_0(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_FaradayServer_ChannelInsights_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_FaradayServer_ChannelInsights_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -809,22 +808,20 @@ func RegisterFaradayServerHandlerServer(ctx context.Context, mux *runtime.ServeM var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/frdrpc.FaradayServer/ExchangeRate", runtime.WithHTTPPathPattern("/v1/faraday/exchangerate")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/frdrpc.FaradayServer/ExchangeRate", runtime.WithHTTPPathPattern("/v1/faraday/exchangerate")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_FaradayServer_ExchangeRate_0(annotatedContext, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_FaradayServer_ExchangeRate_0(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_FaradayServer_ExchangeRate_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_FaradayServer_ExchangeRate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -834,22 +831,20 @@ func RegisterFaradayServerHandlerServer(ctx context.Context, mux *runtime.ServeM var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/frdrpc.FaradayServer/ExchangeRate", runtime.WithHTTPPathPattern("/v1/faraday/exchangerate")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/frdrpc.FaradayServer/ExchangeRate", runtime.WithHTTPPathPattern("/v1/faraday/exchangerate")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_FaradayServer_ExchangeRate_1(annotatedContext, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_FaradayServer_ExchangeRate_1(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_FaradayServer_ExchangeRate_1(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_FaradayServer_ExchangeRate_1(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -859,22 +854,20 @@ func RegisterFaradayServerHandlerServer(ctx context.Context, mux *runtime.ServeM var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/frdrpc.FaradayServer/NodeAudit", runtime.WithHTTPPathPattern("/v1/faraday/nodeaudit")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/frdrpc.FaradayServer/NodeAudit", runtime.WithHTTPPathPattern("/v1/faraday/nodeaudit")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_FaradayServer_NodeAudit_0(annotatedContext, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_FaradayServer_NodeAudit_0(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_FaradayServer_NodeAudit_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_FaradayServer_NodeAudit_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -884,22 +877,20 @@ func RegisterFaradayServerHandlerServer(ctx context.Context, mux *runtime.ServeM var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/frdrpc.FaradayServer/NodeAudit", runtime.WithHTTPPathPattern("/v1/faraday/nodeaudit")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/frdrpc.FaradayServer/NodeAudit", runtime.WithHTTPPathPattern("/v1/faraday/nodeaudit")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_FaradayServer_NodeAudit_1(annotatedContext, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_FaradayServer_NodeAudit_1(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_FaradayServer_NodeAudit_1(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_FaradayServer_NodeAudit_1(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -909,47 +900,20 @@ func RegisterFaradayServerHandlerServer(ctx context.Context, mux *runtime.ServeM var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/frdrpc.FaradayServer/CloseReport", runtime.WithHTTPPathPattern("/v1/faraday/closereport")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/frdrpc.FaradayServer/CloseReport", runtime.WithHTTPPathPattern("/v1/faraday/closereport")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_FaradayServer_CloseReport_0(annotatedContext, inboundMarshaler, server, req, pathParams) + resp, md, err := local_request_FaradayServer_CloseReport_0(rctx, inboundMarshaler, server, req, pathParams) md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_FaradayServer_CloseReport_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_FaradayServer_GetChannelEvents_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/frdrpc.FaradayServer/GetChannelEvents", runtime.WithHTTPPathPattern("/v1/faraday/getchannelevents")) + ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_FaradayServer_GetChannelEvents_0(annotatedContext, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - forward_FaradayServer_GetChannelEvents_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_FaradayServer_CloseReport_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -959,21 +923,21 @@ func RegisterFaradayServerHandlerServer(ctx context.Context, mux *runtime.ServeM // RegisterFaradayServerHandlerFromEndpoint is same as RegisterFaradayServerHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterFaradayServerHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { - conn, err := grpc.NewClient(endpoint, opts...) + conn, err := grpc.Dial(endpoint, opts...) if err != nil { return err } defer func() { if err != nil { if cerr := conn.Close(); cerr != nil { - grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) } return } go func() { <-ctx.Done() if cerr := conn.Close(); cerr != nil { - grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) } }() }() @@ -991,28 +955,26 @@ func RegisterFaradayServerHandler(ctx context.Context, mux *runtime.ServeMux, co // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "FaradayServerClient". // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "FaradayServerClient" // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in -// "FaradayServerClient" to call the correct interceptors. This client ignores the HTTP middlewares. +// "FaradayServerClient" to call the correct interceptors. func RegisterFaradayServerHandlerClient(ctx context.Context, mux *runtime.ServeMux, client FaradayServerClient) error { mux.Handle("GET", pattern_FaradayServer_OutlierRecommendations_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/frdrpc.FaradayServer/OutlierRecommendations", runtime.WithHTTPPathPattern("/v1/faraday/outliers/{rec_request.metric}")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/frdrpc.FaradayServer/OutlierRecommendations", runtime.WithHTTPPathPattern("/v1/faraday/outliers/{rec_request.metric}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_FaradayServer_OutlierRecommendations_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + resp, md, err := request_FaradayServer_OutlierRecommendations_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_FaradayServer_OutlierRecommendations_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_FaradayServer_OutlierRecommendations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -1020,21 +982,19 @@ func RegisterFaradayServerHandlerClient(ctx context.Context, mux *runtime.ServeM ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/frdrpc.FaradayServer/OutlierRecommendations", runtime.WithHTTPPathPattern("/v1/faraday/outliers/{rec_request.metric}")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/frdrpc.FaradayServer/OutlierRecommendations", runtime.WithHTTPPathPattern("/v1/faraday/outliers/{rec_request.metric}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_FaradayServer_OutlierRecommendations_1(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + resp, md, err := request_FaradayServer_OutlierRecommendations_1(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_FaradayServer_OutlierRecommendations_1(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_FaradayServer_OutlierRecommendations_1(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -1042,21 +1002,19 @@ func RegisterFaradayServerHandlerClient(ctx context.Context, mux *runtime.ServeM ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/frdrpc.FaradayServer/ThresholdRecommendations", runtime.WithHTTPPathPattern("/v1/faraday/threshold/{rec_request.metric}")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/frdrpc.FaradayServer/ThresholdRecommendations", runtime.WithHTTPPathPattern("/v1/faraday/threshold/{rec_request.metric}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_FaradayServer_ThresholdRecommendations_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + resp, md, err := request_FaradayServer_ThresholdRecommendations_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_FaradayServer_ThresholdRecommendations_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_FaradayServer_ThresholdRecommendations_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -1064,21 +1022,19 @@ func RegisterFaradayServerHandlerClient(ctx context.Context, mux *runtime.ServeM ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/frdrpc.FaradayServer/ThresholdRecommendations", runtime.WithHTTPPathPattern("/v1/faraday/threshold/{rec_request.metric}")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/frdrpc.FaradayServer/ThresholdRecommendations", runtime.WithHTTPPathPattern("/v1/faraday/threshold/{rec_request.metric}")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_FaradayServer_ThresholdRecommendations_1(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + resp, md, err := request_FaradayServer_ThresholdRecommendations_1(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_FaradayServer_ThresholdRecommendations_1(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_FaradayServer_ThresholdRecommendations_1(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -1086,21 +1042,19 @@ func RegisterFaradayServerHandlerClient(ctx context.Context, mux *runtime.ServeM ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/frdrpc.FaradayServer/RevenueReport", runtime.WithHTTPPathPattern("/v1/faraday/revenue")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/frdrpc.FaradayServer/RevenueReport", runtime.WithHTTPPathPattern("/v1/faraday/revenue")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_FaradayServer_RevenueReport_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + resp, md, err := request_FaradayServer_RevenueReport_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_FaradayServer_RevenueReport_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_FaradayServer_RevenueReport_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -1108,21 +1062,19 @@ func RegisterFaradayServerHandlerClient(ctx context.Context, mux *runtime.ServeM ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/frdrpc.FaradayServer/RevenueReport", runtime.WithHTTPPathPattern("/v1/faraday/revenue")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/frdrpc.FaradayServer/RevenueReport", runtime.WithHTTPPathPattern("/v1/faraday/revenue")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_FaradayServer_RevenueReport_1(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + resp, md, err := request_FaradayServer_RevenueReport_1(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_FaradayServer_RevenueReport_1(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_FaradayServer_RevenueReport_1(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -1130,21 +1082,19 @@ func RegisterFaradayServerHandlerClient(ctx context.Context, mux *runtime.ServeM ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/frdrpc.FaradayServer/ChannelInsights", runtime.WithHTTPPathPattern("/v1/faraday/insights")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/frdrpc.FaradayServer/ChannelInsights", runtime.WithHTTPPathPattern("/v1/faraday/insights")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_FaradayServer_ChannelInsights_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + resp, md, err := request_FaradayServer_ChannelInsights_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_FaradayServer_ChannelInsights_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_FaradayServer_ChannelInsights_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -1152,21 +1102,19 @@ func RegisterFaradayServerHandlerClient(ctx context.Context, mux *runtime.ServeM ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/frdrpc.FaradayServer/ExchangeRate", runtime.WithHTTPPathPattern("/v1/faraday/exchangerate")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/frdrpc.FaradayServer/ExchangeRate", runtime.WithHTTPPathPattern("/v1/faraday/exchangerate")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_FaradayServer_ExchangeRate_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + resp, md, err := request_FaradayServer_ExchangeRate_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_FaradayServer_ExchangeRate_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_FaradayServer_ExchangeRate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -1174,21 +1122,19 @@ func RegisterFaradayServerHandlerClient(ctx context.Context, mux *runtime.ServeM ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/frdrpc.FaradayServer/ExchangeRate", runtime.WithHTTPPathPattern("/v1/faraday/exchangerate")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/frdrpc.FaradayServer/ExchangeRate", runtime.WithHTTPPathPattern("/v1/faraday/exchangerate")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_FaradayServer_ExchangeRate_1(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + resp, md, err := request_FaradayServer_ExchangeRate_1(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_FaradayServer_ExchangeRate_1(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_FaradayServer_ExchangeRate_1(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -1196,21 +1142,19 @@ func RegisterFaradayServerHandlerClient(ctx context.Context, mux *runtime.ServeM ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/frdrpc.FaradayServer/NodeAudit", runtime.WithHTTPPathPattern("/v1/faraday/nodeaudit")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/frdrpc.FaradayServer/NodeAudit", runtime.WithHTTPPathPattern("/v1/faraday/nodeaudit")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_FaradayServer_NodeAudit_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + resp, md, err := request_FaradayServer_NodeAudit_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_FaradayServer_NodeAudit_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_FaradayServer_NodeAudit_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -1218,21 +1162,19 @@ func RegisterFaradayServerHandlerClient(ctx context.Context, mux *runtime.ServeM ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/frdrpc.FaradayServer/NodeAudit", runtime.WithHTTPPathPattern("/v1/faraday/nodeaudit")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/frdrpc.FaradayServer/NodeAudit", runtime.WithHTTPPathPattern("/v1/faraday/nodeaudit")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_FaradayServer_NodeAudit_1(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + resp, md, err := request_FaradayServer_NodeAudit_1(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - forward_FaradayServer_NodeAudit_1(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_FaradayServer_NodeAudit_1(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -1240,43 +1182,19 @@ func RegisterFaradayServerHandlerClient(ctx context.Context, mux *runtime.ServeM ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/frdrpc.FaradayServer/CloseReport", runtime.WithHTTPPathPattern("/v1/faraday/closereport")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/frdrpc.FaradayServer/CloseReport", runtime.WithHTTPPathPattern("/v1/faraday/closereport")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_FaradayServer_CloseReport_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_FaradayServer_CloseReport_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_FaradayServer_GetChannelEvents_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/frdrpc.FaradayServer/GetChannelEvents", runtime.WithHTTPPathPattern("/v1/faraday/getchannelevents")) + resp, md, err := request_FaradayServer_CloseReport_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_FaradayServer_GetChannelEvents_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - forward_FaradayServer_GetChannelEvents_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + forward_FaradayServer_CloseReport_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) @@ -1307,8 +1225,6 @@ var ( pattern_FaradayServer_NodeAudit_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "faraday", "nodeaudit"}, "")) pattern_FaradayServer_CloseReport_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "faraday", "closereport"}, "")) - - pattern_FaradayServer_GetChannelEvents_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "faraday", "getchannelevents"}, "")) ) var ( @@ -1335,6 +1251,4 @@ var ( forward_FaradayServer_NodeAudit_1 = runtime.ForwardResponseMessage forward_FaradayServer_CloseReport_0 = runtime.ForwardResponseMessage - - forward_FaradayServer_GetChannelEvents_0 = runtime.ForwardResponseMessage ) diff --git a/frdrpc/faraday.proto b/frdrpc/faraday.proto index cd551d0..4cf9ef3 100644 --- a/frdrpc/faraday.proto +++ b/frdrpc/faraday.proto @@ -65,17 +65,6 @@ service FaradayServer { http://localhost:8466/v1/faraday/closereport */ rpc CloseReport (CloseReportRequest) returns (CloseReportResponse); - - /** - Get a list of channel events that occurred for a given channel. - */ - rpc GetChannelEvents (ChannelEventsRequest) returns (ChannelEventsResponse); - - /** - Get forwarding ability analysis of peer pairs. - */ - rpc ForwardingAbility (ForwardingAbilityRequest) - returns (ForwardingAbilityResponse); } message CloseRecommendationRequest { @@ -354,11 +343,6 @@ enum FiatBackend { // This API is reached through the following URL: // https://api.coingecko.com/api/v3/coins/bitcoin/market_chart COINGECKO = 4; - - // Use the Bitfinex API for fiat price information. - // This API is reached through the following URL: - // https://api-pub.bitfinex.com/v2/candles/trade:1h:tBTCUSD/hist - BITFINEX = 5; } message ExchangeRateRequest { @@ -607,145 +591,3 @@ message CloseReportResponse { */ string close_fee = 6; } - -message ChannelEventsRequest { - /* - The channel point of the channel to get events for, formatted txid:outpoint. - */ - string chan_point = 1; - - /* - Lower time bound, inclusive, as Unix seconds. Independent filter — does - not need to advance between paginated calls. Zero means no lower bound. - */ - int64 start_time = 2; - - /* - Upper time bound, exclusive, as Unix seconds. Must be greater than or - equal to start_time. Zero means "use the server's current time". - */ - int64 end_time = 3; - - /* - The maximum number of events to return. If zero, the server default is - used. The server enforces a hard cap; values above the cap are clamped. - */ - uint32 max_events = 4; - - /* - Pagination cursor: id of the last event from the previous response. - Pass zero on the first call; for subsequent calls pass the response's - last_id to resume past already-returned events. - */ - int64 last_id = 5; -} - -enum ChannelEventType { - // An unknown event type. - CHAN_EVENT_UNKNOWN = 0; - // An online event. - CHAN_EVENT_ONLINE = 1; - // An offline event. - CHAN_EVENT_OFFLINE = 2; - // A channel balance update event. - CHAN_EVENT_UPDATE = 3; -} - -message ChannelEventsResponse { - // The list of channel events. - repeated ChannelEvent events = 1; - - // Id of the last event returned, suitable as the next request's last_id. - // Zero when events is empty. - int64 last_id = 2; - - // True when the page filled to the requested limit and more events may be - // available; callers should keep paginating until this is false. - bool has_more = 3; -} - -message ChannelEvent { - // The timestamp of the event, as Unix seconds. - int64 timestamp = 1; - - // The type of the event. - ChannelEventType event_type = 2; - - // The channel's local balance at the time of the event in sat. - uint64 local_balance = 3; - - // The channel's remote balance at the time of the event in sat. - uint64 remote_balance = 4; - - // Server-assigned monotonic identity. Echo this back as the next - // request's last_id when paginating. - int64 id = 5; -} - -message ForwardingAbilityRequest { - // The start time of the query range as unix seconds. A value of 0 means - // the earliest available data. - uint64 start_time = 1; - - // The end time of the query range as unix seconds. A value of 0 means the - // server's current time. - uint64 end_time = 2; - - // The minimum directional liquidity in satoshis for a peer pair to count as - // economically forwardable. A value of 0 selects the server default. Hold - // this constant across calls for comparable series. - uint64 liquidity_floor_sat = 3; - - // The uptime fraction in [0, 1] at or above which a peer pair that did not - // forward is reported compactly as a single bit in up_but_idle_bitmask - // rather than as a full entry. A value of 0 selects the server default. - // Pairs below this threshold that also did not forward are omitted - // entirely. If no pair meets the threshold the server returns a - // FailedPrecondition error, since that indicates the node itself was down - // for the window and the data carries no signal. - double uptime_threshold = 4; -} - -message ForwardingAbilityResponse { - // Sorted list of unique compressed 33-byte public keys of the peers. - repeated bytes peers = 1; - - // Sparse list of forwarding ability entries. An entry is present only for a - // pair that forwarded volume, carrying its exact effective_uptime_s and - // forwarded_sat. Pairs that did not forward are never listed here; they are - // either flagged in quiet_uptime_bitmask or absent. Entries take precedence - // over the bitmask for the same pair. - repeated ForwardingAbilityEntry entries = 2; - - // The start of the window the metrics cover, as unix seconds. - int64 start_time = 3; - - // The end of the window the metrics cover, as unix seconds. - int64 end_time = 4; - - // A packed bitmask over the n*n ordered peer pairs, where n is the length - // of peers. The bit at index in*n+out is set when that pair held at least - // the uptime_threshold fraction of effective uptime over the window but did - // not forward: the dense "up but idle" population. A pair with a forwarded - // entry is never flagged here. A pair that is neither listed in entries nor - // flagged here had sub-threshold uptime and no forwards: treat it as zero. - bytes up_but_idle_bitmask = 5; - - // The uptime fraction in [0, 1] used to populate up_but_idle_bitmask, - // echoed back so consumers know the threshold the server applied. - double uptime_threshold = 6; -} - -message ForwardingAbilityEntry { - // The indices of the incoming and outgoing peers packed into a single - // 32-bit integer: packed_idx = (in << 16) | out. This caps the peer set at - // 65535 peers per direction. - uint32 packed_idx = 1; - - // Seconds the peer pair held at least the requested liquidity floor of - // directional forwardable liquidity over the window. - int64 effective_uptime_s = 2; - - // Total successfully forwarded amount over the window, in satoshis. - int64 forwarded_sat = 3; -} diff --git a/frdrpc/faraday.swagger.json b/frdrpc/faraday.swagger.json index 2bcc0db..1124ee9 100644 --- a/frdrpc/faraday.swagger.json +++ b/frdrpc/faraday.swagger.json @@ -102,7 +102,7 @@ }, { "name": "fiat_backend", - "description": "The api to be used for fiat related queries.\n\n - COINCAP: Use the CoinCap API for fiat price information.\nThis API is reached through the following URL:\nhttps://api.coincap.io/v2/assets/bitcoin/history\n - COINDESK: Use the CoinDesk API for fiat price information.\nThis API is reached through the following URL:\nhttps://api.coindesk.com/v1/bpi/historical/close.json\n - CUSTOM: Use custom price data provided in a CSV file for fiat price information.\n - COINGECKO: Use the CoinGecko API for fiat price information.\nThis API is reached through the following URL:\nhttps://api.coingecko.com/api/v3/coins/bitcoin/market_chart\n - BITFINEX: Use the Bitfinex API for fiat price information.\nThis API is reached through the following URL:\nhttps://api-pub.bitfinex.com/v2/candles/trade:1h:tBTCUSD/hist", + "description": "The api to be used for fiat related queries.\n\n - COINCAP: Use the CoinCap API for fiat price information.\nThis API is reached through the following URL:\nhttps://api.coincap.io/v2/assets/bitcoin/history\n - COINDESK: Use the CoinDesk API for fiat price information.\nThis API is reached through the following URL:\nhttps://api.coindesk.com/v1/bpi/historical/close.json\n - CUSTOM: Use custom price data provided in a CSV file for fiat price information.\n - COINGECKO: Use the CoinGecko API for fiat price information.\nThis API is reached through the following URL:\nhttps://api.coingecko.com/api/v3/coins/bitcoin/market_chart", "in": "query", "required": false, "type": "string", @@ -111,8 +111,7 @@ "COINCAP", "COINDESK", "CUSTOM", - "COINGECKO", - "BITFINEX" + "COINGECKO" ], "default": "UNKNOWN_FIATBACKEND" } @@ -154,39 +153,6 @@ ] } }, - "/v1/faraday/getchannelevents": { - "post": { - "summary": "*\nGet a list of channel events that occurred for a given channel.", - "operationId": "FaradayServer_GetChannelEvents", - "responses": { - "200": { - "description": "A successful response.", - "schema": { - "$ref": "#/definitions/frdrpcChannelEventsResponse" - } - }, - "default": { - "description": "An unexpected error response.", - "schema": { - "$ref": "#/definitions/rpcStatus" - } - } - }, - "parameters": [ - { - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/frdrpcChannelEventsRequest" - } - } - ], - "tags": [ - "FaradayServer" - ] - } - }, "/v1/faraday/insights": { "get": { "summary": "* frcli: `insights`\nList currently open channel with routing and uptime information.", @@ -275,7 +241,7 @@ }, { "name": "fiat_backend", - "description": "The api to be used for fiat related queries.\n\n - COINCAP: Use the CoinCap API for fiat price information.\nThis API is reached through the following URL:\nhttps://api.coincap.io/v2/assets/bitcoin/history\n - COINDESK: Use the CoinDesk API for fiat price information.\nThis API is reached through the following URL:\nhttps://api.coindesk.com/v1/bpi/historical/close.json\n - CUSTOM: Use custom price data provided in a CSV file for fiat price information.\n - COINGECKO: Use the CoinGecko API for fiat price information.\nThis API is reached through the following URL:\nhttps://api.coingecko.com/api/v3/coins/bitcoin/market_chart\n - BITFINEX: Use the Bitfinex API for fiat price information.\nThis API is reached through the following URL:\nhttps://api-pub.bitfinex.com/v2/candles/trade:1h:tBTCUSD/hist", + "description": "The api to be used for fiat related queries.\n\n - COINCAP: Use the CoinCap API for fiat price information.\nThis API is reached through the following URL:\nhttps://api.coincap.io/v2/assets/bitcoin/history\n - COINDESK: Use the CoinDesk API for fiat price information.\nThis API is reached through the following URL:\nhttps://api.coindesk.com/v1/bpi/historical/close.json\n - CUSTOM: Use custom price data provided in a CSV file for fiat price information.\n - COINGECKO: Use the CoinGecko API for fiat price information.\nThis API is reached through the following URL:\nhttps://api.coingecko.com/api/v3/coins/bitcoin/market_chart", "in": "query", "required": false, "type": "string", @@ -284,8 +250,7 @@ "COINCAP", "COINDESK", "CUSTOM", - "COINGECKO", - "BITFINEX" + "COINGECKO" ], "default": "UNKNOWN_FIATBACKEND" } @@ -422,7 +387,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/FaradayServerOutlierRecommendationsBody" + "$ref": "#/definitions/frdrpcOutlierRecommendationsRequest" } } ], @@ -611,7 +576,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/FaradayServerThresholdRecommendationsBody" + "$ref": "#/definitions/frdrpcThresholdRecommendationsRequest" } } ], @@ -634,50 +599,6 @@ ], "default": "UNKNOWN" }, - "FaradayServerOutlierRecommendationsBody": { - "type": "object", - "properties": { - "rec_request": { - "type": "object", - "properties": { - "minimum_monitored": { - "type": "string", - "format": "int64", - "description": "The minimum amount of time in seconds that a channel should have been\nmonitored by lnd to be eligible for close. This value is in place to\nprotect against closing of newer channels." - } - }, - "description": "The parameters that are common to all close recommendations.", - "title": "The parameters that are common to all close recommendations." - }, - "outlier_multiplier": { - "type": "number", - "format": "float", - "description": "The number of inter-quartile ranges a value needs to be beneath the lower\nquartile/ above the upper quartile to be considered a lower/upper outlier.\nLower values will be more aggressive in recommending channel closes, and\nupper values will be more conservative. Recommended values are 1.5 for\naggressive recommendations and 3 for conservative recommendations." - } - } - }, - "FaradayServerThresholdRecommendationsBody": { - "type": "object", - "properties": { - "rec_request": { - "type": "object", - "properties": { - "minimum_monitored": { - "type": "string", - "format": "int64", - "description": "The minimum amount of time in seconds that a channel should have been\nmonitored by lnd to be eligible for close. This value is in place to\nprotect against closing of newer channels." - } - }, - "description": "The parameters that are common to all close recommendations.", - "title": "The parameters that are common to all close recommendations." - }, - "threshold_value": { - "type": "number", - "format": "float", - "description": "The threshold that recommendations will be calculated based on.\nFor uptime: ratio of uptime to observed lifetime beneath which channels\nwill be recommended for closure.\n\nFor revenue: revenue per block that capital has been committed to the\nchannel beneath which channels will be recommended for closure. This\nvalue is provided per block so that channels that have been open for\ndifferent periods of time can be compared.\n\nFor incoming volume: The incoming volume per block that capital has\nbeen committed to the channel beneath which channels will be recommended\nfor closure. This value is provided per block so that channels that have\nbeen open for different periods of time can be compared.\n\nFor outgoing volume: The outgoing volume per block that capital has been\ncommitted to the channel beneath which channels will be recommended for\nclosure. This value is provided per block so that channels that have been\nopen for different periods of time can be compared.\n\nFor total volume: The total volume per block that capital has been\ncommitted to the channel beneath which channels will be recommended for\nclosure. This value is provided per block so that channels that have been\nopen for different periods of time can be compared." - } - } - }, "frdrpcBitcoinPrice": { "type": "object", "properties": { @@ -696,97 +617,6 @@ } } }, - "frdrpcChannelEvent": { - "type": "object", - "properties": { - "timestamp": { - "type": "string", - "format": "int64", - "description": "The timestamp of the event, as Unix seconds." - }, - "event_type": { - "$ref": "#/definitions/frdrpcChannelEventType", - "description": "The type of the event." - }, - "local_balance": { - "type": "string", - "format": "uint64", - "description": "The channel's local balance at the time of the event in sat." - }, - "remote_balance": { - "type": "string", - "format": "uint64", - "description": "The channel's remote balance at the time of the event in sat." - }, - "id": { - "type": "string", - "format": "int64", - "description": "Server-assigned monotonic identity. Echo this back as the next\nrequest's last_id when paginating." - } - } - }, - "frdrpcChannelEventType": { - "type": "string", - "enum": [ - "CHAN_EVENT_UNKNOWN", - "CHAN_EVENT_ONLINE", - "CHAN_EVENT_OFFLINE", - "CHAN_EVENT_UPDATE" - ], - "default": "CHAN_EVENT_UNKNOWN", - "description": " - CHAN_EVENT_UNKNOWN: An unknown event type.\n - CHAN_EVENT_ONLINE: An online event.\n - CHAN_EVENT_OFFLINE: An offline event.\n - CHAN_EVENT_UPDATE: A channel balance update event." - }, - "frdrpcChannelEventsRequest": { - "type": "object", - "properties": { - "chan_point": { - "type": "string", - "description": "The channel point of the channel to get events for, formatted txid:outpoint." - }, - "start_time": { - "type": "string", - "format": "int64", - "description": "Lower time bound, inclusive, as Unix seconds. Independent filter — does\nnot need to advance between paginated calls. Zero means no lower bound." - }, - "end_time": { - "type": "string", - "format": "int64", - "description": "Upper time bound, exclusive, as Unix seconds. Must be greater than or\nequal to start_time. Zero means \"use the server's current time\"." - }, - "max_events": { - "type": "integer", - "format": "int64", - "description": "The maximum number of events to return. If zero, the server default is\nused. The server enforces a hard cap; values above the cap are clamped." - }, - "last_id": { - "type": "string", - "format": "int64", - "description": "Pagination cursor: id of the last event from the previous response.\nPass zero on the first call; for subsequent calls pass the response's\nlast_id to resume past already-returned events." - } - } - }, - "frdrpcChannelEventsResponse": { - "type": "object", - "properties": { - "events": { - "type": "array", - "items": { - "type": "object", - "$ref": "#/definitions/frdrpcChannelEvent" - }, - "description": "The list of channel events." - }, - "last_id": { - "type": "string", - "format": "int64", - "description": "Id of the last event returned, suitable as the next request's last_id.\nZero when events is empty." - }, - "has_more": { - "type": "boolean", - "description": "True when the page filled to the requested limit and more events may be\navailable; callers should keep paginating until this is false." - } - } - }, "frdrpcChannelInsight": { "type": "object", "properties": { @@ -836,7 +666,6 @@ "channel_insights": { "type": "array", "items": { - "type": "object", "$ref": "#/definitions/frdrpcChannelInsight" }, "description": "Insights for the set of currently open channels." @@ -873,7 +702,6 @@ "recommendations": { "type": "array", "items": { - "type": "object", "$ref": "#/definitions/frdrpcRecommendation" }, "description": "A set of channel close recommendations. The absence of a channel in this\nset implies that it was not considered for close because it did not meet\nthe criteria for close recommendations (it is private, or has not been\nmonitored for long enough)." @@ -992,7 +820,6 @@ "custom_prices": { "type": "array", "items": { - "type": "object", "$ref": "#/definitions/frdrpcBitcoinPrice" }, "description": "Custom price points to use if the CUSTOM FiatBackend option is set." @@ -1005,7 +832,6 @@ "rates": { "type": "array", "items": { - "type": "object", "$ref": "#/definitions/frdrpcExchangeRate" }, "title": "Rates contains a set of exchange rates for the set of timestamps" @@ -1019,72 +845,10 @@ "COINCAP", "COINDESK", "CUSTOM", - "COINGECKO", - "BITFINEX" + "COINGECKO" ], "default": "UNKNOWN_FIATBACKEND", - "description": "FiatBackend is the API endpoint to be used for any fiat related queries.\n\n - COINCAP: Use the CoinCap API for fiat price information.\nThis API is reached through the following URL:\nhttps://api.coincap.io/v2/assets/bitcoin/history\n - COINDESK: Use the CoinDesk API for fiat price information.\nThis API is reached through the following URL:\nhttps://api.coindesk.com/v1/bpi/historical/close.json\n - CUSTOM: Use custom price data provided in a CSV file for fiat price information.\n - COINGECKO: Use the CoinGecko API for fiat price information.\nThis API is reached through the following URL:\nhttps://api.coingecko.com/api/v3/coins/bitcoin/market_chart\n - BITFINEX: Use the Bitfinex API for fiat price information.\nThis API is reached through the following URL:\nhttps://api-pub.bitfinex.com/v2/candles/trade:1h:tBTCUSD/hist" - }, - "frdrpcForwardingAbilityEntry": { - "type": "object", - "properties": { - "packed_idx": { - "type": "integer", - "format": "int64", - "description": "The indices of the incoming and outgoing peers packed into a single\n32-bit integer: packed_idx = (in \u003c\u003c 16) | out. This caps the peer set at\n65535 peers per direction." - }, - "effective_uptime_s": { - "type": "string", - "format": "int64", - "description": "Seconds the peer pair held at least the requested liquidity floor of\ndirectional forwardable liquidity over the window." - }, - "forwarded_sat": { - "type": "string", - "format": "int64", - "description": "Total successfully forwarded amount over the window, in satoshis." - } - } - }, - "frdrpcForwardingAbilityResponse": { - "type": "object", - "properties": { - "peers": { - "type": "array", - "items": { - "type": "string", - "format": "byte" - }, - "description": "Sorted list of unique compressed 33-byte public keys of the peers." - }, - "entries": { - "type": "array", - "items": { - "type": "object", - "$ref": "#/definitions/frdrpcForwardingAbilityEntry" - }, - "description": "Sparse list of forwarding ability entries. An entry is present only for a\npair that forwarded volume, carrying its exact effective_uptime_s and\nforwarded_sat. Pairs that did not forward are never listed here; they are\neither flagged in quiet_uptime_bitmask or absent. Entries take precedence\nover the bitmask for the same pair." - }, - "start_time": { - "type": "string", - "format": "int64", - "description": "The start of the window the metrics cover, as unix seconds." - }, - "end_time": { - "type": "string", - "format": "int64", - "description": "The end of the window the metrics cover, as unix seconds." - }, - "up_but_idle_bitmask": { - "type": "string", - "format": "byte", - "description": "A packed bitmask over the n*n ordered peer pairs, where n is the length\nof peers. The bit at index in*n+out is set when that pair held at least\nthe uptime_threshold fraction of effective uptime over the window but did\nnot forward: the dense \"up but idle\" population. A pair with a forwarded\nentry is never flagged here. A pair that is neither listed in entries nor\nflagged here had sub-threshold uptime and no forwards: treat it as zero." - }, - "uptime_threshold": { - "type": "number", - "format": "double", - "description": "The uptime fraction in [0, 1] used to populate up_but_idle_bitmask,\nechoed back so consumers know the threshold the server applied." - } - } + "description": "FiatBackend is the API endpoint to be used for any fiat related queries.\n\n - COINCAP: Use the CoinCap API for fiat price information.\nThis API is reached through the following URL:\nhttps://api.coincap.io/v2/assets/bitcoin/history\n - COINDESK: Use the CoinDesk API for fiat price information.\nThis API is reached through the following URL:\nhttps://api.coindesk.com/v1/bpi/historical/close.json\n - CUSTOM: Use custom price data provided in a CSV file for fiat price information.\n - COINGECKO: Use the CoinGecko API for fiat price information.\nThis API is reached through the following URL:\nhttps://api.coingecko.com/api/v3/coins/bitcoin/market_chart" }, "frdrpcGranularity": { "type": "string", @@ -1126,7 +890,6 @@ "custom_categories": { "type": "array", "items": { - "type": "object", "$ref": "#/definitions/frdrpcCustomCategory" }, "description": "An optional set of custom categories which can be used to identify bespoke\ncategories in the report. Each category must have a unique name, and may not\nhave common identifier regexes. Transactions that are matched to these\ncategories report the category name in the CustomCategory field." @@ -1138,7 +901,6 @@ "custom_prices": { "type": "array", "items": { - "type": "object", "$ref": "#/definitions/frdrpcBitcoinPrice" }, "description": "Custom price points to use if the CUSTOM FiatBackend option is set." @@ -1151,13 +913,26 @@ "reports": { "type": "array", "items": { - "type": "object", "$ref": "#/definitions/frdrpcReportEntry" }, "description": "On chain reports for the period queried." } } }, + "frdrpcOutlierRecommendationsRequest": { + "type": "object", + "properties": { + "rec_request": { + "$ref": "#/definitions/frdrpcCloseRecommendationRequest", + "description": "The parameters that are common to all close recommendations." + }, + "outlier_multiplier": { + "type": "number", + "format": "float", + "description": "The number of inter-quartile ranges a value needs to be beneath the lower\nquartile/ above the upper quartile to be considered a lower/upper outlier.\nLower values will be more aggressive in recommending channel closes, and\nupper values will be more conservative. Recommended values are 1.5 for\naggressive recommendations and 3 for conservative recommendations." + } + } + }, "frdrpcPairReport": { "type": "object", "properties": { @@ -1300,21 +1075,37 @@ "reports": { "type": "array", "items": { - "type": "object", "$ref": "#/definitions/frdrpcRevenueReport" }, "description": "Reports is a set of pairwise revenue report generated for the channel(s)\nover the period specified." } } }, + "frdrpcThresholdRecommendationsRequest": { + "type": "object", + "properties": { + "rec_request": { + "$ref": "#/definitions/frdrpcCloseRecommendationRequest", + "description": "The parameters that are common to all close recommendations." + }, + "threshold_value": { + "type": "number", + "format": "float", + "description": "The threshold that recommendations will be calculated based on.\nFor uptime: ratio of uptime to observed lifetime beneath which channels\nwill be recommended for closure.\n\nFor revenue: revenue per block that capital has been committed to the\nchannel beneath which channels will be recommended for closure. This\nvalue is provided per block so that channels that have been open for\ndifferent periods of time can be compared.\n\nFor incoming volume: The incoming volume per block that capital has\nbeen committed to the channel beneath which channels will be recommended\nfor closure. This value is provided per block so that channels that have\nbeen open for different periods of time can be compared.\n\nFor outgoing volume: The outgoing volume per block that capital has been\ncommitted to the channel beneath which channels will be recommended for\nclosure. This value is provided per block so that channels that have been\nopen for different periods of time can be compared.\n\nFor total volume: The total volume per block that capital has been\ncommitted to the channel beneath which channels will be recommended for\nclosure. This value is provided per block so that channels that have been\nopen for different periods of time can be compared." + } + } + }, "protobufAny": { "type": "object", "properties": { - "@type": { + "type_url": { "type": "string" + }, + "value": { + "type": "string", + "format": "byte" } - }, - "additionalProperties": {} + } }, "rpcStatus": { "type": "object", @@ -1329,7 +1120,6 @@ "details": { "type": "array", "items": { - "type": "object", "$ref": "#/definitions/protobufAny" } } diff --git a/frdrpc/faraday.yaml b/frdrpc/faraday.yaml index c289975..42734db 100644 --- a/frdrpc/faraday.yaml +++ b/frdrpc/faraday.yaml @@ -33,6 +33,3 @@ http: body: "*" - selector: frdrpc.FaradayServer.CloseReport get: "/v1/faraday/closereport" - - selector: frdrpc.FaradayServer.GetChannelEvents - post: "/v1/faraday/getchannelevents" - body: "*" diff --git a/frdrpc/faraday_grpc.pb.go b/frdrpc/faraday_grpc.pb.go index 120ec5a..cf25f5a 100644 --- a/frdrpc/faraday_grpc.pb.go +++ b/frdrpc/faraday_grpc.pb.go @@ -62,12 +62,6 @@ type FaradayServerClient interface { // Example request: // http://localhost:8466/v1/faraday/closereport CloseReport(ctx context.Context, in *CloseReportRequest, opts ...grpc.CallOption) (*CloseReportResponse, error) - // * - // Get a list of channel events that occurred for a given channel. - GetChannelEvents(ctx context.Context, in *ChannelEventsRequest, opts ...grpc.CallOption) (*ChannelEventsResponse, error) - // * - // Get forwarding ability analysis of peer pairs. - ForwardingAbility(ctx context.Context, in *ForwardingAbilityRequest, opts ...grpc.CallOption) (*ForwardingAbilityResponse, error) } type faradayServerClient struct { @@ -141,24 +135,6 @@ func (c *faradayServerClient) CloseReport(ctx context.Context, in *CloseReportRe return out, nil } -func (c *faradayServerClient) GetChannelEvents(ctx context.Context, in *ChannelEventsRequest, opts ...grpc.CallOption) (*ChannelEventsResponse, error) { - out := new(ChannelEventsResponse) - err := c.cc.Invoke(ctx, "/frdrpc.FaradayServer/GetChannelEvents", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *faradayServerClient) ForwardingAbility(ctx context.Context, in *ForwardingAbilityRequest, opts ...grpc.CallOption) (*ForwardingAbilityResponse, error) { - out := new(ForwardingAbilityResponse) - err := c.cc.Invoke(ctx, "/frdrpc.FaradayServer/ForwardingAbility", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - // FaradayServerServer is the server API for FaradayServer service. // All implementations must embed UnimplementedFaradayServerServer // for forward compatibility @@ -207,12 +183,6 @@ type FaradayServerServer interface { // Example request: // http://localhost:8466/v1/faraday/closereport CloseReport(context.Context, *CloseReportRequest) (*CloseReportResponse, error) - // * - // Get a list of channel events that occurred for a given channel. - GetChannelEvents(context.Context, *ChannelEventsRequest) (*ChannelEventsResponse, error) - // * - // Get forwarding ability analysis of peer pairs. - ForwardingAbility(context.Context, *ForwardingAbilityRequest) (*ForwardingAbilityResponse, error) mustEmbedUnimplementedFaradayServerServer() } @@ -241,12 +211,6 @@ func (UnimplementedFaradayServerServer) NodeAudit(context.Context, *NodeAuditReq func (UnimplementedFaradayServerServer) CloseReport(context.Context, *CloseReportRequest) (*CloseReportResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method CloseReport not implemented") } -func (UnimplementedFaradayServerServer) GetChannelEvents(context.Context, *ChannelEventsRequest) (*ChannelEventsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetChannelEvents not implemented") -} -func (UnimplementedFaradayServerServer) ForwardingAbility(context.Context, *ForwardingAbilityRequest) (*ForwardingAbilityResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ForwardingAbility not implemented") -} func (UnimplementedFaradayServerServer) mustEmbedUnimplementedFaradayServerServer() {} // UnsafeFaradayServerServer may be embedded to opt out of forward compatibility for this service. @@ -386,42 +350,6 @@ func _FaradayServer_CloseReport_Handler(srv interface{}, ctx context.Context, de return interceptor(ctx, in, info, handler) } -func _FaradayServer_GetChannelEvents_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ChannelEventsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(FaradayServerServer).GetChannelEvents(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/frdrpc.FaradayServer/GetChannelEvents", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(FaradayServerServer).GetChannelEvents(ctx, req.(*ChannelEventsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _FaradayServer_ForwardingAbility_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ForwardingAbilityRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(FaradayServerServer).ForwardingAbility(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/frdrpc.FaradayServer/ForwardingAbility", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(FaradayServerServer).ForwardingAbility(ctx, req.(*ForwardingAbilityRequest)) - } - return interceptor(ctx, in, info, handler) -} - // FaradayServer_ServiceDesc is the grpc.ServiceDesc for FaradayServer service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -457,14 +385,6 @@ var FaradayServer_ServiceDesc = grpc.ServiceDesc{ MethodName: "CloseReport", Handler: _FaradayServer_CloseReport_Handler, }, - { - MethodName: "GetChannelEvents", - Handler: _FaradayServer_GetChannelEvents_Handler, - }, - { - MethodName: "ForwardingAbility", - Handler: _FaradayServer_ForwardingAbility_Handler, - }, }, Streams: []grpc.StreamDesc{}, Metadata: "faraday.proto", diff --git a/frdrpc/faradayserver.pb.json.go b/frdrpc/faradayserver.pb.json.go index 538108d..09854b4 100644 --- a/frdrpc/faradayserver.pb.json.go +++ b/frdrpc/faradayserver.pb.json.go @@ -195,54 +195,4 @@ func RegisterFaradayServerJSONCallbacks(registry map[string]func(ctx context.Con } callback(string(respBytes), nil) } - - registry["frdrpc.FaradayServer.GetChannelEvents"] = func(ctx context.Context, - conn *grpc.ClientConn, reqJSON string, callback func(string, error)) { - - req := &ChannelEventsRequest{} - err := marshaler.Unmarshal([]byte(reqJSON), req) - if err != nil { - callback("", err) - return - } - - client := NewFaradayServerClient(conn) - resp, err := client.GetChannelEvents(ctx, req) - if err != nil { - callback("", err) - return - } - - respBytes, err := marshaler.Marshal(resp) - if err != nil { - callback("", err) - return - } - callback(string(respBytes), nil) - } - - registry["frdrpc.FaradayServer.ForwardingAbility"] = func(ctx context.Context, - conn *grpc.ClientConn, reqJSON string, callback func(string, error)) { - - req := &ForwardingAbilityRequest{} - err := marshaler.Unmarshal([]byte(reqJSON), req) - if err != nil { - callback("", err) - return - } - - client := NewFaradayServerClient(conn) - resp, err := client.ForwardingAbility(ctx, req) - if err != nil { - callback("", err) - return - } - - respBytes, err := marshaler.Marshal(resp) - if err != nil { - callback("", err) - return - } - callback(string(respBytes), nil) - } } diff --git a/frdrpc/forwarding_ability_codec.go b/frdrpc/forwarding_ability_codec.go deleted file mode 100644 index e105ac6..0000000 --- a/frdrpc/forwarding_ability_codec.go +++ /dev/null @@ -1,374 +0,0 @@ -package frdrpc - -import ( - "bytes" - "encoding/hex" - "errors" - "fmt" - "math" - "sort" - "strings" -) - -// maxPackedPeers is the largest peer set a response can address. packed_idx -// splits a uint32 into two 16-bit indices (in << 16 | out), so each direction -// can reference at most 65535 distinct peers. -const maxPackedPeers = 1<<16 - 1 - -// ForwardingAbility is a client-facing mirror of the raw forwarding facts for -// one direction of a peer pair over the analysis window. Derived rates and -// categories are left to the consumer. -type ForwardingAbility struct { - // EffectiveUptimeS is the seconds the pair held at least the requested - // liquidity floor of directional forwardable liquidity over the window. - // The value is whole seconds: sub-second uptime floors to zero, so a - // pair that forwarded volume over a fleeting qualifying window can - // report a zero uptime alongside a non-zero ForwardedSat. - EffectiveUptimeS int64 - - // ForwardedSat is the total successfully forwarded amount over the - // window, in satoshis. - ForwardedSat int64 -} - -// abilityTier classifies how a pair is encoded: a full entry, a single "up but -// idle" bit, or omitted entirely. -type abilityTier int - -const ( - // tierAbsent omits the pair: it neither forwarded nor held enough - // uptime to clear the threshold. Consumers treat absence as zero. - tierAbsent abilityTier = iota - - // tierBit flags the pair in the up-but-idle bitmask: it held at least - // the uptime threshold but did not forward. - tierBit - - // tierEntry emits a full entry carrying the pair's exact uptime and - // forwarded volume. Reserved for pairs that actually forwarded. - tierEntry -) - -// tier decides how a pair is encoded given the minimum qualifying uptime in -// seconds. Forwarding always wins, so a pair that forwarded keeps its exact -// facts even if its uptime is below the threshold; otherwise the pair is -// compacted to a bit when it was up enough, and dropped when it was not. -func (a ForwardingAbility) tier(minUptimeS int64) abilityTier { - switch { - case a.ForwardedSat > 0: - return tierEntry - - case a.EffectiveUptimeS >= minUptimeS: - return tierBit - - default: - return tierAbsent - } -} - -// MinQualifyingUptime converts an uptime fraction threshold into the smallest -// whole-second uptime that clears it over the given window. It is the single -// source of truth shared by the encoder (to bucket pairs) and the server (to -// apply the node-down guard), so the two cannot drift. A pair clears the -// threshold when EffectiveUptimeS >= the returned value, matching the "at least -// the threshold fraction" contract. The result is floored at one second so a -// pair with zero uptime is never treated as up. A non-positive window admits -// nothing. -func MinQualifyingUptime(threshold float64, windowSeconds int64) int64 { - if windowSeconds <= 0 { - return math.MaxInt64 - } - - v := int64(math.Ceil(threshold * float64(windowSeconds))) - if v < 1 { - v = 1 - } - - return v -} - -// setBit sets the bit at the given index in a packed bitmask. The index is an -// int64 because an n*n bitmask over the full peer set overflows a 32-bit int. -func setBit(mask []byte, index int64) { - mask[index/8] |= 1 << (index % 8) -} - -// getBit reports whether the bit at the given index in a packed bitmask is set. -// The index is an int64 because an n*n bitmask over the full peer set overflows -// a 32-bit int. -func getBit(mask []byte, index int64) bool { - return mask[index/8]&(1<<(index%8)) != 0 -} - -// EncodeForwardingAbility serializes a nested map of peer forwarding abilities -// into a memory-efficient sparse gRPC response over [startTime, endTime]. To -// optimize payload size it tiers each pair: pairs that forwarded keep a full -// entry, pairs that were up at least uptimeThreshold of the window but did not -// forward collapse to a single bit in the up-but-idle bitmask, and pairs below -// the threshold that did not forward are omitted entirely. Public keys are -// deduplicated and peer pairs packed into 32-bit indices. -func EncodeForwardingAbility(abilities map[string]map[string]ForwardingAbility, - startTime, endTime int64, - uptimeThreshold float64) (*ForwardingAbilityResponse, error) { - - minUptimeS := MinQualifyingUptime(uptimeThreshold, endTime-startTime) - - // First, find all unique peers involved in pairs that warrant either an - // entry or a bit. Keys are normalized to lower-case hex so a peer that - // appears in mixed case across entries collapses to a single index - // rather than being silently dropped at lookup time. - peerSet := make(map[string]struct{}) - for inPeer, outMap := range abilities { - for outPeer, ability := range outMap { - if ability.tier(minUptimeS) == tierAbsent { - continue - } - - peerSet[strings.ToLower(inPeer)] = struct{}{} - peerSet[strings.ToLower(outPeer)] = struct{}{} - } - } - - // Decode to raw bytes and sort. - var rawPeers [][]byte - for peerHex := range peerSet { - b, err := hex.DecodeString(peerHex) - if err != nil { - return nil, err - } - rawPeers = append(rawPeers, b) - } - - sort.Slice( - rawPeers, - func(i, j int) bool { - return bytes.Compare(rawPeers[i], rawPeers[j]) < 0 - }, - ) - - // Peer indices occupy 16 bits each in packed_idx, so the set must stay - // within maxPackedPeers. Beyond it, an index would overflow its field - // and silently decode to the wrong peer pair, so fail loudly instead. - if len(rawPeers) > maxPackedPeers { - return nil, fmt.Errorf("peer set of %d exceeds the %d "+ - "addressable by packed_idx", len(rawPeers), - maxPackedPeers) - } - - // Create map for index lookup using normalized lowercase hex strings. - peerIndex := make(map[string]uint32) - for idx, b := range rawPeers { - peerIndex[hex.EncodeToString(b)] = uint32(idx) - } - - // The bitmask addresses every ordered pair over the peer set, so it - // needs n*n bits. Allocation is deferred until a bit is actually set so - // a response with no up-but-idle pairs carries no bitmask at all. - n := int64(len(rawPeers)) - var bitmask []byte - - // Build the entries and bitmask. seen guards against two input keys - // that differ only by hex case collapsing onto the same packed pair. - var entries []*ForwardingAbilityEntry - seen := make(map[uint32]struct{}) - - // addEntry appends a full entry for a forwarded pair. - addEntry := func(packed uint32, a ForwardingAbility) { - entries = append(entries, &ForwardingAbilityEntry{ - PackedIdx: packed, - EffectiveUptimeS: a.EffectiveUptimeS, - ForwardedSat: a.ForwardedSat, - }) - } - - for inPeer, outMap := range abilities { - inIdx, okIn := peerIndex[strings.ToLower(inPeer)] - if !okIn { - continue - } - - for outPeer, ability := range outMap { - tier := ability.tier(minUptimeS) - if tier == tierAbsent { - continue - } - - outIdx, okOut := peerIndex[strings.ToLower(outPeer)] - if !okOut { - continue - } - - // Pack the in-peer index into the high 16 bits and the - // out-peer index into the low 16. - packed := (inIdx << 16) | outIdx - - // Reject a case-folded collision rather than silently - // dropping one of the two entries' facts. - if _, dup := seen[packed]; dup { - return nil, fmt.Errorf("duplicate peer pair "+ - "after case normalization: "+ - "in=%s out=%s", inPeer, outPeer) - } - seen[packed] = struct{}{} - - switch tier { - case tierEntry: - addEntry(packed, ability) - - case tierBit: - // The bitmask addresses n*n ordered pairs, one - // bit each. - if bitmask == nil { - bitmask = make( - []byte, (n*n+7)/8, - ) - } - setBit( - bitmask, - int64(inIdx)*n+int64(outIdx), - ) - } - } - } - - // Sort entries by packed_idx for deterministic output and testability. - sort.Slice( - entries, - func(i, j int) bool { - return entries[i].PackedIdx < entries[j].PackedIdx - }, - ) - - return &ForwardingAbilityResponse{ - Peers: rawPeers, - Entries: entries, - StartTime: startTime, - EndTime: endTime, - UpButIdleBitmask: bitmask, - UptimeThreshold: uptimeThreshold, - }, nil -} - -// DecodeForwardingAbility reconstructs the nested map of peer forwarding -// abilities from a sparse packed gRPC response. Forwarded pairs come back with -// their exact facts; up-but-idle pairs flagged in the bitmask come back at full -// window uptime with zero forwarded volume. It validates packed indices and the -// bitmask length against the decoded peer list to prevent out-of-bounds errors. -func DecodeForwardingAbility(resp *ForwardingAbilityResponse) ( - map[string]map[string]ForwardingAbility, error) { - - result := make(map[string]map[string]ForwardingAbility) - if resp == nil { - return result, nil - } - - numPeers := len(resp.Peers) - - // packed_idx addresses peers with 16-bit indices, so a response with - // more than maxPackedPeers peers is malformed. Rejecting it here also - // keeps the n*n bitmask-length computation below from overflowing a - // 32-bit int. - if numPeers > maxPackedPeers { - return nil, fmt.Errorf("peer set of %d exceeds the %d "+ - "addressable by packed_idx", numPeers, maxPackedPeers) - } - - record := func(inIdx, outIdx int, ability ForwardingAbility) { - inPeer := hex.EncodeToString(resp.Peers[inIdx]) - outPeer := hex.EncodeToString(resp.Peers[outIdx]) - - if _, ok := result[inPeer]; !ok { - result[inPeer] = make(map[string]ForwardingAbility) - } - result[inPeer][outPeer] = ability - } - - // Decode the forwarded entries first so they take precedence over any - // bit set for the same pair. - for _, entry := range resp.Entries { - // Unpack the pair: the in-peer index is the high 16 bits, the - // out-peer index the low 16. - inIdx := int(entry.PackedIdx >> 16) - outIdx := int(entry.PackedIdx & 0xffff) - - if inIdx >= numPeers || outIdx >= numPeers { - return nil, errors.New("decoded peer index out of " + - "bounds") - } - - record( - inIdx, outIdx, ForwardingAbility{ - EffectiveUptimeS: entry.EffectiveUptimeS, - ForwardedSat: entry.ForwardedSat, - }, - ) - } - - // Expand the up-but-idle bitmask. An absent bitmask simply means no - // pair was flagged; a present one must address exactly the n*n pairs. - bitmask := resp.UpButIdleBitmask - if len(bitmask) == 0 { - return result, nil - } - - // Compute the expected length in int64 so the n*n multiplication does - // not overflow a 32-bit int for a large peer set. - totalPairs := int64(numPeers) * int64(numPeers) - if want := int((totalPairs + 7) / 8); len(bitmask) != want { - return nil, fmt.Errorf("bitmask length %d does not match the "+ - "%d expected for %d peers", len(bitmask), want, - numPeers) - } - - // Up-but-idle pairs were up the whole window by definition of the - // threshold bucket, so reconstruct them at full window uptime with zero - // forwarded volume. Iterate over the bitmask bytes directly, skipping - // zero bytes, so cost scales with the number of set bits rather than - // the O(n*n) pair space; padding bits beyond n*n are ignored. - windowSeconds := resp.EndTime - resp.StartTime - for i, b := range bitmask { - if b == 0 { - continue - } - - for bit := range 8 { - // If the bit is not set, skip the pair. This also - // implicitly ignores any padding bits in the last byte - // beyond the n*n pairs. - if b&(1<= totalPairs { - break - } - - // Unpack the pair: the in-peer index is the high 16 - // bits, the out-peer index the low 16. The bounds were - // already checked against the bitmask length, so this - // cannot overflow. - inIdx := int(k / int64(numPeers)) - outIdx := int(k % int64(numPeers)) - - // An entry for this pair takes precedence; never - // overwrite it. - inPeer := hex.EncodeToString(resp.Peers[inIdx]) - outPeer := hex.EncodeToString(resp.Peers[outIdx]) - if _, ok := result[inPeer][outPeer]; ok { - continue - } - - record( - inIdx, outIdx, ForwardingAbility{ - EffectiveUptimeS: windowSeconds, - ForwardedSat: 0, - }, - ) - } - } - - return result, nil -} diff --git a/frdrpc/forwarding_ability_codec_test.go b/frdrpc/forwarding_ability_codec_test.go deleted file mode 100644 index 7029138..0000000 --- a/frdrpc/forwarding_ability_codec_test.go +++ /dev/null @@ -1,587 +0,0 @@ -package frdrpc - -import ( - "encoding/hex" - "fmt" - "math" - "strings" - "testing" - - "github.com/stretchr/testify/require" -) - -// fwdKey returns a distinct 33-byte compressed-pubkey hex string for n. Keys -// sort ascending in n, matching the byte ordering the encoder applies. -func fwdKey(n int) string { - return fmt.Sprintf("02%064x", n) -} - -// pair is one expected decoded entry, flattened from the nested result map for -// easy comparison. -type pair struct { - in string - out string - ability ForwardingAbility -} - -// TestForwardingAbilityCodecRoundTrip verifies the three-tier encoding: pairs -// that forwarded keep exact facts as entries, pairs up at least the threshold -// but idle collapse to a bitmask bit (decoded at full window uptime), and -// sub-threshold idle pairs are dropped. The window is [0, 100) and the -// threshold 0.5, so the minimum qualifying uptime is 50 seconds. -func TestForwardingAbilityCodecRoundTrip(t *testing.T) { - const ( - startTime, endTime int64 = 0, 100 - threshold float64 = 0.5 - ) - - tests := []struct { - name string - abilities map[string]map[string]ForwardingAbility - wantPeers []string - wantPairs []pair - wantBitmask bool - }{ - { - // Forwarding wins regardless of uptime, so a - // zero-uptime pair that moved volume survives with its - // exact facts and never lands in the bitmask. - name: "forwarded pairs keep exact facts", - abilities: map[string]map[string]ForwardingAbility{ - fwdKey(1): { - fwdKey(2): { - EffectiveUptimeS: 80, - ForwardedSat: 1500, - }, - }, - fwdKey(2): { - fwdKey(1): { - EffectiveUptimeS: 0, - ForwardedSat: 2500, - }, - }, - }, - wantPeers: []string{ - fwdKey(1), - fwdKey(2), - }, - wantPairs: []pair{ - { - fwdKey(1), - fwdKey(2), - ForwardingAbility{ - 80, - 1500, - }, - }, - { - fwdKey(2), - fwdKey(1), - ForwardingAbility{ - 0, - 2500, - }, - }, - }, - wantBitmask: false, - }, - { - // Up at or above the threshold but no forwards: a bit, - // decoded back at the full window's uptime. - name: "up but idle becomes a bit", - abilities: map[string]map[string]ForwardingAbility{ - fwdKey(1): { - fwdKey(2): { - EffectiveUptimeS: 80, - }, - }, - fwdKey(3): { - fwdKey(1): { - EffectiveUptimeS: 50, - }, - }, - }, - wantPeers: []string{ - fwdKey(1), - fwdKey(2), - fwdKey(3), - }, - wantPairs: []pair{ - { - fwdKey(1), - fwdKey(2), - ForwardingAbility{ - 100, - 0, - }, - }, - { - fwdKey(3), - fwdKey(1), - ForwardingAbility{ - 100, - 0, - }, - }, - }, - wantBitmask: true, - }, - { - // Below the threshold with no forwards: dropped. - name: "sub-threshold idle pairs dropped", - abilities: map[string]map[string]ForwardingAbility{ - fwdKey(1): { - fwdKey(2): { - EffectiveUptimeS: 49, - }, - }, - }, - wantPeers: []string{}, - wantPairs: []pair{}, - wantBitmask: false, - }, - { - // All three tiers at once, including a peer that only - // appears via the bitmask. - name: "mixed tiers", - abilities: map[string]map[string]ForwardingAbility{ - fwdKey(1): { - fwdKey(2): { - EffectiveUptimeS: 80, - ForwardedSat: 1500, - }, - fwdKey(3): { - EffectiveUptimeS: 60, - }, - }, - fwdKey(2): { - fwdKey(3): { - EffectiveUptimeS: 10, - }, - }, - fwdKey(3): { - fwdKey(1): { - ForwardedSat: 500, - }, - }, - }, - wantPeers: []string{ - fwdKey(1), - fwdKey(2), - fwdKey(3), - }, - wantPairs: []pair{ - { - fwdKey(1), - fwdKey(2), - ForwardingAbility{ - 80, - 1500, - }, - }, - { - fwdKey(1), - fwdKey(3), - ForwardingAbility{ - 100, - 0, - }, - }, - { - fwdKey(3), - fwdKey(1), - ForwardingAbility{ - 0, - 500, - }, - }, - }, - wantBitmask: true, - }, - } - - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - resp, err := EncodeForwardingAbility( - tc.abilities, startTime, endTime, threshold, - ) - require.NoError(t, err) - require.Equal(t, startTime, resp.StartTime) - require.Equal(t, endTime, resp.EndTime) - require.Equal(t, threshold, resp.UptimeThreshold) - - require.Equal( - t, tc.wantBitmask, - len(resp.UpButIdleBitmask) > 0, - ) - - // A present bitmask must address exactly n*n bits. - if tc.wantBitmask { - n := len(resp.Peers) - require.Len(t, resp.UpButIdleBitmask, (n*n+7)/8) - } - - gotPeers := make([]string, len(resp.Peers)) - for i, p := range resp.Peers { - gotPeers[i] = hex.EncodeToString(p) - } - require.Equal(t, tc.wantPeers, gotPeers) - - decoded, err := DecodeForwardingAbility(resp) - require.NoError(t, err) - - got := make(map[string]ForwardingAbility) - for in, outMap := range decoded { - for out, ability := range outMap { - got[in+"->"+out] = ability - } - } - require.Len(t, got, len(tc.wantPairs)) - for _, wp := range tc.wantPairs { - require.Equal( - t, wp.ability, got[wp.in+"->"+wp.out], - ) - } - }) - } -} - -// TestMinQualifyingUptime verifies the threshold-to-seconds conversion shared -// by the encoder and the server guard, including its boundary behavior. -func TestMinQualifyingUptime(t *testing.T) { - tests := []struct { - name string - threshold float64 - window int64 - want int64 - }{ - { - "half of clean window", - 0.5, - 100, - 50, - }, - { - "rounds up a fraction", - 0.333, - 100, - 34, - }, - { - "integer boundary", - 0.9, - 2_592_000, - 2_332_800, - }, - { - "floored at one second", - 0.0, - 100, - 1, - }, - { - "non-positive window admits nothing", - 0.5, - 0, - math.MaxInt64, - }, - } - - for _, tc := range tests { - t.Run( - tc.name, - func(t *testing.T) { - require.Equal( - t, tc.want, MinQualifyingUptime( - tc.threshold, tc.window, - ), - ) - }, - ) - } -} - -// TestBitmaskHelpers verifies that setBit and getBit address the same bit. -func TestBitmaskHelpers(t *testing.T) { - mask := make([]byte, 2) - require.False(t, getBit(mask, 9)) - - setBit(mask, 9) - require.True(t, getBit(mask, 9)) - require.False(t, getBit(mask, 8)) - require.False(t, getBit(mask, 10)) -} - -// TestForwardingAbilityDecodeEntryPrecedence verifies that when a pair is both -// listed as an entry and flagged in the bitmask, the entry's exact facts win. -func TestForwardingAbilityDecodeEntryPrecedence(t *testing.T) { - // Two peers => a 2*2 bitmask needs (4+7)/8 = 1 byte. Set the bit for - // pair (0, 1) at index 0*2+1 = 1, and also list it as an entry. - mask := make([]byte, 1) - setBit(mask, 1) - - resp := &ForwardingAbilityResponse{ - Peers: [][]byte{ - { - 1, - }, - { - 2, - }, - }, - StartTime: 0, - EndTime: 100, - Entries: []*ForwardingAbilityEntry{ - { - PackedIdx: (0 << 16) | 1, - EffectiveUptimeS: 42, - ForwardedSat: 7, - }, - }, - UpButIdleBitmask: mask, - } - - decoded, err := DecodeForwardingAbility(resp) - require.NoError(t, err) - require.Equal( - t, ForwardingAbility{42, 7}, - decoded[hex.EncodeToString([]byte{1})][hex.EncodeToString( - []byte{2}, - )], - ) -} - -// TestForwardingAbilityDecodeBadIndex verifies that a packed index referencing -// a peer beyond the decoded peer list is rejected rather than silently mapped. -func TestForwardingAbilityDecodeBadIndex(t *testing.T) { - resp := &ForwardingAbilityResponse{ - Peers: [][]byte{ - { - 1, - 2, - 3, - }, - }, - Entries: []*ForwardingAbilityEntry{ - { - // Out index 1 is out of bounds for a single - // peer. - PackedIdx: (0 << 16) | 1, - EffectiveUptimeS: 3600, - ForwardedSat: 1000, - }, - }, - } - - _, err := DecodeForwardingAbility(resp) - require.ErrorContains(t, err, "peer index out of bounds") -} - -// TestForwardingAbilityDecodeBadBitmaskLen verifies that a bitmask whose length -// does not match the n*n pairs of the peer set is rejected. -func TestForwardingAbilityDecodeBadBitmaskLen(t *testing.T) { - resp := &ForwardingAbilityResponse{ - // Two peers expect a 1-byte bitmask; supply two bytes. - Peers: [][]byte{ - { - 1, - }, - { - 2, - }, - }, - UpButIdleBitmask: []byte{ - 0x00, - 0x00, - }, - } - - _, err := DecodeForwardingAbility(resp) - require.ErrorContains(t, err, "bitmask length") -} - -// TestForwardingAbilityEncodePeerCap verifies that a peer set too large to -// address with packed_idx is rejected loudly instead of overflowing an index -// into the wrong peer pair. -func TestForwardingAbilityEncodePeerCap(t *testing.T) { - outMap := make(map[string]ForwardingAbility) - for i := 1; i <= maxPackedPeers+1; i++ { - // Use forwarded volume so inclusion is threshold-independent. - outMap[fwdKey(i)] = ForwardingAbility{ForwardedSat: 1} - } - abilities := map[string]map[string]ForwardingAbility{ - fwdKey(0): outMap, - } - - _, err := EncodeForwardingAbility(abilities, 0, 1, 0.5) - require.ErrorContains(t, err, "exceeds") -} - -// TestForwardingAbilityEncodeNormalizesCase verifies that a peer appearing in -// mixed hex case collapses to a single index rather than producing a duplicate -// peer entry. -func TestForwardingAbilityEncodeNormalizesCase(t *testing.T) { - // Use a key with hex letters so its upper- and lower-case forms are - // genuinely distinct map keys. - peer := fwdKey(0xabcdef) - - abilities := map[string]map[string]ForwardingAbility{ - strings.ToUpper(peer): { - fwdKey(2): { - ForwardedSat: 20, - }, - }, - peer: { - fwdKey(3): { - ForwardedSat: 40, - }, - }, - } - - resp, err := EncodeForwardingAbility(abilities, 0, 1, 0.5) - require.NoError(t, err) - - // The upper- and lower-case forms of the shared peer must dedup to one - // index, leaving exactly three distinct peers. - require.Len(t, resp.Peers, 3) - - decoded, err := DecodeForwardingAbility(resp) - require.NoError(t, err) - require.Equal( - t, ForwardingAbility{ - ForwardedSat: 20, - }, - decoded[peer][fwdKey(2)], - ) - require.Equal( - t, ForwardingAbility{ - ForwardedSat: 40, - }, - decoded[peer][fwdKey(3)], - ) -} - -// TestForwardingAbilityEncodeRejectsCaseCollision verifies that two input keys -// that differ only by hex case but address the same peer pair are rejected -// rather than silently collapsing onto one packed index and dropping a fact. -func TestForwardingAbilityEncodeRejectsCaseCollision(t *testing.T) { - inPeer := fwdKey(0xabcdef) - outPeer := fwdKey(2) - - // Both in-peer spellings normalize to the same index and share the same - // out-peer, so they collide on packed_idx. - abilities := map[string]map[string]ForwardingAbility{ - strings.ToUpper(inPeer): { - outPeer: { - ForwardedSat: 10, - }, - }, - inPeer: { - outPeer: { - ForwardedSat: 20, - }, - }, - } - - _, err := EncodeForwardingAbility(abilities, 0, 1, 0.5) - require.Error(t, err) -} - -// TestForwardingAbilityCodecRoundTripHighIndices round-trips a large peer set -// so that packed indices exceed a single byte and exercise the high bits of -// each 16-bit direction field, and the up-but-idle bitmask spans many bytes. It -// guards index packing and bitmask addressing against regressions that only -// surface beyond the small indices the other round-trip cases use. -func TestForwardingAbilityCodecRoundTripHighIndices(t *testing.T) { - const ( - numPeers = 300 - startTime, endTime = int64(0), int64(100) - threshold = 0.5 - ) - - // Build a cycle so every peer appears and takes a stable index equal to - // its fwdKey ordinal. Even edges forward (kept as exact entries); odd - // edges are up but idle at >= threshold (collapsed to a bitmask bit, - // decoded back at the full window uptime). - abilities := make(map[string]map[string]ForwardingAbility, numPeers) - want := make(map[string]ForwardingAbility, numPeers) - for i := range numPeers { - in, out := fwdKey(i), fwdKey((i+1)%numPeers) - - var enc, dec ForwardingAbility - if i%2 == 0 { - // Add pair that forwarded. - enc = ForwardingAbility{ - EffectiveUptimeS: 70, - ForwardedSat: int64(i + 1), - } - dec = enc - } else { - // Add up, but idle pair. - enc = ForwardingAbility{EffectiveUptimeS: 60} - dec = ForwardingAbility{ - EffectiveUptimeS: endTime - startTime, - } - } - - abilities[in] = map[string]ForwardingAbility{out: enc} - want[in+"->"+out] = dec - } - - resp, err := EncodeForwardingAbility( - abilities, startTime, endTime, threshold, - ) - require.NoError(t, err) - require.Len(t, resp.Peers, numPeers) - - // With 300 peers the indices exceed one byte, so at least one packed - // index must use the high bits of its 16-bit field. - var sawHighIdx bool - for _, e := range resp.Entries { - if e.PackedIdx>>16 > 0xff || e.PackedIdx&0xffff > 0xff { - sawHighIdx = true - break - } - } - require.True(t, sawHighIdx, "expected an index beyond one byte") - - decoded, err := DecodeForwardingAbility(resp) - require.NoError(t, err) - - got := make(map[string]ForwardingAbility) - for in, outMap := range decoded { - for out, ability := range outMap { - got[in+"->"+out] = ability - } - } - require.Equal(t, want, got) -} - -// TestForwardingAbilityDecodeNil verifies that decoding a nil response yields -// an empty map rather than panicking. -func TestForwardingAbilityDecodeNil(t *testing.T) { - decoded, err := DecodeForwardingAbility(nil) - require.NoError(t, err) - require.Empty(t, decoded) -} - -// TestForwardingAbilityDecodeIgnoresPaddingBit verifies that a bit set in the -// padding region beyond the n*n pairs of the final byte is ignored rather than -// decoded into a bogus pair. -func TestForwardingAbilityDecodeIgnoresPaddingBit(t *testing.T) { - // Two peers => 2*2 = 4 valid bits in a 1-byte mask; bits 4..7 are - // padding. Set padding bit 5 and assert nothing decodes from it. - mask := make([]byte, 1) - setBit(mask, 5) - - resp := &ForwardingAbilityResponse{ - Peers: [][]byte{{1}, {2}}, - StartTime: 0, - EndTime: 100, - UpButIdleBitmask: mask, - } - - decoded, err := DecodeForwardingAbility(resp) - require.NoError(t, err) - require.Empty(t, decoded) -} diff --git a/frdrpc/go.mod b/frdrpc/go.mod deleted file mode 100644 index 9087bec..0000000 --- a/frdrpc/go.mod +++ /dev/null @@ -1,23 +0,0 @@ -module github.com/lightninglabs/faraday/frdrpc - -require ( - github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 - github.com/stretchr/testify v1.10.0 - google.golang.org/grpc v1.65.0 - google.golang.org/protobuf v1.34.2 -) - -require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/kr/text v0.2.0 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rogpeppe/go-internal v1.15.0 // indirect - golang.org/x/net v0.38.0 // indirect - golang.org/x/sys v0.31.0 // indirect - golang.org/x/text v0.23.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) - -go 1.25.10 diff --git a/frdrpc/go.sum b/frdrpc/go.sum deleted file mode 100644 index c5f2aca..0000000 --- a/frdrpc/go.sum +++ /dev/null @@ -1,36 +0,0 @@ -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -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/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -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.15.0 h1:D0RCU5rMAp+SpgkiNdrjfJ+LX4J1M32V2NeCY7EJ6hc= -github.com/rogpeppe/go-internal v1.15.0/go.mod h1:DrUVZyrJU+txYW5/1kwtXQSMFio52ZOxX7yM1VHvnxs= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= -golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= -google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= -google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= -google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= -google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/frdrpcserver/exchange_rate.go b/frdrpcserver/exchange_rate.go index 303779a..f61c5d5 100644 --- a/frdrpcserver/exchange_rate.go +++ b/frdrpcserver/exchange_rate.go @@ -10,11 +10,6 @@ import ( "github.com/lightninglabs/faraday/frdrpc" ) -// fiatBackendBitfinex is the rpc enum value for BITFINEX. -// TODO: Replace with frdrpc.FiatBackend_BITFINEX once the frdrpc module is -// tagged and the dependency is bumped. -const fiatBackendBitfinex = frdrpc.FiatBackend(5) - func priceCfgFromRPC(rpcBackend frdrpc.FiatBackend, rpcGranularity frdrpc.Granularity, disable bool, start, end time.Time, prices []*frdrpc.BitcoinPrice) (*fiat.PriceSourceConfig, error) { @@ -39,8 +34,7 @@ func priceCfgFromRPC(rpcBackend frdrpc.FiatBackend, // Get additional values for backends that require additional // information. switch backend { - case fiat.CoinCapPriceBackend, fiat.CoinbasePriceBackend, - fiat.BitfinexPriceBackend: + case fiat.CoinCapPriceBackend: granularity, err = granularityFromRPC( rpcGranularity, disable, end.Sub(start), ) @@ -131,9 +125,6 @@ func fiatBackendFromRPC(backend frdrpc.FiatBackend) (fiat.PriceBackend, error) { case frdrpc.FiatBackend_COINGECKO: return fiat.CoinGeckoPriceBackend, nil - case fiatBackendBitfinex: - return fiat.BitfinexPriceBackend, nil - default: return fiat.UnknownPriceBackend, fmt.Errorf("unknown fiat backend: %v", backend) diff --git a/frdrpcserver/exchange_rate_test.go b/frdrpcserver/exchange_rate_test.go deleted file mode 100644 index c1e7abf..0000000 --- a/frdrpcserver/exchange_rate_test.go +++ /dev/null @@ -1,94 +0,0 @@ -package frdrpcserver - -import ( - "testing" - "time" - - "github.com/lightninglabs/faraday/fiat" - "github.com/lightninglabs/faraday/frdrpc" - "github.com/stretchr/testify/require" -) - -// TestFiatBackendFromRPC checks mapping from rpc enum values to fiat backend -// implementations. -func TestFiatBackendFromRPC(t *testing.T) { - t.Parallel() - - tests := []struct { - name string - in frdrpc.FiatBackend - expected fiat.PriceBackend - expectErr bool - }{ - { - name: "unknown", - in: frdrpc.FiatBackend_UNKNOWN_FIATBACKEND, - expected: fiat.UnknownPriceBackend, - }, - { - name: "coincap", - in: frdrpc.FiatBackend_COINCAP, - expected: fiat.CoinCapPriceBackend, - }, - { - name: "coindesk", - in: frdrpc.FiatBackend_COINDESK, - expected: fiat.CoinDeskPriceBackend, - }, - { - name: "custom", - in: frdrpc.FiatBackend_CUSTOM, - expected: fiat.CustomPriceBackend, - }, - { - name: "coingecko", - in: frdrpc.FiatBackend_COINGECKO, - expected: fiat.CoinGeckoPriceBackend, - }, - { - name: "bitfinex", - in: fiatBackendBitfinex, - expected: fiat.BitfinexPriceBackend, - }, - { - name: "invalid enum", - in: frdrpc.FiatBackend(999), - expectErr: true, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - backend, err := fiatBackendFromRPC(test.in) - if test.expectErr { - require.Error(t, err) - } else { - require.NoError(t, err) - require.Equal(t, test.expected, backend) - } - }) - } -} - -// TestPriceCfgFromRPCBitfinexGranularity verifies that priceCfgFromRPC sets -// a granularity for bitfinex so that the resulting config passes validation. -func TestPriceCfgFromRPCBitfinexGranularity(t *testing.T) { - t.Parallel() - - start := time.Unix(1711929600, 0).UTC() - end := start.Add(2 * time.Hour) - - cfg, err := priceCfgFromRPC( - fiatBackendBitfinex, frdrpc.Granularity_HOUR, false, - start, end, nil, - ) - require.NoError(t, err) - require.NotNil(t, cfg) - require.Equal(t, fiat.BitfinexPriceBackend, cfg.Backend) - require.NotNil(t, cfg.Granularity) - require.Equal(t, fiat.GranularityHour, *cfg.Granularity) - - // Validate that this config can be used to construct a price source. - _, err = fiat.NewPriceSource(cfg) - require.NoError(t, err) -} diff --git a/frdrpcserver/forwarding_ability.go b/frdrpcserver/forwarding_ability.go deleted file mode 100644 index 2d4088b..0000000 --- a/frdrpcserver/forwarding_ability.go +++ /dev/null @@ -1,169 +0,0 @@ -package frdrpcserver - -import ( - "context" - "log/slog" - "math" - "time" - - "github.com/btcsuite/btcd/btcutil" - "github.com/lightninglabs/faraday/frdrpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -// defaultLiquidityFloorSat is the liquidity floor applied when the request -// leaves liquidity_floor_sat unset. It approximates the smallest amount a -// rebalancer would still move, below which a pair is not economically -// forwardable. -const defaultLiquidityFloorSat = 50_000 - -// defaultUptimeThreshold is the uptime fraction applied when the request leaves -// uptime_threshold unset. A pair that was up at least this fraction of the -// window but did not forward is reported as a single bit rather than a full -// entry. It is high so that only reliably available pairs are flagged, keeping -// the response sparse and the node-down guard meaningful. -const defaultUptimeThreshold = 0.9 - -// ForwardingAbility returns the raw effective-uptime and forwarded-volume facts -// for each peer pair over the requested window. An unset end_time defaults to -// the current time and an unset liquidity_floor_sat to -// defaultLiquidityFloorSat. -func (s *RPCServer) ForwardingAbility(ctx context.Context, - req *frdrpc.ForwardingAbilityRequest) ( - *frdrpc.ForwardingAbilityResponse, error) { - - log.DebugS( - ctx, "Handling ForwardingAbility request", - slog.Uint64("start_time", req.StartTime), - slog.Uint64("end_time", req.EndTime), - slog.Uint64("liquidity_floor_sat", req.LiquidityFloorSat), - ) - - // time.Unix takes an int64, so reject any request value that would - // overflow when its uint64 seconds are narrowed below. - if req.StartTime > math.MaxInt64 { - return nil, status.Error( - codes.InvalidArgument, - "start_time exceeds maximum allowed value", - ) - } - if req.EndTime > math.MaxInt64 { - return nil, status.Error( - codes.InvalidArgument, - "end_time exceeds maximum allowed value", - ) - } - - startTime := time.Unix(int64(req.StartTime), 0) - endTime := time.Now() - if req.EndTime != 0 { - endTime = time.Unix(int64(req.EndTime), 0) - } - - if startTime.After(endTime) { - return nil, status.Error( - codes.InvalidArgument, - "start_time must be less than or equal to end_time", - ) - } - - if s.cfg.ForwardingAnalyzer == nil { - return nil, status.Error( - codes.Unavailable, - "forwarding analyzer is not configured", - ) - } - - liquidityFloor := req.LiquidityFloorSat - if liquidityFloor == 0 { - liquidityFloor = defaultLiquidityFloorSat - } - - uptimeThreshold := req.UptimeThreshold - if uptimeThreshold == 0 { - uptimeThreshold = defaultUptimeThreshold - } - - // Reject NaN explicitly: NaN comparisons are always false, so a bare - // range check would let it slip through. - if math.IsNaN(uptimeThreshold) || uptimeThreshold < 0 || - uptimeThreshold > 1 { - - return nil, status.Error( - codes.InvalidArgument, - "uptime_threshold must be in [0, 1]", - ) - } - - abilities, err := s.cfg.ForwardingAnalyzer.EffectiveUptime( - ctx, startTime, endTime, btcutil.Amount(liquidityFloor), - ) - if err != nil { - log.ErrorS( - ctx, "EffectiveUptime failed", err, - slog.Time("start_time", startTime), - slog.Time("end_time", endTime), - slog.Uint64("liquidity_floor_sat", liquidityFloor), - ) - - return nil, status.Errorf(codes.Internal, "failed to "+ - "calculate effective uptime: %v", err) - } - - // Convert the flat map into the nested map the codec expects, carrying - // the raw facts through unchanged. EffectiveUptime is truncated to - // whole seconds to match the second-granularity wire field. A pair with - // only sub-second qualifying uptime therefore reports zero uptime while - // still carrying its forwarded volume. - nested := make(map[string]map[string]frdrpc.ForwardingAbility) - for pair, ability := range abilities { - if _, ok := nested[pair.PeerIn]; !ok { - nested[pair.PeerIn] = - make(map[string]frdrpc.ForwardingAbility) - } - - nested[pair.PeerIn][pair.PeerOut] = frdrpc.ForwardingAbility{ - EffectiveUptimeS: int64( - ability.EffectiveUptime.Seconds(), - ), - ForwardedSat: int64(ability.ForwardedAmount), - } - } - - // Guard against returning data when the node itself was down for the - // window. If no pair held at least the threshold fraction of uptime, - // the response carries no signal and lowering the threshold to surface - // something would only inflate it, so fail loudly instead. - minUptimeS := frdrpc.MinQualifyingUptime( - uptimeThreshold, endTime.Unix()-startTime.Unix(), - ) - var qualifying int - for _, outMap := range nested { - for _, ability := range outMap { - if ability.EffectiveUptimeS >= minUptimeS { - qualifying++ - } - } - } - if qualifying == 0 { - return nil, status.Error(codes.FailedPrecondition, "no peer "+ - "pair met the uptime threshold over the window; the "+ - "node may have been offline") - } - - resp, err := frdrpc.EncodeForwardingAbility( - nested, startTime.Unix(), endTime.Unix(), uptimeThreshold, - ) - if err != nil { - log.ErrorS( - ctx, "EncodeForwardingAbility failed", err, - slog.Int("pairs", len(abilities)), - ) - - return nil, status.Errorf(codes.Internal, "failed to encode "+ - "forwarding ability: %v", err) - } - - return resp, nil -} diff --git a/frdrpcserver/forwarding_ability_test.go b/frdrpcserver/forwarding_ability_test.go deleted file mode 100644 index f842dc6..0000000 --- a/frdrpcserver/forwarding_ability_test.go +++ /dev/null @@ -1,299 +0,0 @@ -package frdrpcserver - -import ( - "context" - "errors" - "testing" - "time" - - "github.com/btcsuite/btcd/btcutil" - "github.com/lightninglabs/faraday/chanevents" - "github.com/lightninglabs/faraday/frdrpc" - "github.com/stretchr/testify/require" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -type mockForwardingAnalyzer struct { - effectiveUptimeFunc func(ctx context.Context, startTime, endTime time.Time, - liquidityFloor btcutil.Amount) ( - map[chanevents.PeerPair]chanevents.ForwardingAbility, error) -} - -func (m *mockForwardingAnalyzer) EffectiveUptime(ctx context.Context, startTime, - endTime time.Time, liquidityFloor btcutil.Amount) ( - map[chanevents.PeerPair]chanevents.ForwardingAbility, error) { - - return m.effectiveUptimeFunc(ctx, startTime, endTime, liquidityFloor) -} - -// TestForwardingAbility tests the ForwardingAbility RPC method, covering both -// successful and error cases. -func TestForwardingAbility(t *testing.T) { - const ( - peerIn = "02aaaabbbbcccc0000000000000000000000000000000000000000000000000001" - peerOut = "02aaaabbbbcccc0000000000000000000000000000000000000000000000000002" - ) - - // analyzerResult is the canned analyzer return for a case. A nil - // analyzerResult means the case leaves ForwardingAnalyzer unconfigured. - type analyzerResult func() ( - map[chanevents.PeerPair]chanevents.ForwardingAbility, error) - - tests := []struct { - name string - analyzer analyzerResult - req *frdrpc.ForwardingAbilityRequest - - // wantCode is the expected gRPC status; codes.OK denotes - // success. - wantCode codes.Code - - // check runs on success with the response and the floor the - // handler resolved and passed to the analyzer. - check func(t *testing.T, resp *frdrpc.ForwardingAbilityResponse, - gotFloor btcutil.Amount) - }{ - { - name: "encodes analyzer facts", - analyzer: func() ( - map[chanevents.PeerPair]chanevents.ForwardingAbility, - error) { - - return map[chanevents.PeerPair]chanevents.ForwardingAbility{ - { - PeerIn: peerIn, - PeerOut: peerOut, - }: { - EffectiveUptime: 90 * time.Second, - ForwardedAmount: 550, - }, - }, nil - }, - req: &frdrpc.ForwardingAbilityRequest{ - StartTime: 100, - EndTime: 200, - LiquidityFloorSat: 1000, - }, - wantCode: codes.OK, - check: func(t *testing.T, - resp *frdrpc.ForwardingAbilityResponse, - gotFloor btcutil.Amount) { - - // The explicit floor passes straight through. - require.Equal(t, btcutil.Amount(1000), gotFloor) - require.Len(t, resp.Peers, 2) - require.Len(t, resp.Entries, 1) - require.EqualValues(t, 100, resp.StartTime) - require.EqualValues(t, 200, resp.EndTime) - require.EqualValues( - t, 90, resp.Entries[0].EffectiveUptimeS, - ) - require.EqualValues( - t, 550, resp.Entries[0].ForwardedSat, - ) - - // An unset threshold echoes the server default, - // and a forwarded pair leaves the bitmask empty. - require.Equal( - t, defaultUptimeThreshold, - resp.UptimeThreshold, - ) - require.Empty(t, resp.UpButIdleBitmask) - }, - }, - { - name: "unset floor uses server default", - analyzer: func() ( - map[chanevents.PeerPair]chanevents.ForwardingAbility, - error) { - - // Return a fully-up pair so the node-down guard - // passes and the default floor can be observed. - return map[chanevents.PeerPair]chanevents.ForwardingAbility{ - {PeerIn: peerIn, PeerOut: peerOut}: { - EffectiveUptime: 100 * time.Second, - }, - }, nil - }, - req: &frdrpc.ForwardingAbilityRequest{ - StartTime: 100, - EndTime: 200, - }, - wantCode: codes.OK, - check: func(t *testing.T, - _ *frdrpc.ForwardingAbilityResponse, - gotFloor btcutil.Amount) { - - require.Equal( - t, btcutil.Amount( - defaultLiquidityFloorSat, - ), gotFloor, - ) - }, - }, - { - name: "node down trips guard", - analyzer: func() ( - map[chanevents.PeerPair]chanevents.ForwardingAbility, - error) { - - // A single pair, up well below the default 0.9 - // threshold over the 100s window and with no - // forwards, leaves nothing that clears it. - return map[chanevents.PeerPair]chanevents.ForwardingAbility{ - {PeerIn: peerIn, PeerOut: peerOut}: { - EffectiveUptime: 10 * time.Second, - }, - }, nil - }, - req: &frdrpc.ForwardingAbilityRequest{ - StartTime: 100, - EndTime: 200, - }, - wantCode: codes.FailedPrecondition, - }, - { - name: "low-uptime forward does not rescue guard", - analyzer: func() ( - map[chanevents.PeerPair]chanevents.ForwardingAbility, - error) { - - // Forwarded volume at sub-threshold uptime must - // not satisfy the guard. - return map[chanevents.PeerPair]chanevents.ForwardingAbility{ - {PeerIn: peerIn, PeerOut: peerOut}: { - EffectiveUptime: 10 * time.Second, - ForwardedAmount: 999, - }, - }, nil - }, - req: &frdrpc.ForwardingAbilityRequest{ - StartTime: 100, - EndTime: 200, - }, - wantCode: codes.FailedPrecondition, - }, - { - name: "explicit threshold flags up-but-idle pair", - analyzer: func() ( - map[chanevents.PeerPair]chanevents.ForwardingAbility, - error) { - - return map[chanevents.PeerPair]chanevents.ForwardingAbility{ - {PeerIn: peerIn, PeerOut: peerOut}: { - EffectiveUptime: 60 * time.Second, - }, - }, nil - }, - req: &frdrpc.ForwardingAbilityRequest{ - StartTime: 100, - EndTime: 200, - UptimeThreshold: 0.5, - }, - wantCode: codes.OK, - check: func(t *testing.T, - resp *frdrpc.ForwardingAbilityResponse, - _ btcutil.Amount) { - - // Up 60s of a 100s window at a 0.5 threshold: - // idle, so a bit and no entry. - require.Equal(t, 0.5, resp.UptimeThreshold) - require.Empty(t, resp.Entries) - require.NotEmpty(t, resp.UpButIdleBitmask) - }, - }, - { - name: "out of range threshold is rejected", - analyzer: func() ( - map[chanevents.PeerPair]chanevents.ForwardingAbility, - error) { - - return nil, nil - }, - req: &frdrpc.ForwardingAbilityRequest{ - StartTime: 100, - EndTime: 200, - UptimeThreshold: 1.5, - }, - wantCode: codes.InvalidArgument, - }, - { - name: "start after end is rejected", - req: &frdrpc.ForwardingAbilityRequest{ - StartTime: 200, - EndTime: 100, - }, - wantCode: codes.InvalidArgument, - }, - { - name: "missing analyzer is unavailable", - req: &frdrpc.ForwardingAbilityRequest{ - StartTime: 100, - EndTime: 200, - LiquidityFloorSat: 1000, - }, - wantCode: codes.Unavailable, - }, - { - name: "analyzer error is internal", - analyzer: func() ( - map[chanevents.PeerPair]chanevents.ForwardingAbility, - error) { - - return nil, errors.New("db lookup failed") - }, - req: &frdrpc.ForwardingAbilityRequest{ - StartTime: 100, - EndTime: 200, - LiquidityFloorSat: 1000, - }, - wantCode: codes.Internal, - }, - } - - for _, tc := range tests { - t.Run( - tc.name, - func(t *testing.T) { - var gotFloor btcutil.Amount - - cfg := &Config{} - if tc.analyzer != nil { - cfg.ForwardingAnalyzer = &mockForwardingAnalyzer{ - effectiveUptimeFunc: func( - _ context.Context, _, - _ time.Time, - floor btcutil.Amount) ( - map[chanevents.PeerPair]chanevents.ForwardingAbility, - error) { - - gotFloor = floor - - return tc.analyzer() - }, - } - } - - server := NewRPCServer(cfg) - resp, err := server.ForwardingAbility( - t.Context(), tc.req, - ) - - if tc.wantCode != codes.OK { - st, ok := status.FromError(err) - require.True(t, ok) - require.Equal(t, tc.wantCode, st.Code()) - - return - } - - require.NoError(t, err) - require.NotNil(t, resp) - if tc.check != nil { - tc.check(t, resp, gotFloor) - } - }, - ) - } -} diff --git a/frdrpcserver/getchanevents.go b/frdrpcserver/getchanevents.go deleted file mode 100644 index 9e26ac0..0000000 --- a/frdrpcserver/getchanevents.go +++ /dev/null @@ -1,148 +0,0 @@ -package frdrpcserver - -import ( - "context" - "errors" - "time" - - "github.com/btcsuite/btcd/btcutil" - "github.com/lightninglabs/faraday/chanevents" - "github.com/lightninglabs/faraday/frdrpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -// maxChannelEventsLimit is the hard cap the server will return in a single -// GetChannelEvents response, regardless of what the client asks for. It also -// serves as the default when the request leaves max_events at zero. -const maxChannelEventsLimit = 10000 - -// GetChannelEvents serves a paginated read of a channel's events. A zero -// end_time defaults to the server's current time, max_events is clamped to -// the server's hard cap, and an unknown channel point yields NotFound. -func (s *RPCServer) GetChannelEvents(ctx context.Context, - req *frdrpc.ChannelEventsRequest) (*frdrpc.ChannelEventsResponse, - error) { - - log.Debugf("[GetChannelEvents]: chan_point=%s, start_time=%d, "+ - "end_time=%d, max_events=%d, last_id=%d", req.ChanPoint, - req.StartTime, req.EndTime, req.MaxEvents, req.LastId) - - if req.ChanPoint == "" { - return nil, status.Error( - codes.InvalidArgument, "channel point required", - ) - } - - if req.StartTime < 0 || req.EndTime < 0 { - return nil, status.Error( - codes.InvalidArgument, - "start_time and end_time must be >= 0", - ) - } - - startTime := time.Unix(req.StartTime, 0) - endTime := time.Now() - if req.EndTime != 0 { - endTime = time.Unix(req.EndTime, 0) - } - - if startTime.After(endTime) { - return nil, status.Error( - codes.InvalidArgument, "start_time must be <= end_time", - ) - } - - if req.LastId < 0 { - return nil, status.Error( - codes.InvalidArgument, "last_id must be >= 0", - ) - } - - channel, err := s.cfg.ChanEvents.GetChannel(ctx, req.ChanPoint) - if err != nil { - if errors.Is(err, chanevents.ErrUnknownChannel) { - return nil, status.Errorf(codes.NotFound, "channel %s "+ - "not found", req.ChanPoint) - } - log.Errorf("GetChannel(%s): %v", req.ChanPoint, err) - - return nil, status.Error( - codes.Internal, "failed to look up channel", - ) - } - - limit := int32(maxChannelEventsLimit) - if req.MaxEvents != 0 && req.MaxEvents < maxChannelEventsLimit { - limit = int32(req.MaxEvents) - } - - events, err := s.cfg.ChanEvents.GetChannelEvents( - ctx, channel.ID, req.LastId, startTime, endTime, limit, - ) - if err != nil { - log.Errorf("GetChannelEvents(%s): %v", req.ChanPoint, err) - - return nil, status.Error( - codes.Internal, "failed to query channel events", - ) - } - - resp := &frdrpc.ChannelEventsResponse{ - Events: marshalRPCChannelEvents(events), - HasMore: int32(len(events)) == limit, - } - if n := len(events); n > 0 { - resp.LastId = events[n-1].ID - } - - return resp, nil -} - -// marshalRPCChannelEvents converts a slice of chanevents.ChannelEvent into a -// slice of frdrpc.ChannelEvent. -func marshalRPCChannelEvents( - events []*chanevents.ChannelEvent) []*frdrpc.ChannelEvent { - - rpcEvents := make([]*frdrpc.ChannelEvent, len(events)) - - for i, event := range events { - rpcEvent := &frdrpc.ChannelEvent{ - Id: event.ID, - Timestamp: event.Timestamp.Unix(), - EventType: rpcEventType(event.EventType), - } - - event.LocalBalance.WhenSome( - func(b btcutil.Amount) { - rpcEvent.LocalBalance = uint64(b) - }, - ) - event.RemoteBalance.WhenSome( - func(b btcutil.Amount) { - rpcEvent.RemoteBalance = uint64(b) - }, - ) - - rpcEvents[i] = rpcEvent - } - - return rpcEvents -} - -// rpcEventType maps a stored chanevents.EventType to its proto counterpart. -func rpcEventType(e chanevents.EventType) frdrpc.ChannelEventType { - switch e { - case chanevents.EventTypeOnline: - return frdrpc.ChannelEventType_CHAN_EVENT_ONLINE - - case chanevents.EventTypeOffline: - return frdrpc.ChannelEventType_CHAN_EVENT_OFFLINE - - case chanevents.EventTypeUpdate: - return frdrpc.ChannelEventType_CHAN_EVENT_UPDATE - - default: - return frdrpc.ChannelEventType_CHAN_EVENT_UNKNOWN - } -} diff --git a/frdrpcserver/log.go b/frdrpcserver/log.go index 9afc134..b44025a 100644 --- a/frdrpcserver/log.go +++ b/frdrpcserver/log.go @@ -1,7 +1,7 @@ package frdrpcserver import ( - "github.com/btcsuite/btclog/v2" + "github.com/btcsuite/btclog" "github.com/lightningnetwork/lnd/build" ) diff --git a/macaroons.go b/frdrpcserver/macaroons.go similarity index 97% rename from macaroons.go rename to frdrpcserver/macaroons.go index b66c8e0..71627b1 100644 --- a/macaroons.go +++ b/frdrpcserver/macaroons.go @@ -1,4 +1,4 @@ -package faraday +package frdrpcserver import ( "time" diff --git a/frdrpcserver/node_audit.go b/frdrpcserver/node_audit.go index 6a6551a..848ec0b 100644 --- a/frdrpcserver/node_audit.go +++ b/frdrpcserver/node_audit.go @@ -7,23 +7,14 @@ import ( "sort" "time" - "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/lightninglabs/faraday/accounting" "github.com/lightninglabs/faraday/fees" "github.com/lightninglabs/faraday/fiat" "github.com/lightninglabs/faraday/frdrpc" - "github.com/lightninglabs/lndclient" "github.com/lightningnetwork/lnd/routing/route" "github.com/shopspring/decimal" ) -// Since Bitcoin blocks are not guaranteed to be completely ordered -// by timestamp, and the timestamps can be manipulated by miners within a -// certain range, we will apply a buffer on the time range which we use to -// find start and end block heights. This should ensure we widen the block -// height range enough to fetch all relevant transactions within a time range. -const blockTimeRangeBuffer = time.Hour * 24 - var ( // ErrNoCategoryName is returned if a category does not have a name. ErrNoCategoryName = errors.New("category must have a name") @@ -93,21 +84,8 @@ func parseNodeAuditRequest(ctx context.Context, cfg *Config, "backend, some fee entries will be missing (see logs)") } - var blockRangeLookup func(start, end time.Time) (uint32, uint32, error) - - // If a time range is set, we will use a block height lookup function - // to find the block heights for the start and end time. - timeRangeSet := req.StartTime > 0 || req.EndTime > 0 - if timeRangeSet { - blockRangeLookup = func(start, end time.Time) (uint32, uint32, error) { - return resolveBlockHeightRange( - ctx, cfg.Lnd, info.BlockHeight, start, end, - ) - } - } - onChain := accounting.NewOnChainConfig( - ctx, cfg.Lnd, start, end, blockRangeLookup, req.DisableFiat, + ctx, cfg.Lnd, start, end, req.DisableFiat, feeLookup, priceSourceCfg, onChainCategories, ) @@ -300,129 +278,3 @@ func rpcEntryType(t accounting.EntryType) (frdrpc.EntryType, error) { return 0, fmt.Errorf("unknown entrytype: %v", t) } } - -// resolveBlockHeightRange determines the block height range that should be -// used for in queries based on the start and end time of the report. -// The function will apply a buffer to ensure the block height range is -// too large rather than too small, so that all relevant transactions are -// fetched from the backend. -func resolveBlockHeightRange(ctx context.Context, - lndClient lndclient.LndServices, latestHeight uint32, - startTime, endTime time.Time) (uint32, uint32, error) { - - // Apply a buffer on the start time which we use to find the block height. - // This should ensure we use a low enough height to fetch all relevant - // transactions following the start time. - bufferedStartTime := startTime.Add(-blockTimeRangeBuffer) - - if bufferedStartTime.Before(time.Unix(0, 0)) { - bufferedStartTime = time.Unix(0, 0) - } - - startHeight, err := findFirstBlockBeforeTimestamp( - ctx, lndClient, latestHeight, bufferedStartTime, - ) - if err != nil { - return 0, 0, err - } - - // Apply a buffer on the end time which we use to find the block height. - // This should ensure we use a high enough height to fetch all relevant - // transactions up to the end time. - bufferedEndTime := endTime.Add(blockTimeRangeBuffer) - - endHeight, err := findFirstBlockBeforeTimestamp( - ctx, lndClient, latestHeight, bufferedEndTime, - ) - if err != nil { - return 0, 0, err - } - - if startHeight > endHeight { - log.Errorf("Start height: %v is greater than end height: %v, "+ - "setting both to 0", startHeight, endHeight) - - // If startHeight somehow ended up being greater than endHeight, - // set both start and end height to 0, meaning we will query for - // all onchain history. - startHeight = 0 - endHeight = 0 - } - - return startHeight, endHeight, nil -} - -// findFirstBlockBeforeTimestamp finds the block height from just before the -// given timestamp. -func findFirstBlockBeforeTimestamp(ctx context.Context, - lndClient lndclient.LndServices, latestHeight uint32, - targetTime time.Time) (uint32, error) { - - targetTimestamp := targetTime.Unix() - - // Set the search range to the genesis block and the latest block. - low := uint32(0) - high := latestHeight - - // Perform binary search to find the block height that is just before the - // target timestamp. - for low <= high { - mid := (low + high) / 2 - - // Lookup the block in the middle of the search range. - blockHash, err := getBlockHash(ctx, lndClient, mid) - if err != nil { - return 0, err - } - - blockTime, err := getBlockTimestamp(ctx, lndClient, blockHash) - if err != nil { - return 0, err - } - - blockTimestamp := blockTime.Unix() - if blockTimestamp < targetTimestamp { - // If the block we looked up is before the target timestamp, - // we set the new low height to the next block after that. - low = mid + 1 - } else if blockTimestamp > targetTimestamp { - // If the block we looked up is after the target timestamp, - // we set the new high height to the block before that. - high = mid - 1 - } else { - // If we find an exact match of block timestamp and target - // timestamp, ruturn the height of this block. - return mid, nil - } - } - - log.Debugf("Binary search done for targetTimestamp: %v. "+ - "Returning height: %v", targetTimestamp, high) - - // Closest block before the timestamp. - return high, nil -} - -// getBlockHash retrieves the block hash for a given height. -func getBlockHash(ctx context.Context, lndClient lndclient.LndServices, - height uint32) (chainhash.Hash, error) { - - blockHash, err := lndClient.ChainKit.GetBlockHash(ctx, int64(height)) - if err != nil { - return chainhash.Hash{}, err - } - - return blockHash, nil -} - -// getBlockTimestamp retrieves the block timestamp for a given block hash. -func getBlockTimestamp(ctx context.Context, - lndClient lndclient.LndServices, hash chainhash.Hash) (time.Time, error) { - - blockHeader, err := lndClient.ChainKit.GetBlockHeader(ctx, hash) - if err != nil { - return time.Time{}, err - } - - return blockHeader.Timestamp, nil -} diff --git a/frdrpcserver/perms/perms.go b/frdrpcserver/perms/perms.go index 6e20801..fe95829 100644 --- a/frdrpcserver/perms/perms.go +++ b/frdrpcserver/perms/perms.go @@ -33,12 +33,4 @@ var RequiredPermissions = map[string][]bakery.Op{ Entity: "report", Action: "read", }}, - "/frdrpc.FaradayServer/GetChannelEvents": {{ - Entity: "events", - Action: "read", - }}, - "/frdrpc.FaradayServer/ForwardingAbility": {{ - Entity: "insights", - Action: "read", - }}, } diff --git a/frdrpcserver/rpcserver.go b/frdrpcserver/rpcserver.go index c0e7b12..c21e1d6 100644 --- a/frdrpcserver/rpcserver.go +++ b/frdrpcserver/rpcserver.go @@ -11,22 +11,54 @@ package frdrpcserver import ( "context" + "crypto/tls" "errors" - "time" + "fmt" + "net" + "net/http" + "strings" + "sync" + "sync/atomic" - "github.com/btcsuite/btcd/btcutil" + proxy "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/lightninglabs/faraday/accounting" "github.com/lightninglabs/faraday/chain" - "github.com/lightninglabs/faraday/chanevents" "github.com/lightninglabs/faraday/fiat" "github.com/lightninglabs/faraday/frdrpc" + "github.com/lightninglabs/faraday/frdrpcserver/perms" "github.com/lightninglabs/faraday/recommend" "github.com/lightninglabs/faraday/resolutions" "github.com/lightninglabs/faraday/revenue" "github.com/lightninglabs/lndclient" + "github.com/lightningnetwork/lnd/kvdb" + "github.com/lightningnetwork/lnd/lncfg" + "github.com/lightningnetwork/lnd/macaroons" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "google.golang.org/protobuf/encoding/protojson" + "gopkg.in/macaroon-bakery.v2/bakery" ) var ( + // customMarshalerOption is the configuratino we use for the JSON + // marshaler of the REST proxy. The default JSON marshaler only sets + // OrigName to true, which instructs it to use the same field names as + // specified in the proto file and not switch to camel case. What we + // also want is that the marshaler prints all values, even if they are + // falsey. + customMarshalerOption = proxy.WithMarshalerOption( + proxy.MIMEWildcard, &proxy.JSONPb{ + MarshalOptions: protojson.MarshalOptions{ + UseProtoNames: true, + EmitUnpopulated: true, + }, + }, + ) + + // maxMsgRecvSize is the largest message our REST proxy will receive. We + // set this to 200MiB atm. + maxMsgRecvSize = grpc.MaxCallRecvMsgSize(1 * 1024 * 1024 * 200) + // maxInvoiceQueries is the maximum number of invoices we request from // lnd at a time. maxInvoiceQueries = 1000 @@ -41,6 +73,10 @@ var ( // because forwards have less data. maxForwardQueries = 2000 + // errServerAlreadyStarted is the error that is returned if the server + // is requested to start while it's already been started. + errServerAlreadyStarted = fmt.Errorf("server can only be started once") + // ErrBitcoinNodeRequired is required when an endpoint which requires // a bitcoin node backend is hit and we are not connected to one. ErrBitcoinNodeRequired = errors.New("bitcoin node required") @@ -48,20 +84,35 @@ var ( // RPCServer implements the faraday service, serving requests over grpc. type RPCServer struct { + // To be used atomically. + started int32 + + // To be used atomically. + stopped int32 + // Required by the grpc-gateway/v2 library for forward compatibility. + // Must be after the atomically used variables to not break struct + // alignment. frdrpc.UnimplementedFaradayServerServer // cfg contains closures and settings required for operation. cfg *Config -} -// ForwardingAnalyzer is the seam the RPC server uses to compute per-peer-pair -// forwarding facts. It is an interface so the handler can be exercised against -// a mock analyzer in tests. -type ForwardingAnalyzer interface { - EffectiveUptime(ctx context.Context, startTime, endTime time.Time, - liquidityFloor btcutil.Amount) ( - map[chanevents.PeerPair]chanevents.ForwardingAbility, error) + // grpcServer is the main gRPC RPCServer that this RPC server will + // register itself with and accept client requests from. + grpcServer *grpc.Server + + // rpcListener is the listener to use when starting the gRPC server. + rpcListener net.Listener + + // restServer is the REST proxy server. + restServer *http.Server + + macaroonService *lndclient.MacaroonService + macaroonDB kvdb.Backend + + restCancel func() + wg sync.WaitGroup } // Config provides closures and settings required to run the rpc server. @@ -69,27 +120,322 @@ type Config struct { // Lnd is a client which can be used to query lnd. Lnd lndclient.LndServices - // ChanEvents is a database of channel events. - ChanEvents *chanevents.Store + // RPCListen is the address:port that the gRPC server should listen on. + RPCListen string - // ForwardingAnalyzer computes forwarding-ability facts for the - // ForwardingAbility RPC. When nil, that endpoint returns - // codes.Unavailable. - ForwardingAnalyzer ForwardingAnalyzer + // RESTListen is the address:port that the REST server should listen on. + RESTListen string - // BitcoinClient is an optional client which can be used to query - // on-chain data from a connected bitcoin node. If nil, faraday will - // not be able to serve endpoints which require on-chain data. + // CORSOrigin specifies the CORS header that should be set on REST + // responses. No header is added if the value is empty. + CORSOrigin string + + // BitcoinClient is set if the client opted to connect to a bitcoin + // backend, if not, it will be nil. BitcoinClient chain.BitcoinClient + + // TLSServerConfig is the configuration to serve a secure connection + // over TLS. + TLSServerConfig *tls.Config + + // RestClientConfig is the client configuration to connect to a TLS + // server started with the TLS config above. This is used for the REST + // proxy that connects internally to the gRPC server and therefore is a + // TLS client. + RestClientConfig *credentials.TransportCredentials + + // FaradayDir is the main directory faraday uses. The macaroon database + // will be created there. + FaradayDir string + + // MacaroonPath is the full path to the default faraday macaroon file + // that is created automatically. This path normally is within + // FaradayDir unless otherwise specified by the user. + MacaroonPath string } -// NewRPCServer returns a new RPCServer backed by the given config. +// NewRPCServer returns a server which will listen for rpc requests on the +// rpc listen address provided. Note that the server returned is not running, +// and should be started using Start(). func NewRPCServer(cfg *Config) *RPCServer { return &RPCServer{ cfg: cfg, } } +// Start starts the listener and server. +func (s *RPCServer) Start() error { + if atomic.AddInt32(&s.started, 1) != 1 { + return errServerAlreadyStarted + } + + // Depending on how far we got in initializing the server, we might need + // to clean up certain services that were already started. Keep track of + // them with this map of service name to shutdown function. + shutdownFuncs := make(map[string]func() error) + defer func() { + for serviceName, shutdownFn := range shutdownFuncs { + if err := shutdownFn(); err != nil { + log.Errorf("Error shutting down %s service: %v", + serviceName, err) + } + } + }() + + // Set up the macaroon service. + rks, db, err := lndclient.NewBoltMacaroonStore( + s.cfg.FaradayDir, lncfg.MacaroonDBName, macDatabaseOpenTimeout, + ) + if err != nil { + return err + } + shutdownFuncs["macaroondb"] = db.Close + + s.macaroonDB = db + s.macaroonService, err = lndclient.NewMacaroonService( + &lndclient.MacaroonServiceConfig{ + RootKeyStore: rks, + MacaroonLocation: faradayMacaroonLocation, + MacaroonPath: s.cfg.MacaroonPath, + Checkers: []macaroons.Checker{ + macaroons.IPLockChecker, + }, + RequiredPerms: perms.RequiredPermissions, + DBPassword: macDbDefaultPw, + LndClient: &s.cfg.Lnd, + EphemeralKey: lndclient.SharedKeyNUMS, + KeyLocator: lndclient.SharedKeyLocator, + }, + ) + if err != nil { + return fmt.Errorf("error creating macroon service: %v", err) + } + + // Start the macaroon service and let it create its default macaroon in + // case it doesn't exist yet. + if err := s.macaroonService.Start(); err != nil { + return fmt.Errorf("error starting macaroon service: %v", err) + } + shutdownFuncs["macaroon"] = s.macaroonService.Stop + + // First we add the security interceptor to our gRPC server options that + // checks the macaroons for validity. + unaryInterceptor, streamInterceptor, err := s.macaroonService.Interceptors() + if err != nil { + return fmt.Errorf("error with macaroon interceptor: %v", err) + } + + // Add our TLS configuration and then create our server instance. It's + // important that we let gRPC create the TLS listener and we don't just + // use tls.NewListener(). Otherwise we run into the ALPN error with non- + // golang clients. + tlsCredentials := credentials.NewTLS(s.cfg.TLSServerConfig) + s.grpcServer = grpc.NewServer( + grpc.UnaryInterceptor(unaryInterceptor), + grpc.StreamInterceptor(streamInterceptor), + grpc.Creds(tlsCredentials), + ) + + // Start the gRPC RPCServer listening for HTTP/2 connections. + log.Info("Starting gRPC listener") + s.rpcListener, err = net.Listen("tcp", s.cfg.RPCListen) + if err != nil { + return fmt.Errorf("RPC RPCServer unable to listen on %v", + s.cfg.RPCListen) + } + shutdownFuncs["gRPC listener"] = s.rpcListener.Close + log.Infof("gRPC server listening on %s", s.rpcListener.Addr()) + + frdrpc.RegisterFaradayServerServer(s.grpcServer, s) + + // We'll also create and start an accompanying proxy to serve clients + // through REST. An empty address indicates REST is disabled. + if s.cfg.RESTListen != "" { + log.Infof("Starting REST proxy listener ") + restListener, err := net.Listen("tcp", s.cfg.RESTListen) + if err != nil { + return fmt.Errorf("REST server unable to listen on "+ + "%v: %v", s.cfg.RESTListen, err) + } + restListener = tls.NewListener( + restListener, s.cfg.TLSServerConfig, + ) + shutdownFuncs["REST listener"] = restListener.Close + log.Infof("REST server listening on %s", restListener.Addr()) + + // We'll dial into the local gRPC server so we need to set some + // gRPC dial options and CORS settings. + var restCtx context.Context + restCtx, s.restCancel = context.WithCancel(context.Background()) + mux := proxy.NewServeMux(customMarshalerOption) + var restHandler http.Handler = mux + if s.cfg.CORSOrigin != "" { + restHandler = allowCORS(restHandler, s.cfg.CORSOrigin) + } + proxyOpts := []grpc.DialOption{ + grpc.WithTransportCredentials(*s.cfg.RestClientConfig), + grpc.WithDefaultCallOptions(maxMsgRecvSize), + } + + // With TLS enabled by default, we cannot call 0.0.0.0 + // internally from the REST proxy as that IP address isn't in + // the cert. We need to rewrite it to the loopback address. + restProxyDest := s.cfg.RPCListen + switch { + case strings.Contains(restProxyDest, "0.0.0.0"): + restProxyDest = strings.Replace( + restProxyDest, "0.0.0.0", "127.0.0.1", 1, + ) + + case strings.Contains(restProxyDest, "[::]"): + restProxyDest = strings.Replace( + restProxyDest, "[::]", "[::1]", 1, + ) + } + err = frdrpc.RegisterFaradayServerHandlerFromEndpoint( + restCtx, mux, restProxyDest, proxyOpts, + ) + if err != nil { + return err + } + s.restServer = &http.Server{Handler: restHandler} + + s.wg.Add(1) + go func() { + defer s.wg.Done() + err := s.restServer.Serve(restListener) + // ErrServerClosed is always returned when the proxy is + // shut down, so don't log it. + if err != nil && err != http.ErrServerClosed { + log.Error(err) + } + }() + } else { + log.Infof("REST proxy disabled") + } + + s.wg.Add(1) + go func() { + defer s.wg.Done() + if err := s.grpcServer.Serve(s.rpcListener); err != nil { + log.Errorf("could not serve grpc server: %v", err) + } + }() + + // If we got here successfully, there's no need to shutdown anything + // anymore. + shutdownFuncs = nil + + return nil +} + +// StartAsSubserver is an alternative to Start where the RPC server does not +// create its own gRPC server but registers to an existing one. The same goes +// for REST (if enabled), instead of creating an own mux and HTTP server, we +// register to an existing one. +func (s *RPCServer) StartAsSubserver(lndClient lndclient.LndServices, + withMacaroonService bool) error { + + if atomic.AddInt32(&s.started, 1) != 1 { + return errServerAlreadyStarted + } + + if withMacaroonService { + // Set up the macaroon service. + rks, db, err := lndclient.NewBoltMacaroonStore( + s.cfg.FaradayDir, lncfg.MacaroonDBName, + macDatabaseOpenTimeout, + ) + if err != nil { + return err + } + + s.macaroonDB = db + s.macaroonService, err = lndclient.NewMacaroonService( + &lndclient.MacaroonServiceConfig{ + RootKeyStore: rks, + MacaroonLocation: faradayMacaroonLocation, + MacaroonPath: s.cfg.MacaroonPath, + Checkers: []macaroons.Checker{ + macaroons.IPLockChecker, + }, + RequiredPerms: perms.RequiredPermissions, + DBPassword: macDbDefaultPw, + LndClient: &lndClient, + EphemeralKey: lndclient.SharedKeyNUMS, + KeyLocator: lndclient.SharedKeyLocator, + }, + ) + if err != nil { + return fmt.Errorf("error creating macroon service: %v", + err) + } + + // Start the macaroon service and let it create its default + // macaroon in case it doesn't exist yet. + if err := s.macaroonService.Start(); err != nil { + return fmt.Errorf("error starting macaroon service: %v", + err) + } + } + + s.cfg.Lnd = lndClient + return nil +} + +// ValidateMacaroon extracts the macaroon from the context's gRPC metadata, +// checks its signature, makes sure all specified permissions for the called +// method are contained within and finally ensures all caveat conditions are +// met. A non-nil error is returned if any of the checks fail. This method is +// needed to enable faraday running as an external subserver in the same process +// as lnd but still validate its own macaroons. +func (s *RPCServer) ValidateMacaroon(ctx context.Context, + requiredPermissions []bakery.Op, fullMethod string) error { + + if s.macaroonService == nil { + return fmt.Errorf("macaroon service not yet initialised") + } + + // Delegate the call to faraday's own macaroon validator service. + return s.macaroonService.ValidateMacaroon( + ctx, requiredPermissions, fullMethod, + ) +} + +// Stop stops the grpc listener and server. +func (s *RPCServer) Stop() error { + if atomic.AddInt32(&s.stopped, 1) != 1 { + return nil + } + + if s.restServer != nil { + s.restCancel() + err := s.restServer.Close() + if err != nil { + log.Errorf("unable to close REST listener: %v", err) + } + } + + if s.macaroonService != nil { + if err := s.macaroonService.Stop(); err != nil { + log.Errorf("Error stopping macaroon service: %v", err) + } + } + if s.macaroonDB != nil { + if err := s.macaroonDB.Close(); err != nil { + log.Errorf("Error closing macaroon DB: %v", err) + } + } + + // Stop the grpc server and wait for all go routines to terminate. + if s.grpcServer != nil { + s.grpcServer.Stop() + } + s.wg.Wait() + + return nil +} + // OutlierRecommendations provides a set of close recommendations for the // current set of open channels based on whether they are outliers. func (s *RPCServer) OutlierRecommendations(ctx context.Context, @@ -244,3 +590,12 @@ func (s *RPCServer) requireNode() error { return nil } + +// allowCORS wraps the given http.Handler with a function that adds the +// Access-Control-Allow-Origin header to the response. +func allowCORS(handler http.Handler, origin string) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Access-Control-Allow-Origin", origin) + handler.ServeHTTP(w, r) + }) +} diff --git a/go.mod b/go.mod index 2983ed7..b225c5b 100644 --- a/go.mod +++ b/go.mod @@ -1,199 +1,164 @@ module github.com/lightninglabs/faraday require ( - github.com/btcsuite/btcd v0.25.1-0.20260310163610-1c55c7c18179 - github.com/btcsuite/btcd/btcutil v1.1.6 - github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 - github.com/btcsuite/btclog/v2 v2.0.1-0.20250728225537-6090e87c6c5b - github.com/golang-migrate/migrate/v4 v4.19.0 - github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 - github.com/jarcoal/httpmock v1.4.0 - github.com/jessevdk/go-flags v1.6.1 - github.com/lightninglabs/faraday/frdrpc v1.0.1 - github.com/lightninglabs/lndclient v0.21.0-1 - github.com/lightningnetwork/lnd v0.21.0-beta - github.com/lightningnetwork/lnd/cert v1.2.2 - github.com/lightningnetwork/lnd/clock v1.1.1 - github.com/lightningnetwork/lnd/fn/v2 v2.0.9 - github.com/lightningnetwork/lnd/kvdb v1.4.16 - github.com/lightningnetwork/lnd/sqldb/v2 v2.0.0-20260326184657-f7cc56305bae + github.com/btcsuite/btcd v0.23.5-0.20230125025938-be056b0a0b2f + github.com/btcsuite/btcd/btcutil v1.1.3 + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 + github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f + github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0 + github.com/jessevdk/go-flags v1.4.0 + github.com/lightninglabs/lndclient v0.16.0-10 + github.com/lightninglabs/protobuf-hex-display v1.4.3-hex-display + github.com/lightningnetwork/lnd v0.16.0-beta + github.com/lightningnetwork/lnd/cert v1.2.1 + github.com/lightningnetwork/lnd/kvdb v1.4.1 github.com/shopspring/decimal v1.2.0 - github.com/stretchr/testify v1.11.1 - github.com/urfave/cli v1.22.14 - google.golang.org/grpc v1.79.3 - google.golang.org/protobuf v1.36.10 + github.com/stretchr/testify v1.8.1 + github.com/urfave/cli v1.22.9 + google.golang.org/grpc v1.41.0 + google.golang.org/protobuf v1.27.1 gopkg.in/macaroon-bakery.v2 v2.0.1 gopkg.in/macaroon.v2 v2.1.0 - modernc.org/sqlite v1.38.2 ) require ( - dario.cat/mergo v1.0.2 // indirect - github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect github.com/aead/siphash v1.0.1 // indirect + github.com/andybalholm/brotli v1.0.3 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/btcsuite/btcd/btcec/v2 v2.3.6 // indirect - github.com/btcsuite/btcd/btcutil/psbt v1.1.10 // indirect - github.com/btcsuite/btcd/v2transport v1.0.1 // indirect - github.com/btcsuite/btclog v1.0.0 // indirect - github.com/btcsuite/btcwallet v0.16.18 // indirect - github.com/btcsuite/btcwallet/wallet/txauthor v1.3.5 // indirect - github.com/btcsuite/btcwallet/wallet/txrules v1.2.2 // indirect - github.com/btcsuite/btcwallet/wallet/txsizes v1.2.5 // indirect - github.com/btcsuite/btcwallet/walletdb v1.5.1 // indirect - github.com/btcsuite/btcwallet/wtxmgr v1.5.6 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect + github.com/btcsuite/btcd/btcutil/psbt v1.1.5 // indirect + github.com/btcsuite/btcwallet v0.16.7 // indirect + github.com/btcsuite/btcwallet/wallet/txauthor v1.3.2 // indirect + github.com/btcsuite/btcwallet/wallet/txrules v1.2.0 // indirect + github.com/btcsuite/btcwallet/wallet/txsizes v1.2.3 // indirect + github.com/btcsuite/btcwallet/walletdb v1.4.0 // indirect + github.com/btcsuite/btcwallet/wtxmgr v1.5.0 // indirect github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect github.com/btcsuite/winsvc v1.0.0 // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // indirect - github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/containerd/continuity v0.3.0 // indirect + github.com/cenkalti/backoff/v4 v4.1.1 // indirect + github.com/cespare/xxhash/v2 v2.1.1 // indirect github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect - github.com/coreos/go-systemd/v22 v22.5.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect + github.com/coreos/go-systemd/v22 v22.3.2 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/decred/dcrd/crypto/blake256 v1.1.0 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect - github.com/decred/dcrd/lru v1.1.2 // indirect - github.com/docker/cli v28.1.1+incompatible // indirect - github.com/docker/docker v28.3.3+incompatible // indirect - github.com/docker/go-connections v0.5.0 // indirect - github.com/docker/go-units v0.5.0 // indirect - github.com/dustin/go-humanize v1.0.1 // indirect - github.com/fergusstrange/embedded-postgres v1.25.0 // indirect - github.com/go-logr/logr v1.4.3 // indirect - github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-viper/mapstructure/v2 v2.4.0 // indirect + github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/decred/dcrd/lru v1.0.0 // indirect + github.com/dsnet/compress v0.0.1 // indirect + github.com/dustin/go-humanize v1.0.0 // indirect + github.com/fergusstrange/embedded-postgres v1.10.0 // indirect + github.com/go-errors/errors v1.0.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.5.2 // indirect - github.com/golang/protobuf v1.5.4 // indirect + github.com/golang-jwt/jwt/v4 v4.4.2 // indirect + github.com/golang/protobuf v1.5.2 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.0.1 // indirect - github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/gorilla/websocket v1.5.0 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/websocket v1.4.2 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect - github.com/jackc/pgconn v1.14.3 // indirect - github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438 // indirect + github.com/jackc/pgconn v1.10.0 // indirect github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgproto3/v2 v2.3.3 // indirect - github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect - github.com/jackc/pgtype v1.14.4 // indirect - github.com/jackc/pgx/v4 v4.18.3 // indirect - github.com/jackc/pgx/v5 v5.9.2 // indirect - github.com/jackc/puddle/v2 v2.2.2 // indirect + github.com/jackc/pgproto3/v2 v2.1.1 // indirect + github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect + github.com/jackc/pgtype v1.8.1 // indirect + github.com/jackc/pgx/v4 v4.13.0 // indirect github.com/jonboulle/clockwork v0.2.2 // indirect - github.com/jrick/logrotate v1.1.2 // indirect - github.com/json-iterator/go v1.1.12 // indirect + github.com/jrick/logrotate v1.0.0 // indirect + github.com/json-iterator/go v1.1.11 // indirect github.com/juju/loggo v0.0.0-20210728185423-eebad3a902c4 // 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.17.9 // indirect - github.com/lib/pq v1.10.9 // indirect + github.com/klauspost/compress v1.13.6 // 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 - github.com/lightninglabs/neutrino v0.17.1 // indirect - github.com/lightninglabs/neutrino/cache v1.1.3 // indirect - github.com/lightningnetwork/lightning-onion v1.3.0 // indirect - github.com/lightningnetwork/lnd/actor v0.0.6 // indirect - github.com/lightningnetwork/lnd/healthcheck v1.2.6 // indirect - github.com/lightningnetwork/lnd/queue v1.2.0 // indirect - github.com/lightningnetwork/lnd/sqldb v1.0.13 // indirect - github.com/lightningnetwork/lnd/ticker v1.1.1 // indirect - github.com/lightningnetwork/lnd/tlv v1.3.2 // indirect - github.com/lightningnetwork/lnd/tor v1.1.6 // indirect + github.com/lightninglabs/neutrino v0.15.0 // indirect + github.com/lightninglabs/neutrino/cache v1.1.1 // indirect + 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/lightningnetwork/lnd/tor v1.1.0 // indirect github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-isatty v0.0.16 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/mholt/archiver/v3 v3.5.0 // indirect github.com/miekg/dns v1.1.43 // indirect - github.com/moby/docker-image-spec v1.3.1 // indirect - github.com/moby/sys/user v0.3.0 // indirect - github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/ncruces/go-strftime v0.1.9 // indirect - github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.1.0 // indirect - github.com/opencontainers/runc v1.2.8 // indirect - github.com/ory/dockertest/v3 v3.10.0 // indirect - github.com/pkg/errors v0.9.1 // indirect + github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/nwaples/rardecode v1.1.2 // indirect + github.com/pierrec/lz4/v4 v4.1.8 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.11.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.26.0 // indirect github.com/prometheus/procfs v0.6.0 // indirect - github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect github.com/rogpeppe/fastuuid v1.2.0 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sirupsen/logrus v1.9.3 // indirect + github.com/russross/blackfriday/v2 v2.0.1 // indirect + github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect + github.com/sirupsen/logrus v1.7.0 // indirect github.com/soheilhy/cmux v0.1.5 // indirect - github.com/spf13/pflag v1.0.6 // indirect - github.com/stretchr/objx v0.5.2 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/stretchr/objx v0.5.0 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect - github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect - github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect - github.com/xeipuuv/gojsonschema v1.2.0 // indirect + github.com/ulikunitz/xz v0.5.10 // indirect + github.com/xdg-go/stringprep v1.0.3 // indirect github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect - go.etcd.io/bbolt v1.4.3 // indirect - go.etcd.io/etcd/api/v3 v3.5.12 // indirect - go.etcd.io/etcd/client/pkg/v3 v3.5.12 // indirect - go.etcd.io/etcd/client/v2 v2.305.12 // indirect - go.etcd.io/etcd/client/v3 v3.5.12 // indirect - go.etcd.io/etcd/pkg/v3 v3.5.12 // indirect - go.etcd.io/etcd/raft/v3 v3.5.12 // indirect - go.etcd.io/etcd/server/v3 v3.5.12 // indirect - go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect - go.opentelemetry.io/otel v1.40.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0 // indirect - go.opentelemetry.io/otel/metric v1.40.0 // indirect - go.opentelemetry.io/otel/sdk v1.40.0 // indirect - go.opentelemetry.io/otel/trace v1.40.0 // indirect - go.opentelemetry.io/proto/otlp v1.3.1 // indirect - go.uber.org/atomic v1.10.0 // indirect + go.etcd.io/bbolt v1.3.6 // indirect + go.etcd.io/etcd/api/v3 v3.5.7 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.5.7 // indirect + go.etcd.io/etcd/client/v2 v2.305.7 // indirect + go.etcd.io/etcd/client/v3 v3.5.7 // indirect + go.etcd.io/etcd/pkg/v3 v3.5.7 // indirect + 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/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/proto/otlp v0.9.0 // indirect + go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.17.0 // indirect - golang.org/x/crypto v0.46.0 // indirect - golang.org/x/exp v0.0.0-20250811191247-51f88131bc50 // indirect - golang.org/x/net v0.48.0 // indirect - golang.org/x/sync v0.19.0 // indirect - golang.org/x/sys v0.40.0 // indirect - golang.org/x/term v0.38.0 // indirect - golang.org/x/text v0.32.0 // indirect - golang.org/x/time v0.5.0 // indirect - google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect + golang.org/x/crypto v0.1.0 // indirect + golang.org/x/exp v0.0.0-20221111094246-ab4555d3164f // indirect + golang.org/x/mod v0.6.0 // indirect + golang.org/x/net v0.7.0 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/term v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect + golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect + golang.org/x/tools v0.2.0 // indirect + google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced // indirect gopkg.in/errgo.v1 v1.0.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - modernc.org/libc v1.66.3 // indirect - modernc.org/mathutil v1.7.1 // indirect - modernc.org/memory v1.11.0 // indirect - pgregory.net/rapid v1.2.0 // indirect + lukechampine.com/uint128 v1.2.0 // indirect + modernc.org/cc/v3 v3.40.0 // indirect + modernc.org/ccgo/v3 v3.16.13 // indirect + modernc.org/libc v1.22.2 // indirect + modernc.org/mathutil v1.5.0 // indirect + modernc.org/memory v1.4.0 // indirect + modernc.org/opt v0.1.3 // indirect + modernc.org/sqlite v1.20.3 // indirect + modernc.org/strutil v1.1.3 // indirect + modernc.org/token v1.0.1 // indirect sigs.k8s.io/yaml v1.2.0 // indirect ) -// We want to format raw bytes as hex instead of base64. The forked version -// allows us to specify that as an option. -replace google.golang.org/protobuf => github.com/lightninglabs/protobuf-go-hex-display v1.30.0-hex-display - -// We are using a fork of the migration library. -replace github.com/golang-migrate/migrate/v4 => github.com/lightninglabs/migrate/v4 v4.18.2-9023d66a-fork-pr-2.0.20251211093704-71c1eef09789 - -// We need to replace frdrpc locally until we have this PR merged. -replace github.com/lightninglabs/faraday/frdrpc => ./frdrpc - -go 1.25.10 +go 1.19 diff --git a/go.sum b/go.sum index 47219d2..1b83d31 100644 --- a/go.sum +++ b/go.sum @@ -1,18 +1,43 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= -dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0 h1:Dg9iHVQfrhq82rUNu9ZxUDrJLaxFUe/HlCVaLyRruq8= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY= github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA= github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= @@ -22,6 +47,9 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +github.com/andybalholm/brotli v1.0.3 h1:fpcw+r1N1h0Poc1F/pHbW40cUm/lMEQslZtCkBQ0UnM= +github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -29,45 +57,46 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= -github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= -github.com/btcsuite/btcd v0.24.2/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg= -github.com/btcsuite/btcd v0.25.1-0.20260310163610-1c55c7c18179 h1:yJOTxkbxxtuSFrErMqYRvqZLfWggHssioBiWebkV9yo= -github.com/btcsuite/btcd v0.25.1-0.20260310163610-1c55c7c18179/go.mod h1:qbPE+pEiR9643E1s1xu57awsRhlCIm1ZIi6FfeRA4KE= +github.com/btcsuite/btcd v0.22.0-beta.0.20220204213055-eaf0459ff879/go.mod h1:osu7EoKiL36UThEgzYPqdRaxeo0NU8VoXqgcnwpey0g= +github.com/btcsuite/btcd v0.22.0-beta.0.20220207191057-4dc4ff7963b4/go.mod h1:7alexyj/lHlOtr2PJK7L/+HDJZpcGDn/pAU98r7DY08= +github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= +github.com/btcsuite/btcd v0.23.1/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= +github.com/btcsuite/btcd v0.23.3/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= +github.com/btcsuite/btcd v0.23.5-0.20230125025938-be056b0a0b2f h1:UJ/S/pV25+YsK0CJRJh8RDpTgy5h1oXWjOd4fp+opvY= +github.com/btcsuite/btcd v0.23.5-0.20230125025938-be056b0a0b2f/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= +github.com/btcsuite/btcd/btcec/v2 v2.1.1/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= -github.com/btcsuite/btcd/btcec/v2 v2.3.6 h1:IzlsEr9olcSRKB/n7c4351F3xHKxS2lma+1UFGCYd4E= -github.com/btcsuite/btcd/btcec/v2 v2.3.6/go.mod h1:m22FrOAiuxl/tht9wIqAoGHcbnCCaPWyauO8y2LGGtQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= +github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= -github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= -github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c= -github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= -github.com/btcsuite/btcd/btcutil/psbt v1.1.10 h1:TC1zhxhFfhnGqoPjsrlEpoqzh+9TPOHrCgnPR47Mj9I= -github.com/btcsuite/btcd/btcutil/psbt v1.1.10/go.mod h1:ehBEvU91lxSlXtA+zZz3iFYx7Yq9eqnKx4/kSrnsvMY= +github.com/btcsuite/btcd/btcutil v1.1.1/go.mod h1:nbKlBMNm9FGsdvKvu0essceubPiAcI57pYBNnsLAa34= +github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= +github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= +github.com/btcsuite/btcd/btcutil/psbt v1.1.5 h1:x0ZRrYY8j75ThV6xBz86CkYAG82F5bzay4H5D1c8b/U= +github.com/btcsuite/btcd/btcutil/psbt v1.1.5/go.mod h1:kA6FLH/JfUx++j9pYU0pyu+Z8XGBQuuTmuKYUf6q7/U= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= -github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btcd/v2transport v1.0.1 h1:pIyyyBCPwd087K3Wdb/9tIvUubAQdzTJghjPgzTQVsE= -github.com/btcsuite/btcd/v2transport v1.0.1/go.mod h1:N6H0HGSElVVJKntzaYHYVbW71DtWDLMw2yhwVRO3ZOE= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 h1:KdUfX2zKommPRa+PD0sWZUyXe9w277ABlgELO7H04IM= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btclog v1.0.0 h1:sEkpKJMmfGiyZjADwEIgB1NSwMyfdD1FB8v6+w1T0Ns= -github.com/btcsuite/btclog v1.0.0/go.mod h1:w7xnGOhwT3lmrS4H3b/D1XAXxvh+tbhUm8xeHN2y3TQ= -github.com/btcsuite/btclog/v2 v2.0.1-0.20250728225537-6090e87c6c5b h1:MQ+Q6sDy37V1wP1Yu79A5KqJutolqUGwA99UZWQDWZM= -github.com/btcsuite/btclog/v2 v2.0.1-0.20250728225537-6090e87c6c5b/go.mod h1:XItGUfVOxotJL8kkuk2Hj3EVow5KCugXl3wWfQ6K0AE= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcwallet v0.16.18 h1:6h0kMxij4igPu35jOPAWZbn22ceOC4me4L3jj8Za6Zk= -github.com/btcsuite/btcwallet v0.16.18/go.mod h1:4TTru0cgIPbCZpY4aRfAVwX87zrQw4GXM8MH6+A5xZw= -github.com/btcsuite/btcwallet/wallet/txauthor v1.3.5 h1:Rr0njWI3r341nhSPesKQ2JF+ugDSzdPoeckS75SeDZk= -github.com/btcsuite/btcwallet/wallet/txauthor v1.3.5/go.mod h1:+tXJ3Ym0nlQc/iHSwW1qzjmPs3ev+UVWMbGgfV1OZqU= -github.com/btcsuite/btcwallet/wallet/txrules v1.2.2 h1:YEO+Lx1ZJJAtdRrjuhXjWrYsmAk26wLTlNzxt2q0lhk= -github.com/btcsuite/btcwallet/wallet/txrules v1.2.2/go.mod h1:4v+grppsDpVn91SJv+mZT7B8hEV4nSmpREM4I8Uohws= -github.com/btcsuite/btcwallet/wallet/txsizes v1.2.5 h1:93o5Xz9dYepBP4RMFUc9RGIFXwqP2volSWRkYJFrNtI= -github.com/btcsuite/btcwallet/wallet/txsizes v1.2.5/go.mod h1:lQ+e9HxZ85QP7r3kdxItkiMSloSLg1PEGis5o5CXUQw= -github.com/btcsuite/btcwallet/walletdb v1.5.1 h1:HgMhDNCrtEFPC+8q0ei5DQ5U9Tl4RCspA22DEKXlopI= -github.com/btcsuite/btcwallet/walletdb v1.5.1/go.mod h1:jk/hvpLFINF0C1kfTn0bfx2GbnFT+Nvnj6eblZALfjs= -github.com/btcsuite/btcwallet/wtxmgr v1.5.6 h1:Zwvr/rrJYdOLqdBCSr4eICEstnEA+NBUvjIWLkrXaYI= -github.com/btcsuite/btcwallet/wtxmgr v1.5.6/go.mod h1:lzVbDkk/jRao2ib5kge46aLZW1yFc8RFNycdYpnsmZA= +github.com/btcsuite/btcwallet v0.16.7 h1:J6nBMMMc90n77/4QIfzRFn5XB1hPvMDfcgX5U6Ls0kI= +github.com/btcsuite/btcwallet v0.16.7/go.mod h1:J/q3/JxytAcuqR+zSTCRZ5K+0LtMuhxtCjLVXKDHBu0= +github.com/btcsuite/btcwallet/wallet/txauthor v1.3.2 h1:etuLgGEojecsDOYTII8rYiGHjGyV5xTqsXi+ZQ715UU= +github.com/btcsuite/btcwallet/wallet/txauthor v1.3.2/go.mod h1:Zpk/LOb2sKqwP2lmHjaZT9AdaKsHPSbNLm2Uql5IQ/0= +github.com/btcsuite/btcwallet/wallet/txrules v1.2.0 h1:BtEN5Empw62/RVnZ0VcJaVtVlBijnLlJY+dwjAye2Bg= +github.com/btcsuite/btcwallet/wallet/txrules v1.2.0/go.mod h1:AtkqiL7ccKWxuLYtZm8Bu8G6q82w4yIZdgq6riy60z0= +github.com/btcsuite/btcwallet/wallet/txsizes v1.2.2/go.mod h1:q08Rms52VyWyXcp5zDc4tdFRKkFgNsMQrv3/LvE1448= +github.com/btcsuite/btcwallet/wallet/txsizes v1.2.3 h1:PszOub7iXVYbtGybym5TGCp9Dv1h1iX4rIC3HICZGLg= +github.com/btcsuite/btcwallet/wallet/txsizes v1.2.3/go.mod h1:q08Rms52VyWyXcp5zDc4tdFRKkFgNsMQrv3/LvE1448= +github.com/btcsuite/btcwallet/walletdb v1.3.5/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU= +github.com/btcsuite/btcwallet/walletdb v1.4.0 h1:/C5JRF+dTuE2CNMCO/or5N8epsrhmSM4710uBQoYPTQ= +github.com/btcsuite/btcwallet/walletdb v1.4.0/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU= +github.com/btcsuite/btcwallet/wtxmgr v1.5.0 h1:WO0KyN4l6H3JWnlFxfGR7r3gDnlGT7W2cL8vl6av4SU= +github.com/btcsuite/btcwallet/wtxmgr v1.5.0/go.mod h1:TQVDhFxseiGtZwEPvLgtfyxuNUDsIdaJdshvWzR0HJ4= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/golangcrypto v0.0.0-20150304025918-53f62d9b43e8/go.mod h1:tYvUd8KLhm/oXvUeSEs2VlLghFjQt9+ZaF9ghH0JNjc= @@ -79,153 +108,170 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3 github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ= +github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 h1:uH66TXeswKn5PW5zdZ39xEwfS9an067BirqA+P4QaLI= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= -github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA= -github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= -github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= -github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= -github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= -github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= -github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= -github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk= +github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E= +github.com/cockroachdb/errors v1.2.4 h1:Lap807SXTH5tri2TivECb/4abUkMZC9zRoLarvcKDqs= +github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f h1:JOrtw2xFKzlg+cbHpyrpLDmnN1HqhBfnX7WDiW7eG2c= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= -github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= -github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= -github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8= -github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= +github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= -github.com/decred/dcrd/lru v1.1.2 h1:KdCzlkxppuoIDGEvCGah1fZRicrDH36IipvlB1ROkFY= -github.com/decred/dcrd/lru v1.1.2/go.mod h1:gEdCVgXs1/YoBvFWt7Scgknbhwik3FgVSzlnCcXL2N8= -github.com/dhui/dktest v0.4.5 h1:uUfYBIVREmj/Rw6MvgmqNAYzTiKOHJak+enB5Di73MM= -github.com/dhui/dktest v0.4.5/go.mod h1:tmcyeHDKagvlDrz7gDKq4UAJOLIfVZYkfD5OnHDwcCo= -github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= -github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/cli v28.1.1+incompatible h1:eyUemzeI45DY7eDPuwUcmDyDj1pM98oD5MdSpiItp8k= -github.com/docker/cli v28.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI= -github.com/docker/docker v28.3.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= -github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= -github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q= +github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= +github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= +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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/fergusstrange/embedded-postgres v1.25.0 h1:sa+k2Ycrtz40eCRPOzI7Ry7TtkWXXJ+YRsxpKMDhxK0= -github.com/fergusstrange/embedded-postgres v1.25.0/go.mod h1:t/MLs0h9ukYM6FSt99R7InCHs1nW0ordoVCcnzmpTYw= +github.com/fergusstrange/embedded-postgres v1.10.0 h1:YnwF6xAQYmKLAXXrrRx4rHDLih47YJwVPvg8jeKfdNg= +github.com/fergusstrange/embedded-postgres v1.10.0/go.mod h1:a008U8/Rws5FtIOTGYDYa7beVWsT3qVKyqExqYYjL+c= github.com/frankban/quicktest v1.0.0/go.mod h1:R98jIehRai+d1/3Hv2//jOVCTJhW1VBavT6B6CuGq2k= github.com/frankban/quicktest v1.2.2 h1:xfmOhhoH5fGPgbEAlhLpJH9p0z/0Qizio9osmvn9IUY= github.com/frankban/quicktest v1.2.2/go.mod h1:Qh/WofXFeiAFII1aEBu529AtJo6Zg2VHscnEsbBnJ20= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +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= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= 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.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= -github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -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-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= -github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= -github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= 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= -github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= -github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= +github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v0.0.0-20210429001901-424d2337a529 h1:2voWjNECnrZRbfwXxHB1/j8wa6xdKn85B5NzgVL/pTU= +github.com/golang/glog v0.0.0-20210429001901-424d2337a529/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.1-0.20190312032427-6f77996f0c42/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +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/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= -github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 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= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0 h1:ajue7SzQMywqRjg2fK7dcpc0QhFGpTR2plWfV4EZWR4= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.5.0/go.mod h1:r1hZAcvfFXuYmcKyCJI9wlyOPIZUJl6FCB8Cpca/NLE= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 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/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= @@ -236,10 +282,8 @@ github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsU github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgconn v1.14.3 h1:bVoTr12EGANZz66nZPkMInAV/KHD2TxH9npjXXgiB3w= -github.com/jackc/pgconn v1.14.3/go.mod h1:RZbme4uasqzybK2RK5c65VsHxoyaml09lx3tXOcO/VM= -github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438 h1:Dj0L5fhJ9F82ZJyVOmBx6msDp/kfd1t9GRfny/mfJA0= -github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds= +github.com/jackc/pgconn v1.10.0 h1:4EYhlDVEMsJ30nNj0mmgwIUXoq7e9sMJrVC2ED6QlCU= +github.com/jackc/pgconn v1.10.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= @@ -254,138 +298,117 @@ github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.1.1 h1:7PQ/4gLoqnl87ZxL7xjO0DR5gYuviDCZxQJsUlFW1eI= github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.3.3 h1:1HLSx5H+tXR9pW3in3zaztoEwQYRC9SQaYUHjTSUOag= -github.com/jackc/pgproto3/v2 v2.3.3/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= -github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= -github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= -github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= -github.com/jackc/pgtype v1.14.4 h1:fKuNiCumbKTAIxQwXfB/nsrnkEI6bPJrrSiMKgbJ2j8= -github.com/jackc/pgtype v1.14.4/go.mod h1:aKeozOde08iifGosdJpz9MBZonJOUJxqNpPBcMJTlVA= +github.com/jackc/pgtype v1.8.1 h1:9k0IXtdJXHJbyAWQgbWr1lU+MEhPXZz6RIXxfR5oxXs= +github.com/jackc/pgtype v1.8.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= -github.com/jackc/pgx/v4 v4.18.2/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw= -github.com/jackc/pgx/v4 v4.18.3 h1:dE2/TrEsGX3RBprb3qryqSV9Y60iZN1C6i8IrmW9/BA= -github.com/jackc/pgx/v4 v4.18.3/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw= -github.com/jackc/pgx/v5 v5.9.2 h1:3ZhOzMWnR4yJ+RW1XImIPsD1aNSz4T4fyP7zlQb56hw= -github.com/jackc/pgx/v5 v5.9.2/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4= +github.com/jackc/pgx/v4 v4.13.0 h1:JCjhT5vmhMAf/YwBHLvrBn4OGdIQBiFG6ym8Zmdx570= +github.com/jackc/pgx/v4 v4.13.0/go.mod h1:9P4X524sErlaxj0XSGZk7s+LD0eOyu1ZDUrrpznYDF0= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= -github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= -github.com/jarcoal/httpmock v1.4.0 h1:BvhqnH0JAYbNudL2GMJKgOHe2CtKlzJ/5rWKyp+hc2k= -github.com/jarcoal/httpmock v1.4.0/go.mod h1:ftW1xULwo+j0R0JJkJIIi7UKigZUXCLLanykgjwBXL0= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jessevdk/go-flags v1.6.1 h1:Cvu5U8UGrLay1rZfv/zP7iLpSHGUZ/Ou68T0iX1bBK4= -github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +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/jrick/logrotate v1.1.2 h1:6ePk462NCX7TfKtNp5JJ7MbA2YIslkpfgP03TlTYMN0= -github.com/jrick/logrotate v1.1.2/go.mod h1:f9tdWggSVK3iqavGpyvegq5IhNois7KXmasU6/N96OQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 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= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= github.com/juju/clock v0.0.0-20220203021603-d9deb868a28a h1:Az/6CM/P5guGHNy7r6TkOCctv3lDmN3W1uhku7QMupk= -github.com/juju/clock v0.0.0-20220203021603-d9deb868a28a/go.mod h1:GZ/FY8Cqw3KHG6DwRVPUKbSPTAwyrU28xFi5cqZnLsc= github.com/juju/collections v0.0.0-20220203020748-febd7cad8a7a h1:d7eZO8OS/ZXxdP0uq3E8CdoA1qNFaecAv90UxrxaY2k= -github.com/juju/collections v0.0.0-20220203020748-febd7cad8a7a/go.mod h1:JWeZdyttIEbkR51z2S13+J+aCuHVe0F6meRy+P0YGDo= github.com/juju/errors v0.0.0-20220331221717-b38fca44723b h1:AxFeSQJfcm2O3ov1wqAkTKYFsnMw2g1B4PkYujfAdkY= -github.com/juju/errors v0.0.0-20220331221717-b38fca44723b/go.mod h1:jMGj9DWF/qbo91ODcfJq6z/RYc3FX3taCBZMCcpI4Ls= github.com/juju/loggo v0.0.0-20210728185423-eebad3a902c4 h1:NO5tuyw++EGLnz56Q8KMyDZRwJwWO8jQnj285J3FOmY= github.com/juju/loggo v0.0.0-20210728185423-eebad3a902c4/go.mod h1:NIXFioti1SmKAlKNuUwbMenNdef59IF52+ZzuOmHYkg= github.com/juju/mgo/v2 v2.0.0-20220111072304-f200228f1090 h1:zX5GoH3Jp8k1EjUFkApu/YZAYEn0PYQfg/U6IDyNyYs= -github.com/juju/mgo/v2 v2.0.0-20220111072304-f200228f1090/go.mod h1:N614SE0a4e+ih2rg96Vi2PeC3cTpUOWgCTv3Cgk974c= github.com/juju/retry v0.0.0-20220204093819-62423bf33287 h1:U+7oMWEglXfiikIppNexButZRwKPlzLBGKYSNCXzXf8= -github.com/juju/retry v0.0.0-20220204093819-62423bf33287/go.mod h1:SssN1eYeK3A2qjnFGTiVMbdzGJ2BfluaJblJXvuvgqA= github.com/juju/testing v0.0.0-20220203020004-a0ff61f03494 h1:XEDzpuZb8Ma7vLja3+5hzUqVTvAqm5Y+ygvnDs5iTMM= -github.com/juju/testing v0.0.0-20220203020004-a0ff61f03494/go.mod h1:rUquetT0ALL48LHZhyRGvjjBH8xZaZ8dFClulKK5wK4= github.com/juju/utils/v3 v3.0.0-20220203023959-c3fbc78a33b0 h1:bn+2Adl1yWqYjm3KSFlFqsvfLg2eq+XNL7GGMYApdVw= -github.com/juju/utils/v3 v3.0.0-20220203023959-c3fbc78a33b0/go.mod h1:8csUcj1VRkfjNIRzBFWzLFCMLwLqsRWvkmhfVAUwbC4= github.com/juju/version/v2 v2.0.0-20220204124744-fc9915e3d935 h1:6YoyzXVW1XkqN86y2s/rz365Jm7EiAy39v2G5ikzvHU= -github.com/juju/version/v2 v2.0.0-20220204124744-fc9915e3d935/go.mod h1:ZeFjNy+UFEWJDDPdzW7Cm9NeU6dsViGaFYhXzycLQrw= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= 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.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= -github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +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/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= +github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= 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/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 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= +github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= -github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.3 h1:v9QZf2Sn6AmjXtQeFpdoq/eaNtYP6IN+7lcrygsIAtg= +github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf h1:HZKvJUHlcXI/f/O0Avg7t8sqkPo78HFzjmeYFl6DPnc= github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf/go.mod h1:vxmQPeIQxPf6Jf9rM8R+B4rKBqLA2AjttNxkFBL2Plk= -github.com/lightninglabs/lndclient v0.21.0-1 h1:NuyccCK7tbMaH7hhqtewcx+qeBel4/RLJrlnQ/lMkkY= -github.com/lightninglabs/lndclient v0.21.0-1/go.mod h1:RUIcfPr82HrvZr3pu9f8nbD5v6VFbm+KgExqNNp5bE4= -github.com/lightninglabs/migrate/v4 v4.18.2-9023d66a-fork-pr-2.0.20251211093704-71c1eef09789 h1:7kX7vUgHUazAHcCJ6uzBDa4/2MEGEbMEfa01GtfqmTQ= -github.com/lightninglabs/migrate/v4 v4.18.2-9023d66a-fork-pr-2.0.20251211093704-71c1eef09789/go.mod h1:99BKpIi6ruaaXRM1A77eqZ+FWPQ3cfRa+ZVy5bmWMaY= -github.com/lightninglabs/neutrino v0.17.1 h1:lNhgq7ix/N81R6oATroP/kHMzH1qzVVF2dEGcTlN2t4= -github.com/lightninglabs/neutrino v0.17.1/go.mod h1:tcwCgRTGWcaua0L/xzdwllW8eslHDbux4XkiYsivvHE= -github.com/lightninglabs/neutrino/cache v1.1.3 h1:rgnabC41W+XaPuBTQrdeFjFCCAVKh1yctAgmb3Se9zA= -github.com/lightninglabs/neutrino/cache v1.1.3/go.mod h1:qxkJb+pUxR5p84jl5uIGFCR4dGdFkhNUwMSxw3EUWls= -github.com/lightninglabs/protobuf-go-hex-display v1.30.0-hex-display h1:pRdza2wleRN1L2fJXd6ZoQ9ZegVFTAb2bOQfruJPKcY= -github.com/lightninglabs/protobuf-go-hex-display v1.30.0-hex-display/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -github.com/lightningnetwork/lightning-onion v1.3.0 h1:FqILgHjD6euc/Muo1VOzZ4+XDPuFnw6EYROBq0rR/5c= -github.com/lightningnetwork/lightning-onion v1.3.0/go.mod h1:nP85zMHG7c0si/eHBbSQpuDCtnIXfSvFrK3tW6YWzmU= -github.com/lightningnetwork/lnd v0.21.0-beta h1:bDP5UH15E7DVGTztsmBPQLqgyilq5EXDrglvQFmRc3U= -github.com/lightningnetwork/lnd v0.21.0-beta/go.mod h1:HcKq9DyxbVEZXuR28TIyGbIIgAjANCxI+N6dqOnRBAA= -github.com/lightningnetwork/lnd/actor v0.0.6 h1:Ge8N2wivARG+27qJBwTlB0vwsypStZYZy8vk4Zl38sU= -github.com/lightningnetwork/lnd/actor v0.0.6/go.mod h1:YAsoniSbY/cAM9HTVNfZLvt7RI6swDxy6wzPspTcMZg= -github.com/lightningnetwork/lnd/cert v1.2.2 h1:71YK6hogeJtxSxw2teq3eGeuy4rHGKcFf0d0Uy4qBjI= -github.com/lightningnetwork/lnd/cert v1.2.2/go.mod h1:jQmFn/Ez4zhDgq2hnYSw8r35bqGVxViXhX6Cd7HXM6U= -github.com/lightningnetwork/lnd/clock v1.1.1 h1:OfR3/zcJd2RhH0RU+zX/77c0ZiOnIMsDIBjgjWdZgA0= -github.com/lightningnetwork/lnd/clock v1.1.1/go.mod h1:mGnAhPyjYZQJmebS7aevElXKTFDuO+uNFFfMXK1W8xQ= -github.com/lightningnetwork/lnd/fn/v2 v2.0.9 h1:ZytG4ltPac/sCyg1EJDn10RGzPIDJeyennUMRdOw7Y8= -github.com/lightningnetwork/lnd/fn/v2 v2.0.9/go.mod h1:aPUJHJ31S+Lgoo8I5SxDIjnmeCifqujaiTXKZqpav3w= -github.com/lightningnetwork/lnd/healthcheck v1.2.6 h1:1sWhqr93GdkWy4+6U7JxBfcyZIE78MhIHTJZfPx7qqI= -github.com/lightningnetwork/lnd/healthcheck v1.2.6/go.mod h1:Mu02um4CWY/zdTOvFje7WJgJcHyX2zq/FG3MhOAiGaQ= -github.com/lightningnetwork/lnd/kvdb v1.4.16 h1:9BZgWdDfjmHRHLS97cz39bVuBAqMc4/p3HX1xtUdbDI= -github.com/lightningnetwork/lnd/kvdb v1.4.16/go.mod h1:HW+bvwkxNaopkz3oIgBV6NEnV4jCEZCACFUcNg4xSjM= -github.com/lightningnetwork/lnd/queue v1.2.0 h1:sSrn+u84OLuOT/F+xGxgg8VfknXeIZEAFQoMH6BL60s= -github.com/lightningnetwork/lnd/queue v1.2.0/go.mod h1:qLNP0L3B7piRGvDyhAyJKic4xTt+Mw4D7mWrQeuAwxY= -github.com/lightningnetwork/lnd/sqldb v1.0.13 h1:CcG9mrHNW/hIuZnqgosdiNmS7QhjSyfR/XkSFJB7EC8= -github.com/lightningnetwork/lnd/sqldb v1.0.13/go.mod h1:ew3kMfknA0B4djTtrQSAkxvro+8+c++L8LuNaoT7GQA= -github.com/lightningnetwork/lnd/sqldb/v2 v2.0.0-20260326184657-f7cc56305bae h1:ICRuZIkXed43iuqcJaayubPTcQolttttwNZFrapdwIo= -github.com/lightningnetwork/lnd/sqldb/v2 v2.0.0-20260326184657-f7cc56305bae/go.mod h1:T2F1Sfb0oSpZyylIEE3ijiSejaXvIExER5xEdoe5wEE= -github.com/lightningnetwork/lnd/ticker v1.1.1 h1:J/b6N2hibFtC7JLV77ULQp++QLtCwT6ijJlbdiZFbSM= -github.com/lightningnetwork/lnd/ticker v1.1.1/go.mod h1:waPTRAAcwtu7Ji3+3k+u/xH5GHovTsCoSVpho0KDvdA= -github.com/lightningnetwork/lnd/tlv v1.3.2 h1:MO4FCk7F4k5xPMqVZF6Nb/kOpxlwPrUQpYjmyKny5s0= -github.com/lightningnetwork/lnd/tlv v1.3.2/go.mod h1:pJuiBj1ecr1WWLOtcZ+2+hu9Ey25aJWFIsjmAoPPnmc= -github.com/lightningnetwork/lnd/tor v1.1.6 h1:WHUumk7WgU6BUFsqHuqszI9P6nfhMeIG+rjJBlVE6OE= -github.com/lightningnetwork/lnd/tor v1.1.6/go.mod h1:qSRB8llhAK+a6kaTPWOLLXSZc6Hg8ZC0mq1sUQ/8JfI= +github.com/lightninglabs/lndclient v0.16.0-10 h1:cMBJNfssBQtpgYIu23QLP/qw0ijiT5SBZffnXz8zjJk= +github.com/lightninglabs/lndclient v0.16.0-10/go.mod h1:mqY0znSNa+M40HZowwKfno29RyZnmxoqo++BlYP82EY= +github.com/lightninglabs/neutrino v0.15.0 h1:yr3uz36fLAq8hyM0TRUVlef1TRNoWAqpmmNlVtKUDtI= +github.com/lightninglabs/neutrino v0.15.0/go.mod h1:pmjwElN/091TErtSE9Vd5W4hpxoG2/+xlb+HoPm9Gug= +github.com/lightninglabs/neutrino/cache v1.1.1 h1:TllWOSlkABhpgbWJfzsrdUaDH2fBy/54VSIB4vVqV8M= +github.com/lightninglabs/neutrino/cache v1.1.1/go.mod h1:XJNcgdOw1LQnanGjw8Vj44CvguYA25IMKjWFZczwZuo= +github.com/lightninglabs/protobuf-hex-display v1.4.3-hex-display h1:RZJ8H4ueU/aQ9pFtx5wqsuD3B/DezrewJeVwDKKYY8E= +github.com/lightninglabs/protobuf-hex-display v1.4.3-hex-display/go.mod h1:2oKOBU042GKFHrdbgGiKax4xVrFiZu51lhacUZQ9MnE= +github.com/lightningnetwork/lightning-onion v1.2.1-0.20221202012345-ca23184850a1 h1:Wm0g70gkcAu2pGpNZwfWPSVOY21j8IyYsNewwK4OkT4= +github.com/lightningnetwork/lightning-onion v1.2.1-0.20221202012345-ca23184850a1/go.mod h1:7dDx73ApjEZA0kcknI799m2O5kkpfg4/gr7N092ojNo= +github.com/lightningnetwork/lnd v0.16.0-beta h1:h1EIN501DuFrBboO7vPiZ6Z7c9PIOx7IjRw1JhB5hEE= +github.com/lightningnetwork/lnd v0.16.0-beta/go.mod h1:dpm/SAXH7CG00ax3Pks7T2hVvvxdX/cc5ACJNPw+vLo= +github.com/lightningnetwork/lnd/cert v1.2.1 h1:CTrTcU0L66J73oqdRLVfNylZyp1Fh97ZezX6IuzkrqE= +github.com/lightningnetwork/lnd/cert v1.2.1/go.mod h1:04JhIEodoR6usBN5+XBRtLEEmEHsclLi0tEyxZQNP+w= +github.com/lightningnetwork/lnd/clock v1.0.1/go.mod h1:KnQudQ6w0IAMZi1SgvecLZQZ43ra2vpDNj7H/aasemg= +github.com/lightningnetwork/lnd/clock v1.1.0 h1:/yfVAwtPmdx45aQBoXQImeY7sOIEr7IXlImRMBOZ7GQ= +github.com/lightningnetwork/lnd/clock v1.1.0/go.mod h1:KnQudQ6w0IAMZi1SgvecLZQZ43ra2vpDNj7H/aasemg= +github.com/lightningnetwork/lnd/healthcheck v1.2.2 h1:im+qcpgSuteqRCGeorT9yqVXuLrS6A7/acYzGgarMS4= +github.com/lightningnetwork/lnd/healthcheck v1.2.2/go.mod h1:IWY0GChlarRbXFkFDdE4WY5POYJabe/7/H1iCZt4ZKs= +github.com/lightningnetwork/lnd/kvdb v1.4.1 h1:l/nLBPLbdvP/lajMtrFMLzAi5OoLTH3+zUU6SwoEEv8= +github.com/lightningnetwork/lnd/kvdb v1.4.1/go.mod h1:f+F7Da8HTa8MePFsdWvusGRdcmWTgSWykGsVyC02Z5M= +github.com/lightningnetwork/lnd/queue v1.1.0 h1:YpCJjlIvVxN/R7ww2aNiY8ex7U2fucZDLJ67tI3HFx8= +github.com/lightningnetwork/lnd/queue v1.1.0/go.mod h1:YTkTVZCxz8tAYreH27EO3s8572ODumWrNdYW2E/YKxg= +github.com/lightningnetwork/lnd/ticker v1.0.0/go.mod h1:iaLXJiVgI1sPANIF2qYYUJXjoksPNvGNYowB8aRbpX0= +github.com/lightningnetwork/lnd/ticker v1.1.0 h1:ShoBiRP3pIxZHaETndfQ5kEe+S4NdAY1hiX7YbZ4QE4= +github.com/lightningnetwork/lnd/ticker v1.1.0/go.mod h1:ubqbSVCn6RlE0LazXuBr7/Zi6QT0uQo++OgIRBxQUrk= +github.com/lightningnetwork/lnd/tlv v1.1.0 h1:gsyte75HVuA/X59O+BhaISHM6OobZ0YesPbdu+xG1h0= +github.com/lightningnetwork/lnd/tlv v1.1.0/go.mod h1:0+JKp4un47MG1lnj6jKa8woNeB1X7w3yF4MZB1NHiiE= +github.com/lightningnetwork/lnd/tor v1.0.0/go.mod h1:RDtaAdwfAm+ONuPYwUhNIH1RAvKPv+75lHPOegUcz64= +github.com/lightningnetwork/lnd/tor v1.1.0 h1:iXO7fSzjxTI+p88KmtpbuyuRJeNfgtpl9QeaAliILXE= +github.com/lightningnetwork/lnd/tor v1.1.0/go.mod h1:RDtaAdwfAm+ONuPYwUhNIH1RAvKPv+75lHPOegUcz64= github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 h1:sjOGyegMIhvgfq5oaue6Td+hxZuf3tDC8lAPrFldqFw= github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796/go.mod h1:3p7ZTf9V1sNPI5H8P3NkTFF4LuwMdPl2DodF60qAKqY= github.com/ltcsuite/ltcutil v0.0.0-20181217130922-17f3b04680b6/go.mod h1:8Vg/LTOO0KYa/vlHWJ6XZAevPQThGH5sufO0Hrou/lA= @@ -397,57 +420,42 @@ github.com/mattn/go-isatty v0.0.0-20160806122752-66b8e73f3f5c/go.mod h1:M+lRXTBq github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/maxatome/go-testdeep v1.14.0 h1:rRlLv1+kI8eOI3OaBXZwb3O7xY3exRzdW5QyX48g9wI= -github.com/maxatome/go-testdeep v1.14.0/go.mod h1:lPZc/HAcJMP92l7yI6TRz1aZN5URwUBUAfUNvrclaNM= +github.com/mholt/archiver/v3 v3.5.0 h1:nE8gZIrw66cu4osS/U7UW7YDuGMHssxKutU8IfWxwWE= +github.com/mholt/archiver/v3 v3.5.0/go.mod h1:qqTTPUK/HZPFgFQ/TJ3BzvTpF/dPtFVJXdQbCmeMxwc= github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= -github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= -github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= -github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo= -github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs= -github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= -github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= -github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= +github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= +github.com/nwaples/rardecode v1.1.2 h1:Cj0yZY6T1Zx1R7AhTbyGSALm44/Mmq+BAPc4B/p/d3M= +github.com/nwaples/rardecode v1.1.2/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= +github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +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/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= -github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= -github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= -github.com/opencontainers/runc v1.2.8 h1:RnEICeDReapbZ5lZEgHvj7E9Q3Eex9toYmaGBsbvU5Q= -github.com/opencontainers/runc v1.2.8/go.mod h1:cC0YkmZcuvr+rtBZ6T7NBoVbMGNAdLa/21vIElJDOzI= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/ory/dockertest/v3 v3.10.0 h1:4K3z2VMe8Woe++invjaTB7VRyQXQy5UY+loujO4aNE4= -github.com/ory/dockertest/v3 v3.10.0/go.mod h1:nr57ZbRWMqfsdGdFNLHz5jjNdDb7VVFnzAeW1n5N1Lg= +github.com/pierrec/lz4/v4 v4.0.3/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pierrec/lz4/v4 v4.1.8 h1:ieHkV+i2BRzngO4Wd/3HGowuZStgq6QkPsD1eolNAO4= +github.com/pierrec/lz4/v4 v4.1.8/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -473,119 +481,114 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= -github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.15.0 h1:D0RCU5rMAp+SpgkiNdrjfJ+LX4J1M32V2NeCY7EJ6hc= -github.com/rogpeppe/go-internal v1.15.0/go.mod h1:DrUVZyrJU+txYW5/1kwtXQSMFio52ZOxX7yM1VHvnxs= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= -github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= 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/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= 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/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk= -github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= +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= +github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/urfave/cli v1.22.9 h1:cv3/KhXGBGjEXLC4bH0sLuJ9BewaAbpk5oyMOveu4pw= +github.com/urfave/cli v1.22.9/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/xdg-go/stringprep v1.0.3 h1:kdwGpVNwPFtjs98xCGkHjQtGKh86rDcRZN17QEMCOIs= github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo= -go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E= -go.etcd.io/etcd/api/v3 v3.5.12 h1:W4sw5ZoU2Juc9gBWuLk5U6fHfNVyY1WC5g9uiXZio/c= -go.etcd.io/etcd/api/v3 v3.5.12/go.mod h1:Ot+o0SWSyT6uHhA56al1oCED0JImsRiU9Dc26+C2a+4= -go.etcd.io/etcd/client/pkg/v3 v3.5.12 h1:EYDL6pWwyOsylrQyLp2w+HkQ46ATiOvoEdMarindU2A= -go.etcd.io/etcd/client/pkg/v3 v3.5.12/go.mod h1:seTzl2d9APP8R5Y2hFL3NVlD6qC/dOT+3kvrqPyTas4= -go.etcd.io/etcd/client/v2 v2.305.12 h1:0m4ovXYo1CHaA/Mp3X/Fak5sRNIWf01wk/X1/G3sGKI= -go.etcd.io/etcd/client/v2 v2.305.12/go.mod h1:aQ/yhsxMu+Oht1FOupSr60oBvcS9cKXHrzBpDsPTf9E= -go.etcd.io/etcd/client/v3 v3.5.12 h1:v5lCPXn1pf1Uu3M4laUE2hp/geOTc5uPcYYsNe1lDxg= -go.etcd.io/etcd/client/v3 v3.5.12/go.mod h1:tSbBCakoWmmddL+BKVAJHa9km+O/E+bumDe9mSbPiqw= -go.etcd.io/etcd/pkg/v3 v3.5.12 h1:OK2fZKI5hX/+BTK76gXSTyZMrbnARyX9S643GenNGb8= -go.etcd.io/etcd/pkg/v3 v3.5.12/go.mod h1:UVwg/QIMoJncyeb/YxvJBJCE/NEwtHWashqc8A1nj/M= -go.etcd.io/etcd/raft/v3 v3.5.12 h1:7r22RufdDsq2z3STjoR7Msz6fYH8tmbkdheGfwJNRmU= -go.etcd.io/etcd/raft/v3 v3.5.12/go.mod h1:ERQuZVe79PI6vcC3DlKBukDCLja/L7YMu29B74Iwj4U= -go.etcd.io/etcd/server/v3 v3.5.12 h1:EtMjsbfyfkwZuA2JlKOiBfuGkFCekv5H178qjXypbG8= -go.etcd.io/etcd/server/v3 v3.5.12/go.mod h1:axB0oCjMy+cemo5290/CutIjoxlfA6KVYKD1w0uue10= -go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= -go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= -go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms= -go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 h1:dIIDULZJpgdiHz5tXrTgKIMLkus6jEFa7x5SOKcyR7E= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0/go.mod h1:jlRVBe7+Z1wyxFSUs48L6OBQZ5JwH2Hg/Vbl+t9rAgI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0 h1:gvmNvqrPYovvyRmCSygkUDyL8lC5Tl845MLEwqpxhEU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0/go.mod h1:vNUq47TGFioo+ffTSnKNdob241vePmtNZnAODKapKd0= -go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g= -go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc= -go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8= -go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE= -go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw= -go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg= -go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw= -go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA= -go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= -go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.etcd.io/bbolt v1.3.5-0.20200615073812-232d8fc87f50/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= +go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +go.etcd.io/etcd/api/v3 v3.5.7 h1:sbcmosSVesNrWOJ58ZQFitHMdncusIifYcrBfwrlJSY= +go.etcd.io/etcd/api/v3 v3.5.7/go.mod h1:9qew1gCdDDLu+VwmeG+iFpL+QlpHTo7iubavdVDgCAA= +go.etcd.io/etcd/client/pkg/v3 v3.5.7 h1:y3kf5Gbp4e4q7egZdn5T7W9TSHUvkClN6u+Rq9mEOmg= +go.etcd.io/etcd/client/pkg/v3 v3.5.7/go.mod h1:o0Abi1MK86iad3YrWhgUsbGx1pmTS+hrORWc2CamuhY= +go.etcd.io/etcd/client/v2 v2.305.7 h1:AELPkjNR3/igjbO7CjyF1fPuVPjrblliiKj+Y6xSGOU= +go.etcd.io/etcd/client/v2 v2.305.7/go.mod h1:GQGT5Z3TBuAQGvgPfhR7VPySu/SudxmEkRq9BgzFU6s= +go.etcd.io/etcd/client/v3 v3.5.7 h1:u/OhpiuCgYY8awOHlhIhmGIGpxfBU/GZBUP3m/3/Iz4= +go.etcd.io/etcd/client/v3 v3.5.7/go.mod h1:sOWmj9DZUMyAngS7QQwCyAXXAL6WhgTOPLNS/NabQgw= +go.etcd.io/etcd/pkg/v3 v3.5.7 h1:obOzeVwerFwZ9trMWapU/VjDcYUJb5OfgC1zqEGWO/0= +go.etcd.io/etcd/pkg/v3 v3.5.7/go.mod h1:kcOfWt3Ov9zgYdOiJ/o1Y9zFfLhQjylTgL4Lru8opRo= +go.etcd.io/etcd/raft/v3 v3.5.7 h1:aN79qxLmV3SvIq84aNTliYGmjwsW6NqJSnqmI1HLJKc= +go.etcd.io/etcd/raft/v3 v3.5.7/go.mod h1:TflkAb/8Uy6JFBxcRaH2Fr6Slm9mCPVdI2efzxY96yU= +go.etcd.io/etcd/server/v3 v3.5.7 h1:BTBD8IJUV7YFgsczZMHhMTS67XuA4KpRquL0MFOJGRk= +go.etcd.io/etcd/server/v3 v3.5.7/go.mod h1:gxBgT84issUVBRpZ3XkW1T55NjOb4vZZRI4wVvNhf4A= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +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/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/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= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= -go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= @@ -603,32 +606,51 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 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-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= -golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= -golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= +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= -golang.org/x/exp v0.0.0-20250811191247-51f88131bc50 h1:3yiSh9fhy5/RhCSntf4Sy0Tnx50DmMpQ4MQdKKk4yg4= -golang.org/x/exp v0.0.0-20250811191247-51f88131bc50/go.mod h1:rT6SFzZ7oxADUDx58pcaKFTcZ+inxAa9fTrYx/uVYwg= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20221111094246-ab4555d3164f h1:dx+ByaHZgQORWfy/TumeLerCm48o5pDf+skF0SWtLdY= +golang.org/x/exp v0.0.0-20221111094246-ab4555d3164f/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= -golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I= +golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -638,150 +660,285 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/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-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= -golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= +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.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20210615190721-d04028783cf1 h1:x622Z2o4hgCr/4CiKWc51jHVKaWdtVpBNmEI8wI9Qns= +golang.org/x/oauth2 v0.0.0-20210615190721-d04028783cf1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= -golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/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-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= 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/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= -golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= -golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 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/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= -golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= -gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= -google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= -google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 h1:fCvbg86sFXwdrl5LgVcTEvNC+2txB5mgROGmRL5mrls= -google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:+rXWjjaukWZun3mLfjmVnQi18E1AsFbDN9QdJ5YXLto= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced h1:c5geK1iMU3cDKtFrCVQIcjR3W+JOZMuhIyICMCTbtus= +google.golang.org/genproto v0.0.0-20210617175327-b9e0b3197ced/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE= -google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= +google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20160105164936-4f90aeace3a2/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/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v1 v1.0.1 h1:oQFRXzZ7CkBGdm1XZm/EbQYaYNNEElNBOd09M6cqNso= gopkg.in/errgo.v1 v1.0.1/go.mod h1:3NjfXwocQRYAPTq4/fzX+CwUhPRcR/azYRhj8G+LqMo= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= @@ -808,38 +965,39 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.3.0 h1:MfDY1b1/0xN1CyMlQDac0ziEy9zJQd9CXBRRDHw2jJo= -gotest.tools/v3 v3.3.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -modernc.org/cc/v4 v4.26.2 h1:991HMkLjJzYBIfha6ECZdjrIYz2/1ayr+FL8GN+CNzM= -modernc.org/cc/v4 v4.26.2/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= -modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU= -modernc.org/ccgo/v4 v4.28.0/go.mod h1:JygV3+9AV6SmPhDasu4JgquwU81XAKLd3OKTUDNOiKE= -modernc.org/fileutil v1.3.8 h1:qtzNm7ED75pd1C7WgAGcK4edm4fvhtBsEiI/0NQ54YM= -modernc.org/fileutil v1.3.8/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc= -modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= -modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= -modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks= -modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI= -modernc.org/libc v1.66.3 h1:cfCbjTUcdsKyyZZfEUKfoHcP3S0Wkvz3jgSzByEWVCQ= -modernc.org/libc v1.66.3/go.mod h1:XD9zO8kt59cANKvHPXpx7yS2ELPheAey0vjIuZOhOU8= -modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= -modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= -modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= -modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= -modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8= -modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= -modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= -modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= -modernc.org/sqlite v1.38.2 h1:Aclu7+tgjgcQVShZqim41Bbw9Cho0y/7WzYptXqkEek= -modernc.org/sqlite v1.38.2/go.mod h1:cPTJYSlgg3Sfg046yBShXENNtPrWrDX8bsbAQBzgQ5E= -modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= -modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= -modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= -modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk= -pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= +lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw= +modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0= +modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw= +modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY= +modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= +modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= +modernc.org/libc v1.22.2 h1:4U7v51GyhlWqQmwCHj28Rdq2Yzwk55ovjFrdPjs8Hb0= +modernc.org/libc v1.22.2/go.mod h1:uvQavJ1pZ0hIoC/jfqNoMLURIMhKzINIWypNM17puug= +modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= +modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.4.0 h1:crykUfNSnMAXaOJnnxcSzbUGMqkLWjklJKkBK2nwZwk= +modernc.org/memory v1.4.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sqlite v1.20.3 h1:SqGJMMxjj1PHusLxdYxeQSodg7Jxn9WWkaAQjKrntZs= +modernc.org/sqlite v1.20.3/go.mod h1:zKcGyrICaxNTMEHSr1HQ2GUraP0j+845GYw37+EyT6A= +modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY= +modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= +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= +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= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/itest/Dockerfile b/itest/Dockerfile index a797f81..460d272 100644 --- a/itest/Dockerfile +++ b/itest/Dockerfile @@ -2,9 +2,9 @@ # base images. The first stage builds lnd with the golang base image. # The second stage runs directly on the bitcoind base image and adds all # binaries required to run the tests with. -FROM golang:1.25.10-alpine as builder +FROM golang:1.19.4-alpine as builder -ARG LND_VERSION=v0.21.0-beta +ARG LND_VERSION=v0.15.4-beta RUN apk add --no-cache git make diff --git a/itest/channel_events_test.go b/itest/channel_events_test.go deleted file mode 100644 index b1befbd..0000000 --- a/itest/channel_events_test.go +++ /dev/null @@ -1,435 +0,0 @@ -package itest - -import ( - "context" - "testing" - "time" - - "github.com/btcsuite/btcd/btcutil" - "github.com/lightninglabs/faraday/frdrpc" - "github.com/lightninglabs/lndclient" - "github.com/lightningnetwork/lnd/lnrpc" - "github.com/lightningnetwork/lnd/lnwire" - "github.com/stretchr/testify/require" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -// TestGetChannelEvents pins the GetChannelEvents RPC contract: a regtest -// channel lifecycle surfaces the expected event-type counts, and a paginated -// walk over the same window matches the unpaginated result event-for-event. -func TestGetChannelEvents(t *testing.T) { - c := newTestContext(t) - defer c.stop() - - ctx := context.Background() - - // We will start by opening a channel from alice to bob. - var aliceChannelAmt = btcutil.Amount(500000) - - err := c.aliceClient.Client.Connect( - ctx, c.bobPubkey, "localhost:10012", true, - ) - require.NoError(c.t, err, "could not connect nodes") - - aliceChannel, _ := c.openChannel( - c.aliceClient.Client, c.bobPubkey, aliceChannelAmt, - ) - - // Wait until alice can route a payment to bob through the new channel. - var paymentAmount lnwire.MilliSatoshi = 20000000 - c.eventuallyf(func() bool { - return c.channelRoutable(c.bobPubkey, paymentAmount) - }, "channel did not become routable") - - // Now we'll send a payment from alice to bob to generate a balance - // update event. - hash, payreq := c.addInvoice(c.bobClient.Client, paymentAmount) - c.makePayment( - c.aliceClient.LndServices, c.bobClient.LndServices, - lndclient.SendPaymentRequest{ - Invoice: payreq, - PaymentHash: &hash, - Timeout: paymentTimeout, - }, lnrpc.Payment_SUCCEEDED, - ) - - // We now close the channel to generate an offline event. - c.closeChannel(c.aliceClient.Client, aliceChannel, true) - - endTime := time.Now().Add(time.Second).Unix() - - events, err := c.faradayClient.GetChannelEvents( - ctx, &frdrpc.ChannelEventsRequest{ - ChanPoint: aliceChannel.String(), - EndTime: endTime, - }, - ) - require.NoError(c.t, err, "could not get channel events") - - // Check that we have the expected event types. - var ( - onlineEvents int - updateEvents int - offlineEvents int - ) - - for _, event := range events.Events { - switch event.EventType { - case frdrpc.ChannelEventType_CHAN_EVENT_ONLINE: - onlineEvents++ - - case frdrpc.ChannelEventType_CHAN_EVENT_UPDATE: - updateEvents++ - - case frdrpc.ChannelEventType_CHAN_EVENT_OFFLINE: - offlineEvents++ - } - } - - // We expect exactly these events for this channel: - // 1. Channel Open: online, update (initial balance) - // 2. Channel Active: online - // 3. Payment sent: two updates (update_add, update_fulfill) - // 4. Channel Offline: offline - // 5. Channel Close: offline - require.Len(t, events.Events, 7) - require.Equal(t, 2, onlineEvents) - require.Equal(t, 3, updateEvents) - require.Equal(t, 2, offlineEvents) - - // Walk the same window with a small page size and assert the - // concatenated pages match the unpaginated result. Catches - // last_id round-trip, has_more termination, and MaxEvents - // clamping in one pass. - const pageSize = 2 - var ( - paged []*frdrpc.ChannelEvent - lastID int64 - pages int - ) - for { - page, err := c.faradayClient.GetChannelEvents( - ctx, &frdrpc.ChannelEventsRequest{ - ChanPoint: aliceChannel.String(), - EndTime: endTime, - MaxEvents: pageSize, - LastId: lastID, - }, - ) - require.NoError(c.t, err, "could not get paginated events") - - // Non-final pages must fill exactly pageSize; the final - // page (HasMore == false) holds the remainder. - if page.HasMore { - require.Len(t, page.Events, pageSize, - "non-final page %d not full", pages) - } else { - require.LessOrEqual(t, len(page.Events), pageSize, - "final page %d exceeds pageSize", pages) - } - - paged = append(paged, page.Events...) - pages++ - if !page.HasMore { - break - } - - lastID = page.LastId - } - - // With 7 events and pageSize 2 we expect ceil(7/2) = 4 pages. - require.Equal(t, 4, pages, "unexpected page count") - - require.Equal(t, len(events.Events), len(paged), - "paginated and unpaginated counts differ") - for i, e := range events.Events { - require.Equal(t, e.Id, paged[i].Id, - "event order mismatch at index %d", i) - } -} - -// TestForwardingAbility integration test opens a channel, sends payments to -// seed events, and verifies that calling the ForwardingAbility RPC returns -// the peer pair analytics successfully and can be decoded. -func TestForwardingAbility(t *testing.T) { - c := newTestContext(t) - defer c.stop() - - ctx := context.Background() - - // Connect nodes and open a channel from alice to bob. - var aliceChannelAmt = btcutil.Amount(500000) - - err := c.aliceClient.Client.Connect( - ctx, c.bobPubkey, "localhost:10012", true, - ) - require.NoError(c.t, err, "could not connect nodes") - - _, _ = c.openChannel( - c.aliceClient.Client, c.bobPubkey, aliceChannelAmt, - ) - - // Wait until alice can route a payment to bob. - var paymentAmount lnwire.MilliSatoshi = 20000000 - c.eventuallyf(func() bool { - return c.channelRoutable(c.bobPubkey, paymentAmount) - }, "channel did not become routable") - - // Send a payment from alice to bob. - hash, payreq := c.addInvoice(c.bobClient.Client, paymentAmount) - c.makePayment( - c.aliceClient.LndServices, c.bobClient.LndServices, - lndclient.SendPaymentRequest{ - Invoice: payreq, - PaymentHash: &hash, - Timeout: paymentTimeout, - }, lnrpc.Payment_SUCCEEDED, - ) - - // The alice->bob payment moved liquidity onto bob's side of the only - // channel, so from this point on the bob self-pair holds at least the - // requested floor. Measuring over a window that starts now keeps the - // pair's uptime fraction high, which both clears the uptime threshold - // and keeps the node-down guard satisfied. A future end time extends - // the window over the still-funded state. - bobHex := c.bobPubkey.String() - windowStart := time.Now() - - // The events store ingests channel updates asynchronously, so retry - // until the bob self-pair surfaces. - var ability frdrpc.ForwardingAbility - c.eventuallyf(func() bool { - endTime := time.Now().Add(2 * time.Second).Unix() - resp, err := c.faradayClient.ForwardingAbility( - ctx, &frdrpc.ForwardingAbilityRequest{ - StartTime: uint64(windowStart.Unix()), - EndTime: uint64(endTime), - LiquidityFloorSat: 1000, - UptimeThreshold: 0.1, - }, - ) - if err != nil { - return false - } - - decoded, err := frdrpc.DecodeForwardingAbility(resp) - if err != nil { - return false - } - - a, ok := decoded[bobHex][bobHex] - if !ok { - return false - } - ability = a - - return true - }, "expected bob self-pair in forwarding ability") - - // The bob self-pair was up but never forwarded through itself, so it - // surfaces via the up-but-idle bitmask: non-zero effective uptime and - // zero forwarded volume. - require.Greater(c.t, ability.EffectiveUptimeS, int64(0)) - require.Zero(c.t, ability.ForwardedSat) -} - -// TestForwardingDowntime exercises the offline/online plumbing end to end. It -// disconnects the only channel peer to take the channel offline, asserts that -// faraday records the resulting offline event, then reconnects the peer and -// asserts the recovering online event lands and the bob self-pair surfaces in -// ForwardingAbility again. This proves downtime and recovery flow through to -// the analyzer; the exact per-second uptime math is covered deterministically -// by the analyzer unit tests. -func TestForwardingDowntime(t *testing.T) { - c := newTestContext(t) - defer c.stop() - - ctx := context.Background() - - // Connect nodes and open a channel from alice to bob. - var aliceChannelAmt = btcutil.Amount(500000) - - err := c.aliceClient.Client.Connect( - ctx, c.bobPubkey, "localhost:10012", true, - ) - require.NoError(c.t, err, "could not connect nodes") - - aliceChannel, _ := c.openChannel( - c.aliceClient.Client, c.bobPubkey, aliceChannelAmt, - ) - - // Wait until alice can route a payment to bob. - var paymentAmount lnwire.MilliSatoshi = 20000000 - c.eventuallyf(func() bool { - return c.channelRoutable(c.bobPubkey, paymentAmount) - }, "channel did not become routable") - - // Move liquidity onto bob's side so the bob self-pair clears the - // liquidity floor while the channel is up. - hash, payreq := c.addInvoice(c.bobClient.Client, paymentAmount) - c.makePayment( - c.aliceClient.LndServices, c.bobClient.LndServices, - lndclient.SendPaymentRequest{ - Invoice: payreq, - PaymentHash: &hash, - Timeout: paymentTimeout, - }, lnrpc.Payment_SUCCEEDED, - ) - - chanPoint := aliceChannel.String() - bobHex := c.bobPubkey.String() - - // Snapshot the event counts before the disconnect so we can detect the - // new offline and online events the disconnect and recovery produce. - onlineBefore, offlineBefore := c.channelEventCounts(chanPoint) - - // Disconnect bob to take the only channel offline. - c.disconnectPeer(c.aliceClient, c.bobPubkey) - - // faraday should ingest the resulting offline event: this is the - // downtime signal that the channel went inactive. - c.eventuallyf(func() bool { - _, offline := c.channelEventCounts(chanPoint) - return offline > offlineBefore - }, "expected an offline event after disconnect") - - // An explicit DisconnectPeer is sticky: lnd does not auto-reconnect, so - // the channel stays offline until we reconnect. A window that sits - // entirely in this offline period leaves no pair clearing the uptime - // threshold, so the node-down guard rejects the request with - // FailedPrecondition rather than returning an empty response. The - // threshold is irrelevant here since the only pair has zero uptime. - c.eventuallyf(func() bool { - now := time.Now() - _, err := c.faradayClient.ForwardingAbility( - ctx, &frdrpc.ForwardingAbilityRequest{ - StartTime: uint64(now.Unix()), - EndTime: uint64( - now.Add(2 * time.Second).Unix(), - ), - LiquidityFloorSat: 1000, - UptimeThreshold: 0.9, - }, - ) - - return status.Code(err) == codes.FailedPrecondition - }, "expected node-down guard while bob is disconnected") - - // An explicit DisconnectPeer drops lnd's persistent connection, so the - // channel only comes back up once we reconnect. Reconnect bob to bring - // the channel active again. - err = c.aliceClient.Client.Connect( - ctx, c.bobPubkey, "localhost:10012", true, - ) - require.NoError(c.t, err, "could not reconnect nodes") - - // The channel goes active again on reconnect, which faraday records as - // an online event. - c.eventuallyf(func() bool { - online, _ := c.channelEventCounts(chanPoint) - return online > onlineBefore - }, "expected an online event after reconnect") - - // With the channel back up and liquidity still on bob's side, the bob - // self-pair surfaces in ForwardingAbility again over a fresh window - // that opens after recovery. - c.eventuallyf(func() bool { - now := time.Now() - resp, err := c.faradayClient.ForwardingAbility( - ctx, &frdrpc.ForwardingAbilityRequest{ - StartTime: uint64(now.Unix()), - EndTime: uint64( - now.Add(2 * time.Second).Unix(), - ), - LiquidityFloorSat: 1000, - UptimeThreshold: 0.1, - }, - ) - if err != nil { - return false - } - - decoded, err := frdrpc.DecodeForwardingAbility(resp) - if err != nil { - return false - } - - _, ok := decoded[bobHex][bobHex] - - return ok - }, "expected bob self-pair after reconnect") -} - -// TestChannelEventsPruning verifies that starting Faraday with low size limits -// (e.g. max-events=1 and retention=2s) executes live background pruning -// successfully and bounds the database size correctly. -func TestChannelEventsPruning(t *testing.T) { - c := newTestContext( - t, "--chanevents.max-events=1", "--chanevents.retention=2s", - ) - defer c.stop() - - ctx := context.Background() - - // We will start by opening a channel from alice to bob. - var aliceChannelAmt = btcutil.Amount(500000) - - err := c.aliceClient.Client.Connect( - ctx, c.bobPubkey, "localhost:10012", true, - ) - require.NoError(c.t, err, "could not connect nodes") - - aliceChannel, _ := c.openChannel( - c.aliceClient.Client, c.bobPubkey, aliceChannelAmt, - ) - - // Use a far-future end time so the query window never excludes a stored - // event on a slow host. A tight wall-clock window here would make the - // counts below racy. - endTime := time.Now().Add(time.Hour).Unix() - - // We deliberately do not assert on the initial event count here: opening - // a channel records several events, but the 2-second background prune can - // fire before we observe them on a slow host, so any such pre-prune - // assertion would be flaky. The eventuallyf checks below verify the - // pruning behaviour directly instead. - - // Wait for the live background pruning ticker to bound the table to the - // max-events ceiling. We assert at most one event rather than exactly - // one: the size limit keeps a single event, but the 2-second retention - // limit then ages it out since no new events follow the channel open, - // so the steady state is zero or one. - var eventsAfter *frdrpc.ChannelEventsResponse - c.eventuallyf(func() bool { - var err error - eventsAfter, err = c.faradayClient.GetChannelEvents( - ctx, &frdrpc.ChannelEventsRequest{ - ChanPoint: aliceChannel.String(), - EndTime: endTime, - }, - ) - if err != nil { - return false - } - return len(eventsAfter.Events) <= 1 - }, "expected channel events to be pruned down to at most one in the "+ - "background") - - // No further events follow the channel open, so once the remaining - // event ages past the 2-second retention window the age-based prune - // removes it too, draining the table to zero. - c.eventuallyf(func() bool { - eventsAfter, err := c.faradayClient.GetChannelEvents( - ctx, &frdrpc.ChannelEventsRequest{ - ChanPoint: aliceChannel.String(), - EndTime: endTime, - }, - ) - if err != nil { - return false - } - return len(eventsAfter.Events) == 0 - }, "expected channel events to be pruned down to zero once all events "+ - "age out of the retention window") -} diff --git a/itest/log.go b/itest/log.go index 9694140..a16fac8 100644 --- a/itest/log.go +++ b/itest/log.go @@ -1,8 +1,10 @@ package itest -import "github.com/btcsuite/btclog/v2" +import ( + "github.com/btcsuite/btclog" +) var ( - handler = btclog.NewDefaultHandler(newPrefixStdout("itest")) - log = btclog.NewSLogger(handler) + backend = btclog.NewBackend(newPrefixStdout("itest")) + log = backend.Logger("") ) diff --git a/itest/nodereport_test.go b/itest/nodereport_test.go index d492090..26e94b9 100644 --- a/itest/nodereport_test.go +++ b/itest/nodereport_test.go @@ -85,7 +85,7 @@ func TestNodeAudit(t *testing.T) { feeRef := accounting.FeeReference(aliceChannel.Hash.String()) expected[feeRef] = expectedReport{ eventType: frdrpc.EntryType_CHANNEL_OPEN_FEE, - amount: lnwire.MilliSatoshi(4118 * 1000), + amount: lnwire.MilliSatoshi(8237 * 1000), onChain: true, } @@ -100,10 +100,6 @@ func TestNodeAudit(t *testing.T) { invoiceAmount lnwire.MilliSatoshi = 1000 ) - // TODO: there are some timing issues. We should upgrade the test - // framework to lntest. - time.Sleep(time.Second * 3) - // Make a payment from alice to bob, we need to make this payment first // because we do not have any incoming liquidity. hash, payreq := c.addInvoice(c.bobClient.Client, paymentAmount) @@ -116,10 +112,6 @@ func TestNodeAudit(t *testing.T) { }, lnrpc.Payment_SUCCEEDED, ) - // TODO: there are some timing issues. We should upgrade the test - // framework to lntest. - time.Sleep(time.Second * 3) - // Add an entry for our payment to our set of expected entries. We do // not expect a fee entry because we made a single hop payment. Since // this is the first payment we send, we expect it to have a sequence @@ -188,14 +180,14 @@ func TestNodeAudit(t *testing.T) { expected[accounting.FeeReference(closeTx.String())] = expectedReport{ eventType: frdrpc.EntryType_CHANNEL_CLOSE_FEE, - amount: lnwire.MilliSatoshi(4525 * 1000), + amount: lnwire.MilliSatoshi(9060 * 1000), onChain: true, } // Because we force closed our channels, we also expect to have sweep // transactions for our commitment. Bob should have claimed our htlc on // chain, so we do not expect it to be swept. - sweeps, err := c.aliceClient.WalletKit.ListSweeps(ctx, 0) + sweeps, err := c.aliceClient.WalletKit.ListSweeps(ctx) require.NoError(c.t, err, "could not get sweeps") require.Len(c.t, sweeps, 1) diff --git a/itest/test_context.go b/itest/test_context.go index 2f34a2f..4b68c90 100644 --- a/itest/test_context.go +++ b/itest/test_context.go @@ -68,7 +68,7 @@ type testContext struct { } // newTestContext returns a new context instance. -func newTestContext(t *testing.T, extraFaradayArgs ...string) *testContext { +func newTestContext(t *testing.T) *testContext { var err error ctx := &testContext{ @@ -123,11 +123,7 @@ func newTestContext(t *testing.T, extraFaradayArgs ...string) *testContext { require.NoError(t, err) // Start faraday. - ctx.startFaraday(extraFaradayArgs...) - - // Wait for faraday's channel events monitor to finish its initial - // chain-sync. - time.Sleep(5 * time.Second) + ctx.startFaraday() return ctx } @@ -157,6 +153,15 @@ func (c *testContext) mine() int { return len(block.Transactions) - 1 } +// mine mines a block and verifies that the expected number of transactions is +// present (excluding the coinbase tx). +func (c *testContext) mineExactly(expectedTxCount int) { + c.t.Helper() + + txCount := c.mine() + require.Equal(c.t, expectedTxCount, txCount) +} + // mempoolTxCount returns the number of txes currently in the mempool. func (c *testContext) mempoolTxCount() int { txes, err := c.bitcoindClient.GetRawMempool() @@ -299,9 +304,8 @@ func (c *testContext) closeChannel(client lndclient.LightningClient, require.NoError(c.t, err, "could not close channel") var ( - closeTx chainhash.Hash - closeFee btcutil.Amount - gotPending bool + closeTx chainhash.Hash + closeFee btcutil.Amount ) // Wait for us to get an update from our channel indicating that it is @@ -315,10 +319,7 @@ func (c *testContext) closeChannel(client lndclient.LightningClient, case *lndclient.PendingCloseUpdate: // Get our close tx from the mempool to get its fee // and add an expected entry because we opened the - // channel so we pay the fees. This must happen - // before we mine any block, otherwise the close tx - // is confirmed out of the mempool and the lookup - // fails. + // channel so we pay the fees. close, err := c.bitcoindClient.GetMempoolEntry( closeTx.String(), ) @@ -327,8 +328,6 @@ func (c *testContext) closeChannel(client lndclient.LightningClient, closeFee, err = btcutil.NewAmount(close.Fee) require.NoError(c.t, err, "could not get fee") - gotPending = true - case *lndclient.ChannelClosedUpdate: return true } @@ -337,15 +336,9 @@ func (c *testContext) closeChannel(client lndclient.LightningClient, c.t.Fatalf("error closing channel: %v, %v", channel, err) - // If we have not received an update yet, wait for the pending - // close to broadcast. Only once we have captured the close tx - // fee from the mempool do we start mining blocks to drive the - // channel to its fully resolved state, so that mining does not - // confirm the close tx before we read its fee. + // If we have not received an update yet, mine a block. default: - if gotPending { - c.mine() - } + c.mine() } return false @@ -461,75 +454,6 @@ func (c *testContext) waitForChannelOpen(targetChannel *wire.OutPoint) { ) } -// channelRoutable reports whether alice's router can build a route to dest -// for amount. It gates on QueryRoutes rather than channel activation: lnd -// marks a channel Active on channel_ready, but the local channel_update the -// router needs lands a moment later. -func (c *testContext) channelRoutable(dest route.Vertex, - amount lnwire.MilliSatoshi) bool { - - _, err := c.aliceClient.Client.QueryRoutes( - context.Background(), lndclient.QueryRoutesRequest{ - PubKey: dest, - AmtMsat: amount, - }, - ) - - return err == nil -} - -// disconnectPeer disconnects the given client from a peer, taking any channels -// between them offline. lnd normally refuses to disconnect from a peer with an -// active channel, but the itest lnd is a non-integration build where unsafe -// disconnect is always permitted. The raw lnrpc client is used because the -// high-level lndclient interface exposes no Disconnect, and the admin macaroon -// is attached at call time since the shared connection carries none. -func (c *testContext) disconnectPeer(client *lndclient.GrpcLndServices, - peer route.Vertex) { - - c.t.Helper() - - ctx, err := client.WithMacaroonAuthForService( - context.Background(), lndclient.AdminServiceMac, - ) - require.NoError(c.t, err, "could not attach macaroon") - - raw := lnrpc.NewLightningClient(client.ClientConn) - _, err = raw.DisconnectPeer(ctx, &lnrpc.DisconnectPeerRequest{ - PubKey: peer.String(), - }) - require.NoError(c.t, err, "could not disconnect peer") -} - -// channelEventCounts returns how many online and offline events faraday has -// recorded for the given channel up to the present. -func (c *testContext) channelEventCounts(chanPoint string) (online, - offline int) { - - c.t.Helper() - - endTime := time.Now().Add(time.Second).Unix() - events, err := c.faradayClient.GetChannelEvents( - context.Background(), &frdrpc.ChannelEventsRequest{ - ChanPoint: chanPoint, - EndTime: endTime, - }, - ) - require.NoError(c.t, err, "could not get channel events") - - for _, event := range events.Events { - switch event.EventType { - case frdrpc.ChannelEventType_CHAN_EVENT_ONLINE: - online++ - - case frdrpc.ChannelEventType_CHAN_EVENT_OFFLINE: - offline++ - } - } - - return online, offline -} - // findChannel finds a channel in a set of open channels, returning nil if it // is not found. // nolint:interfacer @@ -561,16 +485,29 @@ func (c *testContext) waitForMempoolTxCount(txCount int, msg string) { ) } +// waitForTxesAndMine waits for a specified number of txes to arrive in the +// mempool and then mines a block. +func (c *testContext) waitForTxesAndMine(txCount int, msg string) { + c.t.Helper() + + c.waitForMempoolTxCount(txCount, msg) + c.mineExactly(txCount) +} + +// mempoolEmpty asserts that the mempool is empty. +func (c *testContext) mempoolEmpty() { + c.t.Helper() + + require.Equal(c.t, 0, c.mempoolTxCount(), "mempool not empty") +} + // startFaraday starts faraday, connecting to our test context's alice lnd node. // It returns process start errors and an error channel for errors that occur // after the start. -func (c *testContext) startFaraday(extraArgs ...string) { - args := append([]string{}, faradayArgs...) - args = append(args, extraArgs...) - +func (c *testContext) startFaraday() { // Start loop client daemon. c.faradayCmd = exec.Command( - faradayCmd, args..., + faradayCmd, faradayArgs..., ) attachPrefixStdout(c.faradayCmd, "faraday") diff --git a/itest/util.sh b/itest/util.sh index 55e1995..93ffd85 100644 --- a/itest/util.sh +++ b/itest/util.sh @@ -44,9 +44,6 @@ function start_lnds() { waitnoerror $LNCLI_SERVER getinfo waitnoerror $LNCLI_CLIENT getinfo - waitnoerror $LNCLI_SERVER 'state | grep -q SERVER_ACTIVE' - waitnoerror $LNCLI_CLIENT 'state | grep -q SERVER_ACTIVE' - # Create custom macaroon for faraday to use. PERMS="onchain:read offchain:read address:read peers:read info:read invoices:read uri:/signrpc.Signer/DeriveSharedKey" $LNCLI_SERVER bakemacaroon --save_to lnd-alice/faraday-custom.macaroon $PERMS diff --git a/log.go b/log.go index 1821875..4ee624b 100644 --- a/log.go +++ b/log.go @@ -1,9 +1,8 @@ package faraday import ( - "github.com/btcsuite/btclog/v2" + "github.com/btcsuite/btclog" "github.com/lightninglabs/faraday/accounting" - "github.com/lightninglabs/faraday/chanevents" "github.com/lightninglabs/faraday/dataset" "github.com/lightninglabs/faraday/fiat" "github.com/lightninglabs/faraday/frdrpcserver" @@ -24,7 +23,7 @@ var ( ) // SetupLoggers initializes all package-global logger variables. -func SetupLoggers(root *build.SubLoggerManager, intercept signal.Interceptor) { +func SetupLoggers(root *build.RotatingLogWriter, intercept signal.Interceptor) { genLogger := genSubLogger(root, intercept) log = build.NewSubLogger(Subsystem, genLogger) @@ -38,7 +37,6 @@ func SetupLoggers(root *build.SubLoggerManager, intercept signal.Interceptor) { addSubLogger(root, revenue.Subsystem, intercept, revenue.UseLogger) addSubLogger(root, fiat.Subsystem, intercept, fiat.UseLogger) addSubLogger(root, accounting.Subsystem, intercept, accounting.UseLogger) - addSubLogger(root, chanevents.Subsystem, intercept, chanevents.UseLogger) } // UseLogger uses a specified Logger to output package logging info. @@ -50,7 +48,7 @@ func UseLogger(logger btclog.Logger) { // genSubLogger creates a logger for a subsystem. We provide an instance of // a signal.Interceptor to be able to shutdown in the case of a critical error. -func genSubLogger(root *build.SubLoggerManager, +func genSubLogger(root *build.RotatingLogWriter, interceptor signal.Interceptor) func(string) btclog.Logger { // Create a shutdown function which will request shutdown from our @@ -72,7 +70,7 @@ func genSubLogger(root *build.SubLoggerManager, // addSubLogger is a helper method to conveniently create and register the // logger of a sub system. -func addSubLogger(root *build.SubLoggerManager, subsystem string, +func addSubLogger(root *build.RotatingLogWriter, subsystem string, interceptor signal.Interceptor, useLogger func(btclog.Logger)) { logger := build.NewSubLogger(subsystem, genSubLogger(root, interceptor)) @@ -81,7 +79,7 @@ func addSubLogger(root *build.SubLoggerManager, subsystem string, // setSubLogger is a helper method to conveniently register the logger of a sub // system. -func setSubLogger(root *build.SubLoggerManager, subsystem string, +func setSubLogger(root *build.RotatingLogWriter, subsystem string, logger btclog.Logger, useLogger func(btclog.Logger)) { root.RegisterSubLogger(subsystem, logger) diff --git a/make/testing_flags.mk b/make/testing_flags.mk index d312f0c..ff8dfbe 100644 --- a/make/testing_flags.mk +++ b/make/testing_flags.mk @@ -1,19 +1,6 @@ TEST_FLAGS = -DEV_TAGS = dev COVER_PKG = $$(go list -deps ./... | grep '$(PKG)') -# Add the build tag for running unit tests against a postgres DB. -ifeq ($(dbbackend),postgres) -DEV_TAGS += test_db_postgres -else -DEV_TAGS += test_db_sqlite -endif - -# Add any additional tags that are passed in to make. -ifneq ($(tags),) -DEV_TAGS += ${tags} -endif - # If specific package is being unit tested, construct the full name of the # subpackage. ifneq ($(pkg),) @@ -43,11 +30,11 @@ UNIT_TARGETED ?= no # If a specific package/test case was requested, run the unit test for the # targeted case. Otherwise, default to running all tests. ifeq ($(UNIT_TARGETED), yes) -UNIT := $(GOTEST) -tags="$(DEV_TAGS)" $(TEST_FLAGS) $(UNITPKG) -UNIT_RACE := $(GOTEST) -tags="$(DEV_TAGS)" $(TEST_FLAGS) -race $(UNITPKG) +UNIT := $(GOTEST) $(TEST_FLAGS) $(UNITPKG) +UNIT_RACE := $(GOTEST) $(TEST_FLAGS) -race $(UNITPKG) endif ifeq ($(UNIT_TARGETED), no) -UNIT := $(GOLIST) | $(XARGS) env $(GOTEST) -tags="$(DEV_TAGS)" $(TEST_FLAGS) +UNIT := $(GOLIST) | $(XARGS) env $(GOTEST) $(TEST_FLAGS) UNIT_RACE := $(UNIT) -race endif diff --git a/recommend/log.go b/recommend/log.go index cc9ec32..823bb44 100644 --- a/recommend/log.go +++ b/recommend/log.go @@ -1,7 +1,7 @@ package recommend import ( - "github.com/btcsuite/btclog/v2" + "github.com/btcsuite/btclog" "github.com/lightningnetwork/lnd/build" ) diff --git a/revenue/log.go b/revenue/log.go index 74cb67d..456088a 100644 --- a/revenue/log.go +++ b/revenue/log.go @@ -1,7 +1,7 @@ package revenue import ( - "github.com/btcsuite/btclog/v2" + "github.com/btcsuite/btclog" "github.com/lightningnetwork/lnd/build" ) diff --git a/scripts/gen_sqlc_docker.sh b/scripts/gen_sqlc_docker.sh deleted file mode 100755 index 16db97f..0000000 --- a/scripts/gen_sqlc_docker.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash - -set -e - -# restore_files is a function to restore original schema files. -restore_files() { - echo "Restoring SQLite bigint patch..." - for file in db/sqlc/migrations/*.up.sql.bak; do - mv "$file" "${file%.bak}" - done -} - -# Set trap to call restore_files on script exit. This makes sure the old files -# are always restored. -trap restore_files EXIT - -# Directory of the script file, independent of where it's called from. -DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -# Use the user's cache directories -GOCACHE=$(go env GOCACHE) -GOMODCACHE=$(go env GOMODCACHE) - -# SQLite doesn't support "BIGINT PRIMARY KEY" for auto-incrementing primary -# keys, only "INTEGER PRIMARY KEY". Internally it uses 64-bit integers for -# numbers anyway, independent of the column type. So we can just use -# "INTEGER PRIMARY KEY" and it will work the same under the hood, giving us -# auto incrementing 64-bit integers. -# _BUT_, sqlc will generate Go code with int32 if we use "INTEGER PRIMARY KEY", -# even though we want int64. So before we run sqlc, we need to patch the -# source schema SQL files to use "BIGINT PRIMARY KEY" instead of "INTEGER -# PRIMARY KEY". -echo "Applying SQLite bigint patch..." -for file in db/sqlc/migrations/*.up.sql; do - echo "Patching $file" - sed -i.bak -E 's/INTEGER PRIMARY KEY/BIGINT PRIMARY KEY/g' "$file" -done - -echo "Generating sql models and queries in go..." - -# Run the script to generate the new generated code. Once the script exits, we -# use `trap` to make sure all files are restored. -docker run \ - --rm \ - --user "$UID:$(id -g)" \ - -e UID=$UID \ - -v "$DIR/../:/build" \ - -w /build \ - sqlc/sqlc:1.25.0 generate diff --git a/sqlc.yaml b/sqlc.yaml deleted file mode 100644 index a6d8f2c..0000000 --- a/sqlc.yaml +++ /dev/null @@ -1,10 +0,0 @@ -version: "2" -sql: - - engine: "postgresql" - schema: "db/sqlc/migrations" - queries: "db/sqlc/queries" - gen: - go: - out: db/sqlc - package: sqlc - emit_interface: true diff --git a/tools/Dockerfile b/tools/Dockerfile index 24bb371..13fc9fd 100644 --- a/tools/Dockerfile +++ b/tools/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.25.10-bookworm +FROM golang:1.19.4 RUN apt-get update && apt-get install -y git ENV GOCACHE=/tmp/build/.cache @@ -11,7 +11,7 @@ RUN cd /tmp \ && mkdir -p /tmp/build/.cache \ && mkdir -p /tmp/build/.modcache \ && cd /tmp/tools \ - && go install -trimpath github.com/golangci/golangci-lint/cmd/golangci-lint \ + && go install -trimpath -tags=tools github.com/golangci/golangci-lint/cmd/golangci-lint \ && chmod -R 777 /tmp/build/ WORKDIR /build diff --git a/tools/go.mod b/tools/go.mod index c727448..075f87d 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -1,201 +1,9 @@ module github.com/lightninglabs/faraday/tools +go 1.16 + require ( - github.com/golangci/golangci-lint v1.64.5 + github.com/golangci/golangci-lint v1.45.2 github.com/ory/go-acc v0.2.6 github.com/rinchsan/gosimports v0.1.5 ) - -require ( - 4d63.com/gocheckcompilerdirectives v1.2.1 // indirect - 4d63.com/gochecknoglobals v0.2.2 // indirect - github.com/4meepo/tagalign v1.4.1 // indirect - github.com/Abirdcfly/dupword v0.1.3 // indirect - github.com/Antonboom/errname v1.0.0 // indirect - github.com/Antonboom/nilnil v1.0.1 // indirect - github.com/Antonboom/testifylint v1.5.2 // indirect - github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect - github.com/Crocmagnon/fatcontext v0.7.1 // indirect - github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect - github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0 // indirect - github.com/Masterminds/semver/v3 v3.3.0 // indirect - github.com/OpenPeeDeeP/depguard/v2 v2.2.0 // indirect - github.com/alecthomas/go-check-sumtype v0.3.1 // indirect - github.com/alexkohler/nakedret/v2 v2.0.5 // indirect - github.com/alexkohler/prealloc v1.0.0 // indirect - github.com/alingse/asasalint v0.0.11 // indirect - github.com/alingse/nilnesserr v0.1.2 // indirect - github.com/ashanbrown/forbidigo v1.6.0 // indirect - github.com/ashanbrown/makezero v1.2.0 // indirect - github.com/beorn7/perks v1.0.1 // indirect - github.com/bkielbasa/cyclop v1.2.3 // indirect - github.com/blizzy78/varnamelen v0.8.0 // indirect - github.com/bombsimon/wsl/v4 v4.5.0 // indirect - github.com/breml/bidichk v0.3.2 // indirect - github.com/breml/errchkjson v0.4.0 // indirect - github.com/butuzov/ireturn v0.3.1 // indirect - github.com/butuzov/mirror v1.3.0 // indirect - github.com/catenacyber/perfsprint v0.8.1 // indirect - github.com/ccojocar/zxcvbn-go v1.0.2 // indirect - github.com/cespare/xxhash v1.1.0 // indirect - github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/charithe/durationcheck v0.0.10 // indirect - github.com/chavacava/garif v0.1.0 // indirect - github.com/ckaznocha/intrange v0.3.0 // indirect - github.com/curioswitch/go-reassign v0.3.0 // indirect - github.com/daixiang0/gci v0.13.5 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/denis-tingaikin/go-header v0.5.0 // indirect - github.com/dgraph-io/ristretto v0.0.2 // indirect - github.com/ettle/strcase v0.2.0 // indirect - github.com/fatih/color v1.18.0 // indirect - github.com/fatih/structtag v1.2.0 // indirect - github.com/firefart/nonamedreturns v1.0.5 // indirect - github.com/fsnotify/fsnotify v1.5.4 // indirect - github.com/fzipp/gocyclo v0.6.0 // indirect - github.com/ghostiam/protogetter v0.3.9 // indirect - github.com/go-critic/go-critic v0.12.0 // indirect - github.com/go-toolsmith/astcast v1.1.0 // indirect - github.com/go-toolsmith/astcopy v1.1.0 // indirect - github.com/go-toolsmith/astequal v1.2.0 // indirect - github.com/go-toolsmith/astfmt v1.1.0 // indirect - github.com/go-toolsmith/astp v1.1.0 // indirect - github.com/go-toolsmith/strparse v1.1.0 // indirect - github.com/go-toolsmith/typep v1.1.0 // indirect - github.com/go-viper/mapstructure/v2 v2.4.0 // indirect - github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect - github.com/gobwas/glob v0.2.3 // indirect - github.com/gofrs/flock v0.12.1 // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect - github.com/golangci/go-printf-func-name v0.1.0 // indirect - github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d // indirect - github.com/golangci/misspell v0.6.0 // indirect - github.com/golangci/plugin-module-register v0.1.1 // indirect - github.com/golangci/revgrep v0.8.0 // indirect - github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed // indirect - github.com/google/go-cmp v0.6.0 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/gordonklaus/ineffassign v0.1.0 // indirect - github.com/gostaticanalysis/analysisutil v0.7.1 // indirect - github.com/gostaticanalysis/comment v1.4.2 // indirect - github.com/gostaticanalysis/forcetypeassert v0.2.0 // indirect - github.com/gostaticanalysis/nilerr v0.1.1 // indirect - github.com/hashicorp/go-immutable-radix/v2 v2.1.0 // indirect - github.com/hashicorp/go-version v1.7.0 // indirect - github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect - github.com/hashicorp/hcl v1.0.0 // indirect - github.com/hexops/gotextdiff v1.0.3 // indirect - github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/jgautheron/goconst v1.7.1 // indirect - github.com/jingyugao/rowserrcheck v1.1.1 // indirect - github.com/jjti/go-spancheck v0.6.4 // indirect - github.com/julz/importas v0.2.0 // indirect - github.com/karamaru-alpha/copyloopvar v1.2.1 // indirect - github.com/kisielk/errcheck v1.8.0 // indirect - github.com/kkHAIKE/contextcheck v1.1.5 // indirect - github.com/kulti/thelper v0.6.3 // indirect - github.com/kunwardeep/paralleltest v1.0.10 // indirect - github.com/lasiar/canonicalheader v1.1.2 // indirect - github.com/ldez/exptostd v0.4.1 // indirect - github.com/ldez/gomoddirectives v0.6.1 // indirect - github.com/ldez/grignotin v0.9.0 // indirect - github.com/ldez/tagliatelle v0.7.1 // indirect - github.com/ldez/usetesting v0.4.2 // indirect - github.com/leonklingele/grouper v1.1.2 // indirect - github.com/macabu/inamedparam v0.1.3 // indirect - github.com/magiconair/properties v1.8.6 // indirect - github.com/maratori/testableexamples v1.0.0 // indirect - github.com/maratori/testpackage v1.1.1 // indirect - github.com/matoous/godox v1.1.0 // indirect - github.com/mattn/go-colorable v0.1.14 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.16 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/mgechev/revive v1.6.1 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/moricho/tparallel v0.3.2 // indirect - github.com/nakabonne/nestif v0.3.1 // indirect - github.com/nishanths/exhaustive v0.12.0 // indirect - github.com/nishanths/predeclared v0.2.2 // indirect - github.com/nunnatsa/ginkgolinter v0.19.0 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/ory/viper v1.7.5 // indirect - github.com/pborman/uuid v1.2.0 // indirect - github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pelletier/go-toml/v2 v2.2.3 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/polyfloyd/go-errorlint v1.7.1 // indirect - github.com/prometheus/client_golang v1.12.1 // indirect - github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/common v0.32.1 // indirect - github.com/prometheus/procfs v0.7.3 // indirect - github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 // indirect - github.com/quasilyte/go-ruleguard/dsl v0.3.22 // indirect - github.com/quasilyte/gogrep v0.5.0 // indirect - github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect - github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect - github.com/raeperd/recvcheck v0.2.0 // indirect - github.com/rivo/uniseg v0.4.7 // indirect - github.com/rogpeppe/go-internal v1.13.1 // indirect - github.com/ryancurrah/gomodguard v1.3.5 // indirect - github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect - github.com/sanposhiho/wastedassign/v2 v2.1.0 // indirect - github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect - github.com/sashamelentyev/interfacebloat v1.1.0 // indirect - github.com/sashamelentyev/usestdlibvars v1.28.0 // indirect - github.com/securego/gosec/v2 v2.22.1 // indirect - github.com/sirupsen/logrus v1.9.3 // indirect - github.com/sivchari/containedctx v1.0.3 // indirect - github.com/sivchari/tenv v1.12.1 // indirect - github.com/sonatard/noctx v0.1.0 // indirect - github.com/sourcegraph/go-diff v0.7.0 // indirect - github.com/spf13/afero v1.12.0 // indirect - github.com/spf13/cast v1.5.0 // indirect - github.com/spf13/cobra v1.8.1 // indirect - github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/spf13/pflag v1.0.6 // indirect - github.com/spf13/viper v1.12.0 // indirect - github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect - github.com/stbenjam/no-sprintf-host-port v0.2.0 // indirect - github.com/stretchr/objx v0.5.2 // indirect - github.com/stretchr/testify v1.10.0 // indirect - github.com/subosito/gotenv v1.4.1 // indirect - github.com/tdakkota/asciicheck v0.4.0 // indirect - github.com/tetafro/godot v1.4.20 // indirect - github.com/timakin/bodyclose v0.0.0-20241017074812-ed6a65f985e3 // indirect - github.com/timonwong/loggercheck v0.10.1 // indirect - github.com/tomarrell/wrapcheck/v2 v2.10.0 // indirect - github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect - github.com/ultraware/funlen v0.2.0 // indirect - github.com/ultraware/whitespace v0.2.0 // indirect - github.com/uudashr/gocognit v1.2.0 // indirect - github.com/uudashr/iface v1.3.1 // indirect - github.com/xen0n/gosmopolitan v1.2.2 // indirect - github.com/yagipy/maintidx v1.0.0 // indirect - github.com/yeya24/promlinter v0.3.0 // indirect - github.com/ykadowak/zerologlint v0.1.5 // indirect - gitlab.com/bosi/decorder v0.4.2 // indirect - go-simpler.org/musttag v0.13.0 // indirect - go-simpler.org/sloglint v0.9.0 // indirect - go.uber.org/atomic v1.7.0 // indirect - go.uber.org/automaxprocs v1.6.0 // indirect - go.uber.org/multierr v1.6.0 // indirect - go.uber.org/zap v1.24.0 // indirect - golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect - golang.org/x/mod v0.23.0 // indirect - golang.org/x/sync v0.11.0 // indirect - golang.org/x/sys v0.30.0 // indirect - golang.org/x/text v0.22.0 // indirect - golang.org/x/tools v0.30.0 // indirect - google.golang.org/protobuf v1.36.4 // indirect - gopkg.in/ini.v1 v1.67.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - honnef.co/go/tools v0.6.0 // indirect - mvdan.cc/gofumpt v0.7.0 // indirect - mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f // indirect -) - -go 1.25.10 diff --git a/tools/go.sum b/tools/go.sum index 8917725..2a3c7d9 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -1,7 +1,6 @@ -4d63.com/gocheckcompilerdirectives v1.2.1 h1:AHcMYuw56NPjq/2y615IGg2kYkBdTvOaojYCBcRE7MA= -4d63.com/gocheckcompilerdirectives v1.2.1/go.mod h1:yjDJSxmDTtIHHCqX0ufRYZDL6vQtMG7tJdKVeWwsqvs= -4d63.com/gochecknoglobals v0.2.2 h1:H1vdnwnMaZdQW/N+NrkT1SZMTBmcwHe9Vq8lJcYYTtU= -4d63.com/gochecknoglobals v0.2.2/go.mod h1:lLxwTQjL5eIesRbvnzIP3jZtG140FnTdz+AlMa+ogt0= +4d63.com/gochecknoglobals v0.1.0 h1:zeZSRqj5yCg28tCkIV/z/lWbwvNm5qnKVS15PI8nhD0= +4d63.com/gochecknoglobals v0.1.0/go.mod h1:wfdC5ZjKSPr7CybKEcgJhUOgeAQW1+7WcyK8OvUilfo= +bitbucket.org/creachadair/shell v0.0.6/go.mod h1:8Qqi/cYk7vPnsOePHroKXDJYmb5x7ENhtiFtfZq8K+M= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -15,8 +14,23 @@ cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6 cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.60.0/go.mod h1:yw2G51M9IfRboUH61Us8GqCeF1PzPblB823Mn2q2eAU= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0cM= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -25,124 +39,136 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/firestore v1.6.0/go.mod h1:afJwI0vaXwAG54kI7A//lP/lSPDkQORQuMkv56TxEPU= +cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/pubsub v1.5.0/go.mod h1:ZEwJccE3z93Z2HWvstpri00jOg7oO4UZDtKhwDwqF0w= +cloud.google.com/go/spanner v1.7.0/go.mod h1:sd3K2gZ9Fd0vMPLXzeCrF6fq4i63Q7aTLW/lBIfBkIk= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/4meepo/tagalign v1.4.1 h1:GYTu2FaPGOGb/xJalcqHeD4il5BiCywyEYZOA55P6J4= -github.com/4meepo/tagalign v1.4.1/go.mod h1:2H9Yu6sZ67hmuraFgfZkNcg5Py9Ch/Om9l2K/2W1qS4= -github.com/Abirdcfly/dupword v0.1.3 h1:9Pa1NuAsZvpFPi9Pqkd93I7LIYRURj+A//dFd5tgBeE= -github.com/Abirdcfly/dupword v0.1.3/go.mod h1:8VbB2t7e10KRNdwTVoxdBaxla6avbhGzb8sCTygUMhw= -github.com/Antonboom/errname v1.0.0 h1:oJOOWR07vS1kRusl6YRSlat7HFnb3mSfMl6sDMRoTBA= -github.com/Antonboom/errname v1.0.0/go.mod h1:gMOBFzK/vrTiXN9Oh+HFs+e6Ndl0eTFbtsRTSRdXyGI= -github.com/Antonboom/nilnil v1.0.1 h1:C3Tkm0KUxgfO4Duk3PM+ztPncTFlOf0b2qadmS0s4xs= -github.com/Antonboom/nilnil v1.0.1/go.mod h1:CH7pW2JsRNFgEh8B2UaPZTEPhCMuFowP/e8Udp9Nnb0= -github.com/Antonboom/testifylint v1.5.2 h1:4s3Xhuv5AvdIgbd8wOOEeo0uZG7PbDKQyKY5lGoQazk= -github.com/Antonboom/testifylint v1.5.2/go.mod h1:vxy8VJ0bc6NavlYqjZfmp6EfqXMtBgQ4+mhCojwC1P8= +github.com/Antonboom/errname v0.1.5 h1:IM+A/gz0pDhKmlt5KSNTVAvfLMb+65RxavBXpRtCUEg= +github.com/Antonboom/errname v0.1.5/go.mod h1:DugbBstvPFQbv/5uLcRRzfrNqKE9tVdVCqWCLp6Cifo= +github.com/Antonboom/nilnil v0.1.0 h1:DLDavmg0a6G/F4Lt9t7Enrbgb3Oph6LnDE6YVsmTt74= +github.com/Antonboom/nilnil v0.1.0/go.mod h1:PhHLvRPSghY5Y7mX4TW+BHZQYo1A8flE5H20D3IPZBo= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs= -github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU= +github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Crocmagnon/fatcontext v0.7.1 h1:SC/VIbRRZQeQWj/TcQBS6JmrXcfA+BU4OGSVUt54PjM= -github.com/Crocmagnon/fatcontext v0.7.1/go.mod h1:1wMvv3NXEBJucFGfwOJBxSVWcoIO6emV215SMkW9MFU= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= -github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0 h1:/fTUt5vmbkAcMBt4YQiuC23cV0kEsN1MVMNqeOW43cU= -github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0/go.mod h1:ONJg5sxcbsdQQ4pOW8TGdTidT2TMAUy/2Xhr8mrYaao= -github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= -github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/sprig v2.15.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= +github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/OpenPeeDeeP/depguard/v2 v2.2.0 h1:vDfG60vDtIuf0MEOhmLlLLSzqaRM8EMcgJPdp74zmpA= -github.com/OpenPeeDeeP/depguard/v2 v2.2.0/go.mod h1:CIzddKRvLBC4Au5aYP/i3nyaWQ+ClszLIuVocRiCYFQ= -github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= -github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= -github.com/alecthomas/go-check-sumtype v0.3.1 h1:u9aUvbGINJxLVXiFvHUlPEaD7VDULsrxJb4Aq31NLkU= -github.com/alecthomas/go-check-sumtype v0.3.1/go.mod h1:A8TSiN3UPRw3laIgWEUOHHLPa6/r9MtoigdlP5h3K/E= -github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= -github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= +github.com/OpenPeeDeeP/depguard v1.1.0 h1:pjK9nLPS1FwQYGGpPxoMYpe7qACHOhAWQMQzV71i49o= +github.com/OpenPeeDeeP/depguard v1.1.0/go.mod h1:JtAMzWkmFEzDPyAd+W0NHl1lvpQKTvT9jnRVsohBKpc= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alexkohler/nakedret/v2 v2.0.5 h1:fP5qLgtwbx9EJE8dGEERT02YwS8En4r9nnZ71RK+EVU= -github.com/alexkohler/nakedret/v2 v2.0.5/go.mod h1:bF5i0zF2Wo2o4X4USt9ntUWve6JbFv02Ff4vlkmS/VU= github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= -github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= -github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= -github.com/alingse/nilnesserr v0.1.2 h1:Yf8Iwm3z2hUUrP4muWfW83DF4nE3r1xZ26fGWUKCZlo= -github.com/alingse/nilnesserr v0.1.2/go.mod h1:1xJPrXonEtX7wyTq8Dytns5P2hNzoWymVUIaKm4HNFg= +github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/ashanbrown/forbidigo v1.6.0 h1:D3aewfM37Yb3pxHujIPSpTf6oQk9sc9WZi8gerOIVIY= -github.com/ashanbrown/forbidigo v1.6.0/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= -github.com/ashanbrown/makezero v1.2.0 h1:/2Lp1bypdmK9wDIq7uWBlDF1iMUpIIS4A+pF6C9IEUU= -github.com/ashanbrown/makezero v1.2.0/go.mod h1:dxlPhHbDMC6N6xICzFBSK+4njQDdK8euNO0qjQMtGY4= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/ashanbrown/forbidigo v1.3.0 h1:VkYIwb/xxdireGAdJNZoo24O4lmnEWkactplBlWTShc= +github.com/ashanbrown/forbidigo v1.3.0/go.mod h1:vVW7PEdqEFqapJe95xHkTfB1+XvZXBFg8t0sG2FIxmI= +github.com/ashanbrown/makezero v1.1.1 h1:iCQ87C0V0vSyO+M9E/FZYbu65auqH0lnsOkf5FcB28s= +github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvxKHxgO5Z1axI= +github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.36.30/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bkielbasa/cyclop v1.2.3 h1:faIVMIGDIANuGPWH031CZJTi2ymOQBULs9H21HSMa5w= -github.com/bkielbasa/cyclop v1.2.3/go.mod h1:kHTwA9Q0uZqOADdupvcFJQtp/ksSnytRMe8ztxG8Fuo= -github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M= -github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= -github.com/bombsimon/wsl/v4 v4.5.0 h1:iZRsEvDdyhd2La0FVi5k6tYehpOR/R7qIUjmKk7N74A= -github.com/bombsimon/wsl/v4 v4.5.0/go.mod h1:NOQ3aLF4nD7N5YPXMruR6ZXDOAqLoM0GEpLwTdvmOSc= -github.com/breml/bidichk v0.3.2 h1:xV4flJ9V5xWTqxL+/PMFF6dtJPvZLPsyixAoPe8BGJs= -github.com/breml/bidichk v0.3.2/go.mod h1:VzFLBxuYtT23z5+iVkamXO386OB+/sVwZOpIj6zXGos= -github.com/breml/errchkjson v0.4.0 h1:gftf6uWZMtIa/Is3XJgibewBm2ksAQSY/kABDNFTAdk= -github.com/breml/errchkjson v0.4.0/go.mod h1:AuBOSTHyLSaaAFlWsRSuRBIroCh3eh7ZHh5YeelDIk8= -github.com/butuzov/ireturn v0.3.1 h1:mFgbEI6m+9W8oP/oDdfA34dLisRFCj2G6o/yiI1yZrY= -github.com/butuzov/ireturn v0.3.1/go.mod h1:ZfRp+E7eJLC0NQmk1Nrm1LOrn/gQlOykv+cVPdiXH5M= -github.com/butuzov/mirror v1.3.0 h1:HdWCXzmwlQHdVhwvsfBb2Au0r3HyINry3bDWLYXiKoc= -github.com/butuzov/mirror v1.3.0/go.mod h1:AEij0Z8YMALaq4yQj9CPPVYOyJQyiexpQEQgihajRfI= -github.com/catenacyber/perfsprint v0.8.1 h1:bGOHuzHe0IkoGeY831RW4aSlt1lPRd3WRAScSWOaV7E= -github.com/catenacyber/perfsprint v0.8.1/go.mod h1:/wclWYompEyjUD2FuIIDVKNkqz7IgBIWXIH3V0Zol50= -github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg= -github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bkielbasa/cyclop v1.2.0 h1:7Jmnh0yL2DjKfw28p86YTd/B4lRGcNuu12sKE35sM7A= +github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI= +github.com/blizzy78/varnamelen v0.6.1 h1:kttPCLzXFa+0nt++Cw9fb7GrSSM4KkyIAoX/vXsbuqA= +github.com/blizzy78/varnamelen v0.6.1/go.mod h1:zy2Eic4qWqjrxa60jG34cfL0VXcSwzUrIx68eJPb4Q8= +github.com/bombsimon/wsl/v3 v3.3.0 h1:Mka/+kRLoQJq7g2rggtgQsjuI/K5Efd87WX96EWFxjM= +github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= +github.com/breml/bidichk v0.2.2 h1:w7QXnpH0eCBJm55zGCTJveZEkQBt6Fs5zThIdA6qQ9Y= +github.com/breml/bidichk v0.2.2/go.mod h1:zbfeitpevDUGI7V91Uzzuwrn4Vls8MoBMrwtt78jmso= +github.com/breml/errchkjson v0.2.3 h1:97eGTmR/w0paL2SwfRPI1jaAZHaH/fXnxWTw2eEIqE0= +github.com/breml/errchkjson v0.2.3/go.mod h1:jZEATw/jF69cL1iy7//Yih8yp/mXp2CBoBr9GJwCAsY= +github.com/butuzov/ireturn v0.1.1 h1:QvrO2QF2+/Cx1WA/vETCIYBKtRjc30vesdoPUNo1EbY= +github.com/butuzov/ireturn v0.1.1/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= -github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/charithe/durationcheck v0.0.10 h1:wgw73BiocdBDQPik+zcEoBG/ob8uyBHf2iyoHGPf5w4= -github.com/charithe/durationcheck v0.0.10/go.mod h1:bCWXb7gYRysD1CU3C+u4ceO49LoGOY1C1L6uouGNreQ= -github.com/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc= -github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww= +github.com/charithe/durationcheck v0.0.9 h1:mPP4ucLrf/rKZiIG/a9IPXHGlh8p4CzgpyTy6EEutYk= +github.com/charithe/durationcheck v0.0.9/go.mod h1:SSbRIBVfMjCi/kEB6K65XEA83D6prSM8ap1UCpNKtgg= +github.com/chavacava/garif v0.0.0-20210405164556-e8a0a408d6af h1:spmv8nSH9h5oCQf40jt/ufBCt9j0/58u4G+rkeMqXGI= +github.com/chavacava/garif v0.0.0-20210405164556-e8a0a408d6af/go.mod h1:Qjyv4H3//PWVzTeCezG2b9IRn6myJxJSr4TD/xo6ojU= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/ckaznocha/intrange v0.3.0 h1:VqnxtK32pxgkhJgYQEeOArVidIPg+ahLP7WBOXZd5ZY= -github.com/ckaznocha/intrange v0.3.0/go.mod h1:+I/o2d2A1FBHgGELbGxzIcyd3/9l9DuwjM8FsbSS3Lo= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= 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/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/curioswitch/go-reassign v0.3.0 h1:dh3kpQHuADL3cobV/sSGETA8DOv457dwl+fbBAhrQPs= -github.com/curioswitch/go-reassign v0.3.0/go.mod h1:nApPCCTtqLJN/s8HfItCcKV0jIPwluBOvZP+dsJGA88= -github.com/daixiang0/gci v0.13.5 h1:kThgmH1yBmZSBCh1EJVxQ7JsHpm5Oms0AMed/0LaH4c= -github.com/daixiang0/gci v0.13.5/go.mod h1:12etP2OniiIdP4q+kjUGrC/rUagga7ODbqsom5Eo5Yk= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/daixiang0/gci v0.3.3 h1:55xJKH7Gl9Vk6oQ1cMkwrDWjAkT1D+D1G9kNmRcAIY4= +github.com/daixiang0/gci v0.3.3/go.mod h1:1Xr2bxnQbDxCqqulUOv8qpGqkgRw9RSCGGjEC2LjF8o= +github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/denis-tingaikin/go-header v0.5.0 h1:SRdnP5ZKvcO9KKRP1KJrhFR3RrlGuD+42t4429eC9k8= -github.com/denis-tingaikin/go-header v0.5.0/go.mod h1:mMenU5bWrok6Wl2UsZjy+1okegmwQ3UgWl4V1D8gjlY= +github.com/denis-tingaikin/go-header v0.4.3 h1:tEaZKAlqql6SKCY++utLmkPLd6K8IBM20Ha7UVm+mtU= +github.com/denis-tingaikin/go-header v0.4.3/go.mod h1:0wOCWuN71D5qIgE2nz9KrKmuYBAC2Mra5RassOIQ2/c= github.com/dgraph-io/ristretto v0.0.1/go.mod h1:T40EBc7CJke8TkpiYfGGKAeFjSaxuFXhuXRyumBd6RE= github.com/dgraph-io/ristretto v0.0.2 h1:a5WaUrDa0qm0YrAAS1tUykT5El3kt62KNZZeMxQn3po= github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= @@ -150,83 +176,92 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= -github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= +github.com/envoyproxy/protoc-gen-validate v0.0.14/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ettle/strcase v0.2.0 h1:fGNiVF21fHXpX1niBgk0aROov1LagYsOwV/xqKDKR/Q= -github.com/ettle/strcase v0.2.0/go.mod h1:DajmHElDSaX76ITe3/VHVyMin4LWSJN5Z909Wp+ED1A= -github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= -github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws= +github.com/esimonov/ifshort v1.0.4 h1:6SID4yGWfRae/M7hkVDVVyppy8q/v9OuxNdmjLQStBA= +github.com/esimonov/ifshort v1.0.4/go.mod h1:Pe8zjlRrJ80+q2CxHLfEOfTwxCZ4O+MuhcHcfgNWTk0= +github.com/ettle/strcase v0.1.1 h1:htFueZyVeE1XNnMEfbqp5r67qAN/4r6ya1ysq8Q+Zcw= +github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= -github.com/firefart/nonamedreturns v1.0.5 h1:tM+Me2ZaXs8tfdDw3X6DOX++wMCOqzYUho6tUTYIdRA= -github.com/firefart/nonamedreturns v1.0.5/go.mod h1:gHJjDqhGM4WyPt639SOZs+G89Ko7QKH5R5BhnO6xJhw= -github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= -github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= +github.com/frankban/quicktest v1.14.2 h1:SPb1KFFmM+ybpEjPUhCCkZOM5xlovT5UbrMvWnXyBns= +github.com/frankban/quicktest v1.14.2/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= -github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= +github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= +github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= +github.com/fullstorydev/grpcurl v1.6.0/go.mod h1:ZQ+ayqbKMJNhzLmbpCiurTVlaK2M/3nqZCxaQ2Ze/sM= +github.com/fzipp/gocyclo v0.4.0 h1:IykTnjwh2YLyYkGa0y92iTTEQcnyAz0r9zOo15EbJ7k= +github.com/fzipp/gocyclo v0.4.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/ghostiam/protogetter v0.3.9 h1:j+zlLLWzqLay22Cz/aYwTHKQ88GE2DQ6GkWSYFOI4lQ= -github.com/ghostiam/protogetter v0.3.9/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA= -github.com/go-critic/go-critic v0.12.0 h1:iLosHZuye812wnkEz1Xu3aBwn5ocCPfc9yqmFG9pa6w= -github.com/go-critic/go-critic v0.12.0/go.mod h1:DpE0P6OVc6JzVYzmM5gq5jMU31zLr4am5mB/VfFK64w= +github.com/go-critic/go-critic v0.6.2 h1:L5SDut1N4ZfsWZY0sH4DCrsHLHnhuuWak2wa165t9gs= +github.com/go-critic/go-critic v0.6.2/go.mod h1:td1s27kfmLpe5G/DPjlnFI7o1UCzePptwU7Az0V5iCM= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= 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.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= -github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= -github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8= -github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU= -github.com/go-toolsmith/astcopy v1.1.0 h1:YGwBN0WM+ekI/6SS6+52zLDEf8Yvp3n2seZITCUBt5s= -github.com/go-toolsmith/astcopy v1.1.0/go.mod h1:hXM6gan18VA1T/daUEHCFcYiW8Ai1tIwIzHY6srfEAw= -github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= -github.com/go-toolsmith/astequal v1.1.0/go.mod h1:sedf7VIdCL22LD8qIvv7Nn9MuWJruQA/ysswh64lffQ= -github.com/go-toolsmith/astequal v1.2.0 h1:3Fs3CYZ1k9Vo4FzFhwwewC3CHISHDnVUPC4x0bI2+Cw= -github.com/go-toolsmith/astequal v1.2.0/go.mod h1:c8NZ3+kSFtFY/8lPso4v8LuJjdJiUFVnSuU3s0qrrDY= -github.com/go-toolsmith/astfmt v1.1.0 h1:iJVPDPp6/7AaeLJEruMsBUlOYCmvg0MoCfJprsOmcco= -github.com/go-toolsmith/astfmt v1.1.0/go.mod h1:OrcLlRwu0CuiIBp/8b5PYF9ktGVZUjlNMV634mhwuQ4= -github.com/go-toolsmith/astp v1.1.0 h1:dXPuCl6u2llURjdPLLDxJeZInAeZ0/eZwFJmqZMnpQA= -github.com/go-toolsmith/astp v1.1.0/go.mod h1:0T1xFGz9hicKs8Z5MfAqSUitoUYS30pDMsRVIDHs8CA= -github.com/go-toolsmith/pkgload v1.2.2 h1:0CtmHq/02QhxcF7E9N5LIFcYFsMR5rdovfqTtRKkgIk= -github.com/go-toolsmith/pkgload v1.2.2/go.mod h1:R2hxLNRKuAsiXCo2i5J6ZQPhnPMOVtU+f0arbFPWCus= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g= +github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= +github.com/go-toolsmith/astcopy v1.0.0 h1:OMgl1b1MEpjFQ1m5ztEO06rz5CUd3oBv9RF7+DyvdG8= +github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ= +github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +github.com/go-toolsmith/astequal v1.0.1 h1:JbSszi42Jiqu36Gnf363HWS9MTEAz67vTQLponh3Moc= +github.com/go-toolsmith/astequal v1.0.1/go.mod h1:4oGA3EZXTVItV/ipGiOx7NWkY5veFfcsOJVS2YxltLw= +github.com/go-toolsmith/astfmt v1.0.0 h1:A0vDDXt+vsvLEdbMFJAUBI/uTbRw1ffOPnxsILnFL6k= +github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw= +github.com/go-toolsmith/astp v1.0.0 h1:alXE75TXgcmupDsMK1fRAy0YUzLzqPVvBKoyWV+KPXg= +github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI= +github.com/go-toolsmith/pkgload v1.0.2-0.20220101231613-e814995d17c5 h1:eD9POs68PHkwrx7hAB78z1cb6PfGq/jyWn3wJywsH1o= +github.com/go-toolsmith/pkgload v1.0.2-0.20220101231613-e814995d17c5/go.mod h1:3NAwwmD4uY/yggRxoEjk/S00MIV3A+H7rrE3i87eYxM= +github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4= github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= -github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQiyP2Bvw= -github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= -github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= -github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= -github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= -github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= -github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUWY= -github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= +github.com/go-toolsmith/typep v1.0.2 h1:8xdsa1+FSIH/RhEkgnD1j2CJOy5mNllW1Q9tRiYwvlk= +github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= +github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b h1:khEcpUM4yFcxg4/FHQWkvVRmgijNXRfzkIDHh23ggEo= +github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= -github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= @@ -234,6 +269,9 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -249,27 +287,34 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0= +github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= -github.com/golangci/go-printf-func-name v0.1.0 h1:dVokQP+NMTO7jwO4bwsRwLWeudOVUPPyAKJuzv8pEJU= -github.com/golangci/go-printf-func-name v0.1.0/go.mod h1:wqhWFH5mUdJQhweRnldEywnR5021wTdZSNgwYceV14s= -github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d h1:viFft9sS/dxoYY0aiOTsLKO2aZQAPT4nlQCsimGcSGE= -github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d/go.mod h1:ivJ9QDg0XucIkmwhzCDsqcnxxlDStoTl89jDMIoNxKY= -github.com/golangci/golangci-lint v1.64.5 h1:5omC86XFBKXZgCrVdUWU+WNHKd+CWCxNx717KXnzKZY= -github.com/golangci/golangci-lint v1.64.5/go.mod h1:WZnwq8TF0z61h3jLQ7Sk5trcP7b3kUFxLD6l1ivtdvU= -github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs= -github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo= -github.com/golangci/plugin-module-register v0.1.1 h1:TCmesur25LnyJkpsVrupv1Cdzo+2f7zX0H6Jkw1Ol6c= -github.com/golangci/plugin-module-register v0.1.1/go.mod h1:TTpqoB6KkwOJMV8u7+NyXMrkwwESJLOkfl9TxR1DGFc= -github.com/golangci/revgrep v0.8.0 h1:EZBctwbVd0aMeRnNUsFogoyayvKHyxlV3CdUA46FX2s= -github.com/golangci/revgrep v0.8.0/go.mod h1:U4R/s9dlXZsg8uJmaR1GrloUr14D7qDl8gi2iPXJH8k= -github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed h1:IURFTjxeTfNFP0hTEi1YKjB/ub8zkpaOqFFMApi2EAs= -github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed/go.mod h1:XLXN8bNw4CGRPaqgl3bv/lhz7bsGPh4/xSaMTbo2vkQ= +github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613 h1:9kfjN3AdxcbsZBf8NjltjWihK2QfBBBZuv91cMFfDHw= +github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8= +github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a h1:iR3fYXUjHCR97qWS8ch1y9zPNsgXThGwjKPrYfqMPks= +github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU= +github.com/golangci/golangci-lint v1.45.2 h1:9I3PzkvscJkFAQpTQi5Ga0V4qWdJERajX1UZ7QqkW+I= +github.com/golangci/golangci-lint v1.45.2/go.mod h1:f20dpzMmUTRp+oYnX0OGjV1Au3Jm2JeI9yLqHq1/xsI= +github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA= +github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= +github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= +github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= +github.com/golangci/misspell v0.3.5 h1:pLzmVdl3VxTOncgzHcvLOKirdvcx/TydsClUQXTehjo= +github.com/golangci/misspell v0.3.5/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= +github.com/golangci/revgrep v0.0.0-20210930125155-c22e5001d4f2 h1:SgM7GDZTxtTTQPU84heOxy34iG5Du7F2jcoZnvp+fXI= +github.com/golangci/revgrep v0.0.0-20210930125155-c22e5001d4f2/go.mod h1:LK+zW4MpyytAWQRz0M4xnzEk50lSvqDQKfx304apFkY= +github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys= +github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= +github.com/google/certificate-transparency-go v1.1.1/go.mod h1:FDKqPvSXawb2ecErVRrD+nfy23RCzyl7eqVCEmlT1Zs= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -278,419 +323,582 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= 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= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200507031123-427632fa3b1c/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg= -github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/trillian v1.3.11/go.mod h1:0tPraVHrSDkA3BO6vKX67zgLXs6SsOAbHEivX+9mPgw= +github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gordonklaus/ineffassign v0.1.0 h1:y2Gd/9I7MdY1oEIt+n+rowjBNDcLQq3RsH5hwJd0f9s= -github.com/gordonklaus/ineffassign v0.1.0/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= +github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= +github.com/gordonklaus/ineffassign v0.0.0-20210914165742-4cc7213b9bc8 h1:PVRE9d4AQKmbelZ7emNig1+NT27DUmKZn5qXxfio54U= +github.com/gordonklaus/ineffassign v0.0.0-20210914165742-4cc7213b9bc8/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= +github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75/go.mod h1:g2644b03hfBX9Ov0ZBDgXXens4rxSxmqFBbhvKv2yVA= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= +github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= +github.com/gostaticanalysis/analysisutil v0.1.0/go.mod h1:dMhHRU9KTiDcuLGdy87/2gTR8WruwYZrKdRq9m1O6uw= +github.com/gostaticanalysis/analysisutil v0.4.1/go.mod h1:18U/DLpRgIUd459wGxVHE0fRgmo1UgHDcbw7F5idXu0= github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= +github.com/gostaticanalysis/comment v1.3.0/go.mod h1:xMicKDx7XRXYdVwY9f9wQpDJVnqWxw9wCauCMKp+IBI= github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= github.com/gostaticanalysis/comment v1.4.2 h1:hlnx5+S2fY9Zo9ePo4AhgYsYHbM2+eAv8m/s1JiCd6Q= github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= -github.com/gostaticanalysis/forcetypeassert v0.2.0 h1:uSnWrrUEYDr86OCxWa4/Tp2jeYDlogZiZHzGkWFefTk= -github.com/gostaticanalysis/forcetypeassert v0.2.0/go.mod h1:M5iPavzE9pPqWyeiVXSFghQjljW1+l/Uke3PXHS6ILY= +github.com/gostaticanalysis/forcetypeassert v0.1.0 h1:6eUflI3DiGusXGK6X7cCcIgVCpZ2CiZ1Q7jl6ZxNV70= +github.com/gostaticanalysis/forcetypeassert v0.1.0/go.mod h1:qZEedyP/sY1lTGV1uJ3VhWZ2mqag3IkWsDHVbplHXak= github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3Uqrmrcpk= github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= -github.com/gostaticanalysis/testutil v0.5.0 h1:Dq4wT1DdTwTGCQQv3rl3IvD5Ld0E6HiY+3Zh0sUGqw8= -github.com/gostaticanalysis/testutil v0.5.0/go.mod h1:OLQSbuM6zw2EvCcXTz1lVq5unyoNft372msDY0nY5Hs= +github.com/gostaticanalysis/testutil v0.4.0 h1:nhdCmubdmDF6VEatUNjgUZBJKWRqugoISdUv3PPQgHY= +github.com/gostaticanalysis/testutil v0.4.0/go.mod h1:bLIoPefWXrRi/ssLFWX1dx7Repi5x3CuviD3dgAZaBU= +github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/hashicorp/go-immutable-radix/v2 v2.1.0 h1:CUW5RYIcysz+D3B+l1mDeXrQ7fUvGGCwJfdASSzbrfo= -github.com/hashicorp/go-immutable-radix/v2 v2.1.0/go.mod h1:hgdqLXA4f6NIjRVisM1TJ9aOJVNRqKZj+xDGF6m7PBw= -github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= -github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= +github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= +github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= +github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= -github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.4.0 h1:aAQzgqIrRKRa7w75CKpbBxYsmUoPjzVm1W59ca1L0J4= +github.com/hashicorp/go-version v1.4.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= -github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= +github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= +github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= +github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= +github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= +github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= -github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jgautheron/goconst v1.7.1 h1:VpdAG7Ca7yvvJk5n8dMwQhfEZJh95kl/Hl9S1OI5Jkk= -github.com/jgautheron/goconst v1.7.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= +github.com/jgautheron/goconst v1.5.1 h1:HxVbL1MhydKs8R8n/HE5NPvzfaYmQJA3o879lE4+WcM= +github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= +github.com/jhump/protoreflect v1.6.1/go.mod h1:RZQ/lnuN+zqeRVpQigTwO6o0AJUkxbnSnpuG7toUTG4= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= -github.com/jjti/go-spancheck v0.6.4 h1:Tl7gQpYf4/TMU7AT84MN83/6PutY21Nb9fuQjFTpRRc= -github.com/jjti/go-spancheck v0.6.4/go.mod h1:yAEYdKJ2lRkDA8g7X+oKUHXOWVAXSBJRv04OhF+QUjk= +github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af h1:KA9BjwUk7KlCh6S9EAGWBt1oExIUv9WyNCiRz5amv48= +github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/josharian/txtarfs v0.0.0-20210218200122-0702f000015a/go.mod h1:izVPOvVRsHiKkeGCT6tYBNWyDVuzj9wAaBb5R9qamfw= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +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/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/julz/importas v0.2.0 h1:y+MJN/UdL63QbFJHws9BVC5RpA2iq0kpjrFajTGivjQ= -github.com/julz/importas v0.2.0/go.mod h1:pThlt589EnCYtMnmhmRYY/qn9lCf/frPOK+WMx3xiJY= -github.com/karamaru-alpha/copyloopvar v1.2.1 h1:wmZaZYIjnJ0b5UoKDjUHrikcV0zuPyyxI4SVplLd2CI= -github.com/karamaru-alpha/copyloopvar v1.2.1/go.mod h1:nFmMlFNlClC2BPvNaHMdkirmTJxVCY0lhxBtlfOypMM= +github.com/julz/importas v0.1.0 h1:F78HnrsjY3cR7j0etXy5+TU1Zuy7Xt08X/1aJnH5xXY= +github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= +github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.8.0 h1:ZX/URYa7ilESY19ik/vBmCn6zdGQLxACwjAcWbHlYlg= -github.com/kisielk/errcheck v1.8.0/go.mod h1:1kLL+jV4e+CFfueBmI1dSK2ADDyQnlrnrY/FqKluHJQ= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/errcheck v1.6.0 h1:YTDO4pNy7AUN/021p+JGHycQyYNIyMoenM1YDVK6RlY= +github.com/kisielk/errcheck v1.6.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkHAIKE/contextcheck v1.1.5 h1:CdnJh63tcDe53vG+RebdpdXJTc9atMgGqdx8LXxiilg= -github.com/kkHAIKE/contextcheck v1.1.5/go.mod h1:O930cpht4xb1YQpK+1+AgoM3mFsvxr7uyFptcnWTYUA= +github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 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/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= 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/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= -github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= -github.com/kunwardeep/paralleltest v1.0.10 h1:wrodoaKYzS2mdNVnc4/w31YaXFtsc21PCTdvWJ/lDDs= -github.com/kunwardeep/paralleltest v1.0.10/go.mod h1:2C7s65hONVqY7Q5Efj5aLzRCNLjw2h4eMc9EcypGjcY= -github.com/lasiar/canonicalheader v1.1.2 h1:vZ5uqwvDbyJCnMhmFYimgMZnJMjwljN5VGY0VKbMXb4= -github.com/lasiar/canonicalheader v1.1.2/go.mod h1:qJCeLFS0G/QlLQ506T+Fk/fWMa2VmBUiEI2cuMK4djI= -github.com/ldez/exptostd v0.4.1 h1:DIollgQ3LWZMp3HJbSXsdE2giJxMfjyHj3eX4oiD6JU= -github.com/ldez/exptostd v0.4.1/go.mod h1:iZBRYaUmcW5jwCR3KROEZ1KivQQp6PHXbDPk9hqJKCQ= -github.com/ldez/gomoddirectives v0.6.1 h1:Z+PxGAY+217f/bSGjNZr/b2KTXcyYLgiWI6geMBN2Qc= -github.com/ldez/gomoddirectives v0.6.1/go.mod h1:cVBiu3AHR9V31em9u2kwfMKD43ayN5/XDgr+cdaFaKs= -github.com/ldez/grignotin v0.9.0 h1:MgOEmjZIVNn6p5wPaGp/0OKWyvq42KnzAt/DAb8O4Ow= -github.com/ldez/grignotin v0.9.0/go.mod h1:uaVTr0SoZ1KBii33c47O1M8Jp3OP3YDwhZCmzT9GHEk= -github.com/ldez/tagliatelle v0.7.1 h1:bTgKjjc2sQcsgPiT902+aadvMjCeMHrY7ly2XKFORIk= -github.com/ldez/tagliatelle v0.7.1/go.mod h1:3zjxUpsNB2aEZScWiZTHrAXOl1x25t3cRmzfK1mlo2I= -github.com/ldez/usetesting v0.4.2 h1:J2WwbrFGk3wx4cZwSMiCQQ00kjGR0+tuuyW0Lqm4lwA= -github.com/ldez/usetesting v0.4.2/go.mod h1:eEs46T3PpQ+9RgN9VjpY6qWdiw2/QmfiDeWmdZdrjIQ= -github.com/leonklingele/grouper v1.1.2 h1:o1ARBDLOmmasUaNDesWqWCIFH3u7hoFlM84YrjT3mIY= -github.com/leonklingele/grouper v1.1.2/go.mod h1:6D0M/HVkhs2yRKRFZUoGjeDy7EZTfFBE9gl4kjmIGkA= -github.com/macabu/inamedparam v0.1.3 h1:2tk/phHkMlEL/1GNe/Yf6kkR/hkcUdAEY3L0hjYV1Mk= -github.com/macabu/inamedparam v0.1.3/go.mod h1:93FLICAIk/quk7eaPPQvbzihUdn/QkGDwIZEoLtpH6I= +github.com/kulti/thelper v0.5.1 h1:Uf4CUekH0OvzQTFPrWkstJvXgm6pnNEtQu3HiqEkpB0= +github.com/kulti/thelper v0.5.1/go.mod h1:vMu2Cizjy/grP+jmsvOFDx1kYP6+PD1lqg4Yu5exl2U= +github.com/kunwardeep/paralleltest v1.0.3 h1:UdKIkImEAXjR1chUWLn+PNXqWUGs//7tzMeWuP7NhmI= +github.com/kunwardeep/paralleltest v1.0.3/go.mod h1:vLydzomDFpk7yu5UX02RmP0H8QfRPOV/oFhWN85Mjb4= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/kyoh86/exportloopref v0.1.8 h1:5Ry/at+eFdkX9Vsdw3qU4YkvGtzuVfzT4X7S77LoN/M= +github.com/kyoh86/exportloopref v0.1.8/go.mod h1:1tUcJeiioIs7VWe5gcOObrux3lb66+sBqGZrRkMwPgg= +github.com/ldez/gomoddirectives v0.2.2 h1:p9/sXuNFArS2RLc+UpYZSI4KQwGMEDWC/LbtF5OPFVg= +github.com/ldez/gomoddirectives v0.2.2/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= +github.com/ldez/tagliatelle v0.3.1 h1:3BqVVlReVUZwafJUwQ+oxbx2BEX2vUG4Yu/NOfMiKiM= +github.com/ldez/tagliatelle v0.3.1/go.mod h1:8s6WJQwEYHbKZDsp/LjArytKOG8qaMrKQQ3mFukHs88= +github.com/leonklingele/grouper v1.1.0 h1:tC2y/ygPbMFSBOs3DcyaEMKnnwH7eYKzohOtRrf0SAg= +github.com/leonklingele/grouper v1.1.0/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= +github.com/letsencrypt/pkcs11key/v4 v4.0.0/go.mod h1:EFUvBDay26dErnNb70Nd0/VW3tJiIbETBPTl9ATXQag= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= -github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= -github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= -github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04= -github.com/maratori/testpackage v1.1.1/go.mod h1:s4gRK/ym6AMrqpOa/kEbQTV4Q4jb7WeLZzVhVVVOQMc= -github.com/matoous/godox v1.1.0 h1:W5mqwbyWrwZv6OQ5Z1a/DHGMOvXYCBP3+Ht7KMoJhq4= -github.com/matoous/godox v1.1.0/go.mod h1:jgE/3fUXiTurkdHOLT5WEkThTSuE7yxHv5iWPa80afs= +github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/maratori/testpackage v1.0.1 h1:QtJ5ZjqapShm0w5DosRjg0PRlSdAdlx+W6cCKoALdbQ= +github.com/maratori/testpackage v1.0.1/go.mod h1:ddKdw+XG0Phzhx8BFDTKgpWP4i7MpApTE5fXSKAqwDU= +github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 h1:pWxk9e//NbPwfxat7RXkts09K+dEBJWakUWwICVqYbA= +github.com/matoous/godox v0.0.0-20210227103229-6504466cf951/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= -github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= -github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mgechev/revive v1.6.1 h1:ncK0ZCMWtb8GXwVAmk+IeWF2ULIDsvRxSRfg5sTwQ2w= -github.com/mgechev/revive v1.6.1/go.mod h1:/2tfHWVO8UQi/hqJsIYNEKELi+DJy/e+PQpLgTB1v88= +github.com/mbilski/exhaustivestruct v1.2.0 h1:wCBmUnSYufAHO6J4AVWY6ff+oxWxsVFrwgOdMUQePUo= +github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= +github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg= +github.com/mgechev/revive v1.1.4 h1:sZOjY6GU35Kr9jKa/wsKSHgrFz8eASIB5i3tqWZMp0A= +github.com/mgechev/revive v1.1.4/go.mod h1:ZZq2bmyssGh8MSPz3VVziqRNIMYTJXzP8MUKG90vZ9A= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= +github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= +github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/moricho/tparallel v0.3.2 h1:odr8aZVFA3NZrNybggMkYO3rgPRcqjeQUlBBFVxKHTI= -github.com/moricho/tparallel v0.3.2/go.mod h1:OQ+K3b4Ln3l2TZveGCywybl68glfLEwFGqvnjok8b+U= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/moricho/tparallel v0.2.1 h1:95FytivzT6rYzdJLdtfn6m1bfFJylOJK41+lgv/EHf4= +github.com/moricho/tparallel v0.2.1/go.mod h1:fXEIZxG2vdfl0ZF8b42f5a78EhjjD5mX8qUplsoSU4k= +github.com/mozilla/scribe v0.0.0-20180711195314-fb71baf557c1/go.mod h1:FIczTrinKo8VaLxe6PWTPEXRXDIHz2QAwiaBaP5/4a8= +github.com/mozilla/tls-observatory v0.0.0-20210609171429-7bc42856d2e5/go.mod h1:FUqVoUPHSEdDR0MnFM3Dh8AU0pZHLXUD127SAJGER/s= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007/go.mod h1:m2XC9Qq0AlmmVksL6FktJCdTYyLk7V3fKyp0sl1yWQo= +github.com/mwitkow/go-proto-validators v0.2.0/go.mod h1:ZfA1hW+UH/2ZHOWvQ3HnQaU0DtnpXu850MZiy+YUgcc= github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U= github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= -github.com/nishanths/exhaustive v0.12.0 h1:vIY9sALmw6T/yxiASewa4TQcFsVYZQQRUQJhKRf3Swg= -github.com/nishanths/exhaustive v0.12.0/go.mod h1:mEZ95wPIZW+x8kC4TgC+9YCUgiST7ecevsVDTgc2obs= -github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= -github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= -github.com/nunnatsa/ginkgolinter v0.19.0 h1:CnHRFAeBS3LdLI9h+Jidbcc5KH71GKOmaBZQk8Srnto= -github.com/nunnatsa/ginkgolinter v0.19.0/go.mod h1:jkQ3naZDmxaZMXPWaS9rblH+i+GWXQCaS/JFIWcOH2s= +github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 h1:4kuARK6Y6FxaNu/BnU2OAaLF86eTVhP2hjTB6iMvItA= +github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nishanths/exhaustive v0.7.11 h1:xV/WU3Vdwh5BUH4N06JNUznb6d5zhRPOnlgCrpNYNKA= +github.com/nishanths/exhaustive v0.7.11/go.mod h1:gX+MP7DWMKJmNa1HfMozK+u04hQd3na9i0hyqf3/dOI= +github.com/nishanths/predeclared v0.0.0-20190419143655-18a43bb90ffc/go.mod h1:62PewwiQTlm/7Rj+cxVYqZvDIUc+JjZq6GHAC1fsObQ= +github.com/nishanths/predeclared v0.2.1 h1:1TXtjmy4f3YCFjTxRd8zcFHOmoUir+gp0ESzjFzG2sw= +github.com/nishanths/predeclared v0.2.1/go.mod h1:HvkGJcA3naj4lOwnFXFDkFxVtSqQMB9sbB1usJ+xjQE= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU= -github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk= -github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= -github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/ginkgo/v2 v2.1.3 h1:e/3Cwtogj0HA+25nMP1jCMDIf8RtRYbGwGGuBIFztkc= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= +github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/ory/go-acc v0.2.6 h1:YfI+L9dxI7QCtWn2RbawqO0vXhiThdXu/RgizJBbaq0= github.com/ory/go-acc v0.2.6/go.mod h1:4Kb/UnPcT8qRAk3IAxta+hvVapdxTLWtrr7bFLlEgpw= github.com/ory/viper v1.7.5 h1:+xVdq7SU3e1vNaCsk/ixsfxE4zylk1TJUiJrY647jUE= github.com/ory/viper v1.7.5/go.mod h1:ypOuyJmEUb3oENywQZRgeAMwqgOyDqwboO1tj3DjTaM= +github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= -github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= -github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs= -github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= -github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= -github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= +github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d h1:CdDQnGF8Nq9ocOS/xlSptM1N3BbrA6/kmaep5ggwaIA= +github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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/polyfloyd/go-errorlint v1.7.1 h1:RyLVXIbosq1gBdk/pChWA8zWYLsq9UEw7a1L5TVMCnA= -github.com/polyfloyd/go-errorlint v1.7.1/go.mod h1:aXjNb1x2TNhoLsk26iv1yl7a+zTnXPhwEMtEXukiLR8= -github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= -github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= +github.com/polyfloyd/go-errorlint v0.0.0-20211125173453-6d6d39c5bb8b h1:/BDyEJWLnDUYKGWdlNx/82qSaVu2bUok/EvPUtIGuvw= +github.com/polyfloyd/go-errorlint v0.0.0-20211125173453-6d6d39c5bb8b/go.mod h1:wi9BfjxjF/bwiZ701TzmfKu6UKC357IOAtNr0Td0Lvw= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1 h1:+Wl/0aFp0hpuHM3H//KMft64WQ1yX9LdJY64Qm/gFCo= -github.com/quasilyte/go-ruleguard v0.4.3-0.20240823090925-0fe6f58b47b1/go.mod h1:GJLgqsLeo4qgavUoL8JeGFNS7qcisx3awV/w9eWTmNI= -github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= -github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= -github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo= -github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= -github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl980XxGFEZSS6KlBGIV0diGdySzxATTWoqaU= -github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= -github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs= -github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= -github.com/raeperd/recvcheck v0.2.0 h1:GnU+NsbiCqdC2XX5+vMZzP+jAJC5fht7rcVTAhX74UI= -github.com/raeperd/recvcheck v0.2.0/go.mod h1:n04eYkwIR0JbgD73wT8wL4JjPC3wm0nFtzBnWNocnYU= +github.com/pseudomuto/protoc-gen-doc v1.3.2/go.mod h1:y5+P6n3iGrbKG+9O04V5ld71in3v/bX88wUwgt+U8EA= +github.com/pseudomuto/protokit v0.2.0/go.mod h1:2PdH30hxVHsup8KpBTOXTBeMVhJZVio3Q8ViKSAXT0Q= +github.com/quasilyte/go-ruleguard v0.3.1-0.20210203134552-1b5a410e1cc8/go.mod h1:KsAh3x0e7Fkpgs+Q9pNLS5XpFSvYCEVl5gP9Pp1xp30= +github.com/quasilyte/go-ruleguard v0.3.15 h1:iWYzp1z72IlXTioET0+XI6SjQdPfMGfuAiZiKznOt7g= +github.com/quasilyte/go-ruleguard v0.3.15/go.mod h1:NhuWhnlVEM1gT1A4VJHYfy9MuYSxxwHgxWoPsn9llB4= +github.com/quasilyte/go-ruleguard/dsl v0.3.0/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/quasilyte/go-ruleguard/dsl v0.3.12-0.20220101150716-969a394a9451/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/quasilyte/go-ruleguard/dsl v0.3.12/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/quasilyte/go-ruleguard/dsl v0.3.17/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/quasilyte/go-ruleguard/rules v0.0.0-20201231183845-9e62ed36efe1/go.mod h1:7JTjp89EGyU1d6XfBiXihJNG37wB2VRkd125Q1u7Plc= +github.com/quasilyte/go-ruleguard/rules v0.0.0-20211022131956-028d6511ab71/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50= +github.com/quasilyte/gogrep v0.0.0-20220103110004-ffaa07af02e3 h1:P4QPNn+TK49zJjXKERt/vyPbv/mCHB/zQ4flDYOMN+M= +github.com/quasilyte/gogrep v0.0.0-20220103110004-ffaa07af02e3/go.mod h1:wSEyW6O61xRV6zb6My3HxrQ5/8ke7NE2OayqCHa3xRM= +github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 h1:L8QM9bvf68pVdQ3bCFZMDmnt9yqcMBro1pC7F+IPYMY= +github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= github.com/rinchsan/gosimports v0.1.5 h1:Z/l9lS79z0xgKC6fLJYmDdY44D0LFwo3MzaMtWvMKpY= github.com/rinchsan/gosimports v0.1.5/go.mod h1:102/jU2cwf9fpa/YM9D9o4gSen2Vg8Jl80Sxctgd9N0= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= -github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= -github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryancurrah/gomodguard v1.3.5 h1:cShyguSwUEeC0jS7ylOiG/idnd1TpJ1LfHGpV3oJmPU= -github.com/ryancurrah/gomodguard v1.3.5/go.mod h1:MXlEPQRxgfPQa62O8wzK3Ozbkv9Rkqr+wKjSxTdsNJE= -github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9fJfSfdyCU= -github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ= -github.com/sanposhiho/wastedassign/v2 v2.1.0 h1:crurBF7fJKIORrV85u9UUpePDYGWnwvv3+A96WvwXT0= -github.com/sanposhiho/wastedassign/v2 v2.1.0/go.mod h1:+oSmSC+9bQ+VUAxA66nBb0Z7N8CK7mscKTDYC6aIek4= -github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw= -github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= -github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= -github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= -github.com/sashamelentyev/usestdlibvars v1.28.0 h1:jZnudE2zKCtYlGzLVreNp5pmCdOxXUzwsMDBkR21cyQ= -github.com/sashamelentyev/usestdlibvars v1.28.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8= -github.com/securego/gosec/v2 v2.22.1 h1:IcBt3TpI5Y9VN1YlwjSpM2cHu0i3Iw52QM+PQeg7jN8= -github.com/securego/gosec/v2 v2.22.1/go.mod h1:4bb95X4Jz7VSEPdVjC0hD7C/yR6kdeUBvCPOy9gDQ0g= +github.com/ryancurrah/gomodguard v1.2.3 h1:ww2fsjqocGCAFamzvv/b8IsRduuHHeK2MHTcTxZTQX8= +github.com/ryancurrah/gomodguard v1.2.3/go.mod h1:rYbA/4Tg5c54mV1sv4sQTP5WOPBcoLtnBZ7/TEhXAbg= +github.com/ryanrolds/sqlclosecheck v0.3.0 h1:AZx+Bixh8zdUBxUA1NxbxVAS78vTPq4rCb8OUZI9xFw= +github.com/ryanrolds/sqlclosecheck v0.3.0/go.mod h1:1gREqxyTGR3lVtpngyFo3hZAgk0KCtEdgEkHwDbigdA= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sagikazarmark/crypt v0.1.0/go.mod h1:B/mN0msZuINBtQ1zZLEQcegFJJf9vnYIR88KRMEuODE= +github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= +github.com/sagikazarmark/crypt v0.4.0/go.mod h1:ALv2SRj7GxYV4HO9elxH9nS6M9gW+xDNxqmyJ6RfDFM= +github.com/sanposhiho/wastedassign/v2 v2.0.6 h1:+6/hQIHKNJAUixEj6EmOngGIisyeI+T3335lYTyxRoA= +github.com/sanposhiho/wastedassign/v2 v2.0.6/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/securego/gosec/v2 v2.10.0 h1:l6BET4EzWtyUXCpY2v7N92v0DDCas0L7ngg3bpqbr8g= +github.com/securego/gosec/v2 v2.10.0/go.mod h1:PVq8Ewh/nCN8l/kKC6zrGXSr7m2NmEK6ITIAWMtIaA0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= +github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= +github.com/shirou/gopsutil/v3 v3.22.2/go.mod h1:WapW1AOOPlHyXr+yOyw3uYx36enocrtSoSBy0L5vUHY= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+Wwfd0XE= -github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4= -github.com/sivchari/tenv v1.12.1 h1:+E0QzjktdnExv/wwsnnyk4oqZBUfuh89YMQT1cyuvSY= -github.com/sivchari/tenv v1.12.1/go.mod h1:1LjSOUCc25snIr5n3DtGGrENhX3LuWefcplwVGC24mw= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sivchari/containedctx v1.0.2 h1:0hLQKpgC53OVF1VT7CeoFHk9YKstur1XOgfYIc1yrHI= +github.com/sivchari/containedctx v1.0.2/go.mod h1:PwZOeqm4/DLoJOqMSIJs3aKqXRX4YO+uXww087KZ7Bw= +github.com/sivchari/tenv v1.4.7 h1:FdTpgRlTue5eb5nXIYgS/lyVXSjugU8UUVDwhP1NLU8= +github.com/sivchari/tenv v1.4.7/go.mod h1:5nF+bITvkebQVanjU6IuMbvIot/7ReNsUV7I5NbprB0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/sonatard/noctx v0.1.0 h1:JjqOc2WN16ISWAjAk8M5ej0RfExEXtkEyExl2hLW+OM= -github.com/sonatard/noctx v0.1.0/go.mod h1:0RvBxqY8D4j9cTTTWE8ylt2vqj2EPI8fHmrxHdsaZ2c= -github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= -github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= +github.com/sonatard/noctx v0.0.1 h1:VC1Qhl6Oxx9vvWo3UDgrGXYCeKCe3Wbw7qAWL6FrmTY= +github.com/sonatard/noctx v0.0.1/go.mod h1:9D2D/EoULe8Yy2joDHJj7bv3sZoq9AaSb8B4lqBjiZI= +github.com/sourcegraph/go-diff v0.6.1 h1:hmA1LzxW0n1c3Q4YbrFgg4P99GSnebYa3x8gr0HZqLQ= +github.com/sourcegraph/go-diff v0.6.1/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= -github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= +github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= +github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= -github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= +github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= +github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= -github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= +github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= +github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= +github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= -github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= -github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= +github.com/spf13/viper v1.9.0/go.mod h1:+i6ajR7OX2XaiBkrcZJFK21htRk7eDeLg7+O6bhUPP4= +github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= +github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk= +github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU= github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= -github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8Bg8etvARQ1rpyl4= -github.com/stbenjam/no-sprintf-host-port v0.2.0/go.mod h1:eL0bQ9PasS0hsyTyfTjjG+E80QIyPnBVQbYZyv20Jfk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v0.0.0-20170130113145-4d4bfba8f1d1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 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/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= -github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= -github.com/tdakkota/asciicheck v0.4.0 h1:VZ13Itw4k1i7d+dpDSNS8Op645XgGHpkCEh/WHicgWw= -github.com/tdakkota/asciicheck v0.4.0/go.mod h1:0k7M3rCfRXb0Z6bwgvkEIMleKH3kXNz9UqJ9Xuqopr8= +github.com/sylvia7788/contextcheck v1.0.4 h1:MsiVqROAdr0efZc/fOCt0c235qm9XJqHtWwM+2h2B04= +github.com/sylvia7788/contextcheck v1.0.4/go.mod h1:vuPKJMQ7MQ91ZTqfdyreNKwZjyUg6KO+IebVyQDedZQ= +github.com/tdakkota/asciicheck v0.1.1 h1:PKzG7JUTUmVspQTDqtkX9eSiLGossXTybutHwTXuO0A= +github.com/tdakkota/asciicheck v0.1.1/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA= github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= -github.com/tetafro/godot v1.4.20 h1:z/p8Ek55UdNvzt4TFn2zx2KscpW4rWqcnUrdmvWJj7E= -github.com/tetafro/godot v1.4.20/go.mod h1:2oVxTBSftRTh4+MVfUaUXR6bn2GDXCaMcOG4Dk3rfio= -github.com/timakin/bodyclose v0.0.0-20241017074812-ed6a65f985e3 h1:y4mJRFlM6fUyPhoXuFg/Yu02fg/nIPFMOY8tOqppoFg= -github.com/timakin/bodyclose v0.0.0-20241017074812-ed6a65f985e3/go.mod h1:mkjARE7Yr8qU23YcGMSALbIxTQ9r9QBVahQOBRfU460= -github.com/timonwong/loggercheck v0.10.1 h1:uVZYClxQFpw55eh+PIoqM7uAOHMrhVcDoWDery9R8Lg= -github.com/timonwong/loggercheck v0.10.1/go.mod h1:HEAWU8djynujaAVX7QI65Myb8qgfcZ1uKbdpg3ZzKl8= +github.com/tetafro/godot v1.4.11 h1:BVoBIqAf/2QdbFmSwAWnaIqDivZdOV0ZRwEm6jivLKw= +github.com/tetafro/godot v1.4.11/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= +github.com/timakin/bodyclose v0.0.0-20210704033933-f49887972144 h1:kl4KhGNsJIbDHS9/4U9yQo1UcPQM0kOMJHn29EoH/Ro= +github.com/timakin/bodyclose v0.0.0-20210704033933-f49887972144/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= +github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs= +github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tomarrell/wrapcheck/v2 v2.10.0 h1:SzRCryzy4IrAH7bVGG4cK40tNUhmVmMDuJujy4XwYDg= -github.com/tomarrell/wrapcheck/v2 v2.10.0/go.mod h1:g9vNIyhb5/9TQgumxQyOEqDHsmGYcGsVMOx/xGkqdMo= -github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw= -github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= +github.com/tmc/grpc-websocket-proxy v0.0.0-20200427203606-3cfed13b9966/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tomarrell/wrapcheck/v2 v2.5.0 h1:g27SGGHNoQdvHz4KZA9o4v09RcWzylR+b1yueE5ECiw= +github.com/tomarrell/wrapcheck/v2 v2.5.0/go.mod h1:68bQ/eJg55BROaRTbMjC7vuhL2OgfoG8bLp9ZyoBfyY= +github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4= +github.com/tommy-muehle/go-mnd/v2 v2.5.0 h1:iAj0a8e6+dXSL7Liq0aXPox36FiN1dBbjA6lt9fl65s= +github.com/tommy-muehle/go-mnd/v2 v2.5.0/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ultraware/funlen v0.2.0 h1:gCHmCn+d2/1SemTdYMiKLAHFYxTYz7z9VIDRaTGyLkI= -github.com/ultraware/funlen v0.2.0/go.mod h1:ZE0q4TsJ8T1SQcjmkhN/w+MceuatI6pBFSxxyteHIJA= -github.com/ultraware/whitespace v0.2.0 h1:TYowo2m9Nfj1baEQBjuHzvMRbp19i+RCcRYrSWoFa+g= -github.com/ultraware/whitespace v0.2.0/go.mod h1:XcP1RLD81eV4BW8UhQlpaR+SDc2givTvyI8a586WjW8= -github.com/uudashr/gocognit v1.2.0 h1:3BU9aMr1xbhPlvJLSydKwdLN3tEUUrzPSSM8S4hDYRA= -github.com/uudashr/gocognit v1.2.0/go.mod h1:k/DdKPI6XBZO1q7HgoV2juESI2/Ofj9AcHPZhBBdrTU= -github.com/uudashr/iface v1.3.1 h1:bA51vmVx1UIhiIsQFSNq6GZ6VPTk3WNMZgRiCe9R29U= -github.com/uudashr/iface v1.3.1/go.mod h1:4QvspiRd3JLPAEXBQ9AiZpLbJlrWWgRChOKDJEuQTdg= -github.com/xen0n/gosmopolitan v1.2.2 h1:/p2KTnMzwRexIW8GlKawsTWOxn7UHA+jCMF/V8HHtvU= -github.com/xen0n/gosmopolitan v1.2.2/go.mod h1:7XX7Mj61uLYrj0qmeN0zi7XDon9JRAEhYQqAPLVNTeg= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/ultraware/funlen v0.0.3 h1:5ylVWm8wsNwH5aWo9438pwvsK0QiqVuUrt9bn7S/iLA= +github.com/ultraware/funlen v0.0.3/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= +github.com/ultraware/whitespace v0.0.5 h1:hh+/cpIcopyMYbZNVov9iSxvJU3OYQg78Sfaqzi/CzI= +github.com/ultraware/whitespace v0.0.5/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/uudashr/gocognit v1.0.5 h1:rrSex7oHr3/pPLQ0xoWq108XMU8s678FJcQ+aSfOHa4= +github.com/uudashr/gocognit v1.0.5/go.mod h1:wgYz0mitoKOTysqxTDMOUXg+Jb5SvtihkfmugIZYpEA= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.30.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus= +github.com/valyala/quicktemplate v1.7.0/go.mod h1:sqKJnoaOF88V07vkO+9FL8fb9uZg/VPSJnLYn+LmLk8= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/viki-org/dnscache v0.0.0-20130720023526-c70c1f23c5d8/go.mod h1:dniwbG03GafCjFohMDmz6Zc6oCuiqgH6tGNyXTkHzXE= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM= github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= -github.com/yeya24/promlinter v0.3.0 h1:JVDbMp08lVCP7Y6NP3qHroGAO6z2yGKQtS5JsjqtoFs= -github.com/yeya24/promlinter v0.3.0/go.mod h1:cDfJQQYv9uYciW60QT0eeHlFodotkYZlL+YcPQN+mW4= -github.com/ykadowak/zerologlint v0.1.5 h1:Gy/fMz1dFQN9JZTPjv1hxEk+sRWm05row04Yoolgdiw= -github.com/ykadowak/zerologlint v0.1.5/go.mod h1:KaUskqF3e/v59oPmdq1U1DnKcuHokl2/K1U4pmIELKg= +github.com/yeya24/promlinter v0.1.1-0.20210918184747-d757024714a1 h1:YAaOqqMTstELMMGblt6yJ/fcOt4owSYuw3IttMnKfAM= +github.com/yeya24/promlinter v0.1.1-0.20210918184747-d757024714a1/go.mod h1:rs5vtZzeBHqqMwXqFScncpCF6u06lezhZepno9AB1Oc= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo= -gitlab.com/bosi/decorder v0.4.2/go.mod h1:muuhHoaJkA9QLcYHq4Mj8FJUwDZ+EirSHRiaTcTf6T8= -go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ= -go-simpler.org/assert v0.9.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= -go-simpler.org/musttag v0.13.0 h1:Q/YAW0AHvaoaIbsPj3bvEI5/QFP7w696IMUpnKXQfCE= -go-simpler.org/musttag v0.13.0/go.mod h1:FTzIGeK6OkKlUDVpj0iQUXZLUO1Js9+mvykDQy9C5yM= -go-simpler.org/sloglint v0.9.0 h1:/40NQtjRx9txvsB/RN022KsUJU+zaaSb/9q9BSefSrE= -go-simpler.org/sloglint v0.9.0/go.mod h1:G/OrAF6uxj48sHahCzrbarVMptL2kjWTaUeC8+fOGww= +github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +gitlab.com/bosi/decorder v0.2.1 h1:ehqZe8hI4w7O4b1vgsDZw1YU1PE7iJXrQWFMsocbQ1w= +gitlab.com/bosi/decorder v0.2.1/go.mod h1:6C/nhLSbF6qZbYD8bRmISBwc6vcWdNsiIBkRvjJFrH0= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/etcd v0.0.0-20200513171258-e048e166ab9c/go.mod h1:xCI7ZzBfRuGgBXyXO6yfWfDmlWd35khcWpUa4L0xI/k= +go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= +go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs= +go.mozilla.org/mozlog v0.0.0-20170222151521-4bb13139d403/go.mod h1:jHoPAGnDrCy6kaI2tAze5Prf0Nr0w/oNkROt2lw3n3o= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= -go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= -go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +golang.org/x/crypto v0.0.0-20180501155221-613d6eafa307/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +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/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -701,12 +909,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= -golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= -golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac h1:TSSpLIG4v+p0rPv1pNOQtl1I8knsO4S9trOxNMOLVP4= -golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -719,6 +922,8 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -727,20 +932,17 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= -golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -755,6 +957,9 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -762,55 +967,72 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= -golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= -golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -819,12 +1041,21 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -833,70 +1064,86 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/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-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/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-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= -golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.0.0-20211213223007-03aa0b5f6827/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-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +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/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= -golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190307163923-6a08e3108db3/go.mod h1:25r3+/G6/xytQM8iWZKq3Hn0kr0rgFKPUNVEL/dr3z4= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190321232350-e250d351ecad/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -905,16 +1152,25 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190916130336-e45ffcd953cc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +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/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117220505-0cba7a3a9ee9/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -927,38 +1183,64 @@ golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200414032229-332987a829c3/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200422022333-3d57cf2e726e/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200622203043-20e05c1c8ffa/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200624225443-88f3c62a19ff/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200625211823-6506e20df31f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200630154851-b2d8b0336632/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200706234117-b22de6825cf7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200812195022-5ae4c3c160a0/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200831203904-5a2aa26beb65/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= +golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201028025901-8cd080b735b3/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201114224030-61ea331ec02b/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201230224404-63754364767c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.9-0.20211228192929-ee1ca4ffc4da/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= -golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= -golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= -golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= @@ -971,13 +1253,34 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw= +google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181107211654-5fc9ac540362/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -985,6 +1288,7 @@ google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= @@ -998,27 +1302,85 @@ google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200626011028-ee7919e894b5/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200707001353-8e8330bf89df/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.0/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1031,32 +1393,41 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= -google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 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/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= -gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.63.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI= +gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.6/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1064,12 +1435,17 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.6.0 h1:TAODvD3knlq75WCp2nyGJtT4LeRV/o7NN9nYPeVJXf8= -honnef.co/go/tools v0.6.0/go.mod h1:3puzxxljPCe8RGJX7BIy1plGbxEOZni5mR2aXe3/uk4= -mvdan.cc/gofumpt v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU= -mvdan.cc/gofumpt v0.7.0/go.mod h1:txVFJy/Sc/mvaycET54pV8SW8gWxTlUuGHVEcncmNUo= -mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f h1:lMpcwN6GxNbWtbpI1+xzFLSW8XzX0u72NttUGVFjO3U= -mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f/go.mod h1:RSLa7mKKCNeTTMHBw5Hsy2rfJmd6O2ivt9Dw9ZqCQpQ= +honnef.co/go/tools v0.2.2 h1:MNh1AVMyVX23VUHE2O27jm6lNj3vjO5DexS4A1xvnzk= +honnef.co/go/tools v0.2.2/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY= +mvdan.cc/gofumpt v0.3.0 h1:kTojdZo9AcEYbQYhGuLf/zszYthRdhDNDUi2JKTxas4= +mvdan.cc/gofumpt v0.3.0/go.mod h1:0+VyGZWleeIj5oostkOex+nDBA0eyavuDnDusAJ8ylo= +mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= +mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= +mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo= +mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= +mvdan.cc/unparam v0.0.0-20211214103731-d0ef000c54e5 h1:Jh3LAeMt1eGpxomyu3jVkmVZWW2MxZ1qIIV2TZ/nRio= +mvdan.cc/unparam v0.0.0-20211214103731-d0ef000c54e5/go.mod h1:b8RRCBm0eeiWR8cfN88xeq2G5SG3VKGO+5UPWi5FSOY= 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= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= diff --git a/version.go b/version.go index 2a81a6c..82a6c1e 100644 --- a/version.go +++ b/version.go @@ -25,7 +25,7 @@ const ( // Please update release_notes.md when updating this! appMajor uint = 0 appMinor uint = 2 - appPatch uint = 16 + appPatch uint = 11 // appPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec.