From e1f12b71a1075ba3b8bdaf1c21e548b88f10c977 Mon Sep 17 00:00:00 2001 From: Slyghtning Date: Wed, 2 Sep 2026 16:06:45 +0200 Subject: [PATCH 1/5] assets: Add shared asset HTLC kit Move the existing server asset HTLC contract into Loop so both sides can derive and spend the same commitment. Freeze the legacy vectors and bind witness construction to verified proofs, prevouts, and input indices. Reserve future policies so Loop Asset Out can choose its contract explicitly instead of inheriting the deposit key path. --- assets/htlc/doc.go | 8 + assets/htlc/script.go | 125 ++++ assets/htlc/swapkit.go | 917 ++++++++++++++++++++++++++ assets/htlc/swapkit_test.go | 1226 +++++++++++++++++++++++++++++++++++ go.mod | 2 + go.sum | 1077 ++++++++++++++++++++++++++++++ 6 files changed, 3355 insertions(+) create mode 100644 assets/htlc/doc.go create mode 100644 assets/htlc/script.go create mode 100644 assets/htlc/swapkit.go create mode 100644 assets/htlc/swapkit_test.go diff --git a/assets/htlc/doc.go b/assets/htlc/doc.go new file mode 100644 index 000000000..ba30f82de --- /dev/null +++ b/assets/htlc/doc.go @@ -0,0 +1,8 @@ +// Package htlc defines the shared, versioned Taproot Asset HTLC construction +// used by Loop and the Loop server. +// +// LegacyDepositV0 preserves the server's existing asset deposit contract. A +// new protocol must add and explicitly select its own policy before it can +// construct a contract, so this compatibility layer does not silently choose +// the on-chain terms of a future Loop Asset Out protocol. +package htlc diff --git a/assets/htlc/script.go b/assets/htlc/script.go new file mode 100644 index 000000000..af65296e6 --- /dev/null +++ b/assets/htlc/script.go @@ -0,0 +1,125 @@ +package htlc + +import ( + "fmt" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" + "github.com/decred/dcrd/dcrec/secp256k1/v4" + "github.com/lightninglabs/taproot-assets/asset" + "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/keychain" + "github.com/lightningnetwork/lnd/lntypes" +) + +// GenSuccessPathScript constructs the success payment path. The final +// relative lock of one block is part of the version-zero contract and must not +// be changed without introducing a new contract version. +func GenSuccessPathScript(receiverHtlcKey *btcec.PublicKey, + swapHash lntypes.Hash) ([]byte, error) { + + if receiverHtlcKey == nil { + return nil, fmt.Errorf("receiver HTLC key is required") + } + + builder := txscript.NewScriptBuilder() + builder.AddData(schnorr.SerializePubKey(receiverHtlcKey)) + builder.AddOp(txscript.OP_CHECKSIGVERIFY) + builder.AddOp(txscript.OP_SIZE) + builder.AddInt64(32) + builder.AddOp(txscript.OP_EQUALVERIFY) + builder.AddOp(txscript.OP_HASH160) + builder.AddData(input.Ripemd160H(swapHash[:])) + builder.AddOp(txscript.OP_EQUALVERIFY) + builder.AddInt64(int64(SuccessSequence)) + builder.AddOp(txscript.OP_CHECKSEQUENCEVERIFY) + + return builder.Script() +} + +// GenTimeoutPathScript constructs the timeout payment path. +func GenTimeoutPathScript(senderHtlcKey *btcec.PublicKey, csvExpiry int64) ( + []byte, error) { + + if senderHtlcKey == nil { + return nil, fmt.Errorf("sender HTLC key is required") + } + if csvExpiry <= 0 { + return nil, fmt.Errorf("CSV expiry must be positive") + } + if csvExpiry > int64(wire.SequenceLockTimeMask) { + return nil, fmt.Errorf("CSV expiry exceeds block-based BIP68 range") + } + + builder := txscript.NewScriptBuilder() + builder.AddData(schnorr.SerializePubKey(senderHtlcKey)) + builder.AddOp(txscript.OP_CHECKSIGVERIFY) + builder.AddInt64(csvExpiry) + builder.AddOp(txscript.OP_CHECKSEQUENCEVERIFY) + + return builder.Script() +} + +// GetOpTrueScript returns a script that always evaluates to true. +func GetOpTrueScript() ([]byte, error) { + return txscript.NewScriptBuilder().AddOp(txscript.OP_TRUE).Script() +} + +// CreateOpTrueLeaf creates the legacy Taproot Asset script key whose only +// script path is OP_TRUE beneath the public Taproot Assets NUMS key. +func CreateOpTrueLeaf() (asset.ScriptKey, txscript.TapLeaf, + *txscript.IndexedTapScriptTree, *txscript.ControlBlock, error) { + + tapScript, err := GetOpTrueScript() + if err != nil { + return asset.ScriptKey{}, txscript.TapLeaf{}, nil, nil, err + } + + tapLeaf := txscript.NewBaseTapLeaf(tapScript) + tree := txscript.AssembleTaprootScriptTree(tapLeaf) + rootHash := tree.RootNode.TapHash() + tapKey := txscript.ComputeTaprootOutputKey( + asset.NUMSPubKey, rootHash[:], + ) + + controlBlock := &txscript.ControlBlock{ + LeafVersion: txscript.BaseLeafVersion, + InternalKey: asset.NUMSPubKey, + } + tapScriptKey := asset.ScriptKey{ + PubKey: tapKey, + TweakedScriptKey: &asset.TweakedScriptKey{ + RawKey: keychain.KeyDescriptor{ + PubKey: asset.NUMSPubKey, + }, + Tweak: rootHash[:], + }, + } + if tapKey.SerializeCompressed()[0] == + secp256k1.PubKeyFormatCompressedOdd { + + controlBlock.OutputKeyYIsOdd = true + } + + return tapScriptKey, tapLeaf, tree, controlBlock, nil +} + +// GetOpTrueScriptKey returns the compressed legacy OP_TRUE Taproot Asset +// script key. +func GetOpTrueScriptKey() ([]byte, error) { + opTrueScriptKey, _, _, _, err := CreateOpTrueLeaf() + if err != nil { + return nil, err + } + + scriptKey, err := schnorr.ParsePubKey( + opTrueScriptKey.PubKey.SerializeCompressed()[1:], + ) + if err != nil { + return nil, err + } + + return scriptKey.SerializeCompressed(), nil +} diff --git a/assets/htlc/swapkit.go b/assets/htlc/swapkit.go new file mode 100644 index 000000000..71e1c3600 --- /dev/null +++ b/assets/htlc/swapkit.go @@ -0,0 +1,917 @@ +package htlc + +import ( + "bytes" + "context" + "fmt" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/btcsuite/btcd/btcutil/psbt" + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" + "github.com/decred/dcrd/dcrec/secp256k1/v4" + "github.com/lightninglabs/lndclient" + "github.com/lightninglabs/taproot-assets/address" + "github.com/lightninglabs/taproot-assets/asset" + "github.com/lightninglabs/taproot-assets/commitment" + "github.com/lightninglabs/taproot-assets/proof" + "github.com/lightninglabs/taproot-assets/tappsbt" + "github.com/lightninglabs/taproot-assets/tapscript" + "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/keychain" + "github.com/lightningnetwork/lnd/lntypes" +) + +const ( + // SuccessSequence is the relative lock used by the success path. It is + // part of the legacy version-zero policy. + SuccessSequence uint32 = 1 + + // rawSimNetHDCoinType is the BIP-0044 coin type used by btcd's native + // simnet parameters. LND deliberately uses the testnet coin type for + // simnet instead, so both forms need explicit, stable definitions. + rawSimNetHDCoinType uint32 = 115 +) + +// Policy identifies an immutable version of an asset HTLC contract. New +// protocols must use distinct policies so they cannot silently change an +// existing on-chain contract. +type Policy uint8 + +const ( + // PolicyUnknown reserves the zero value so every caller must choose the + // protocol whose compatibility rules it expects. + PolicyUnknown Policy = iota + + // LegacyDepositV0 preserves the asset deposit HTLC contract that predates + // this shared package. + LegacyDepositV0 +) + +// Params contains the validated inputs used to construct a SwapKit. +type Params struct { + SenderPubKey *btcec.PublicKey + ReceiverPubKey *btcec.PublicKey + AssetID asset.ID + Amount uint64 + SwapHash lntypes.Hash + CsvExpiry uint32 + AddressParams *address.ChainParams +} + +// SwapKit holds the immutable information required to construct and spend an +// on-chain Taproot Asset HTLC. NewSwapKit is the only constructor so a funded +// contract cannot later be changed by mutating a key, hash, amount, or expiry. +type SwapKit struct { + policy Policy + senderPubKey *btcec.PublicKey + receiverPubKey *btcec.PublicKey + assetID asset.ID + amount uint64 + swapHash lntypes.Hash + csvExpiry uint32 + addressParams address.ChainParams +} + +// NewSwapKit returns a defensively validated asset HTLC kit. +func NewSwapKit(policy Policy, params Params) (*SwapKit, error) { + if params.SenderPubKey == nil { + return nil, fmt.Errorf("sender public key is required") + } + if params.ReceiverPubKey == nil { + return nil, fmt.Errorf("receiver public key is required") + } + if params.AddressParams == nil { + return nil, fmt.Errorf("address parameters are required") + } + if params.AddressParams.Params == nil || params.AddressParams.TapHRP == "" { + return nil, fmt.Errorf("address parameters are incomplete") + } + canonicalParams, err := canonicalAddressParams(params.AddressParams) + if err != nil { + return nil, err + } + + senderKey, err := btcec.ParsePubKey( + params.SenderPubKey.SerializeCompressed(), + ) + if err != nil { + return nil, fmt.Errorf("invalid sender public key: %w", err) + } + receiverKey, err := btcec.ParsePubKey( + params.ReceiverPubKey.SerializeCompressed(), + ) + if err != nil { + return nil, fmt.Errorf("invalid receiver public key: %w", err) + } + if senderKey.IsEqual(receiverKey) { + return nil, fmt.Errorf("sender and receiver keys must differ") + } + + addressParams := cloneAddressParams(*canonicalParams) + kit := &SwapKit{ + policy: policy, + senderPubKey: senderKey, + receiverPubKey: receiverKey, + assetID: params.AssetID, + amount: params.Amount, + swapHash: params.SwapHash, + csvExpiry: params.CsvExpiry, + addressParams: *addressParams, + } + if err := kit.Validate(); err != nil { + return nil, err + } + + return kit, nil +} + +// canonicalAddressParams returns the supported network parameters matching the +// caller's Taproot Asset address tuple. +func canonicalAddressParams(params *address.ChainParams) ( + *address.ChainParams, error) { + + rawSimNet := cloneAddressParams(address.SimNetTap) + rawSimNet.HDCoinType = rawSimNetHDCoinType + lndSimNet := cloneAddressParams(address.SimNetTap) + lndSimNet.HDCoinType = address.TestNet3Tap.HDCoinType + + knownNetworks := []*address.ChainParams{ + &address.MainNetTap, + &address.TestNet3Tap, + &address.TestNet4Tap, + &address.RegressionNetTap, + &address.SigNetTap, + rawSimNet, + lndSimNet, + } + for _, known := range knownNetworks { + if params.TapHRP != known.TapHRP || params.Net != known.Net || + params.HDCoinType != known.HDCoinType { + + continue + } + + return cloneAddressParams(*known), nil + } + + return nil, fmt.Errorf("unsupported or mismatched address parameters") +} + +// Policy returns the immutable contract policy. +func (s *SwapKit) Policy() Policy { + return s.policy +} + +// SenderPubKey returns the sender's refund public key. +func (s *SwapKit) SenderPubKey() *btcec.PublicKey { + key, _ := btcec.ParsePubKey(s.senderPubKey.SerializeCompressed()) + + return key +} + +// ReceiverPubKey returns the receiver's claim public key. +func (s *SwapKit) ReceiverPubKey() *btcec.PublicKey { + key, _ := btcec.ParsePubKey(s.receiverPubKey.SerializeCompressed()) + + return key +} + +// AssetID returns the exact asset identifier. +func (s *SwapKit) AssetID() asset.ID { + return s.assetID +} + +// Amount returns the amount in the asset's native unit. +func (s *SwapKit) Amount() uint64 { + return s.amount +} + +// SwapHash returns the payment hash committed to by the success path. +func (s *SwapKit) SwapHash() lntypes.Hash { + return s.swapHash +} + +// CsvExpiry returns the sender's block-based relative refund delay. +func (s *SwapKit) CsvExpiry() uint32 { + return s.csvExpiry +} + +// AddressParams returns a copy of the contract's address parameters. +func (s *SwapKit) AddressParams() address.ChainParams { + return *cloneAddressParams(s.addressParams) +} + +// cloneAddressParams returns an independent copy of address parameters, +// including the nested Bitcoin network parameters when present. +func cloneAddressParams(params address.ChainParams) *address.ChainParams { + paramsCopy := params + if params.Params != nil { + bitcoinParams := *params.Params + paramsCopy.Params = &bitcoinParams + } + + return ¶msCopy +} + +// Validate verifies every field required to create an HTLC virtual packet. +func (s *SwapKit) Validate() error { + if err := s.validateScripts(); err != nil { + return err + } + if s.amount == 0 { + return fmt.Errorf("asset amount must be positive") + } + if s.assetID == (asset.ID{}) { + return fmt.Errorf("asset ID is required") + } + if s.swapHash == (lntypes.Hash{}) { + return fmt.Errorf("swap hash is required") + } + + return nil +} + +// validateScripts checks the immutable policy inputs used to derive the HTLC +// script tree. +func (s *SwapKit) validateScripts() error { + if s == nil { + return fmt.Errorf("swap kit is required") + } + if s.policy != LegacyDepositV0 { + return fmt.Errorf("unknown asset HTLC policy: %d", s.policy) + } + if s.senderPubKey == nil { + return fmt.Errorf("sender public key is required") + } + if s.receiverPubKey == nil { + return fmt.Errorf("receiver public key is required") + } + if s.csvExpiry <= SuccessSequence { + return fmt.Errorf("CSV expiry must exceed success sequence") + } + if s.csvExpiry > wire.SequenceLockTimeMask { + return fmt.Errorf("CSV expiry exceeds block-based BIP68 range") + } + + return nil +} + +// GetSuccessScript returns the success path script of the swap HTLC. +func (s *SwapKit) GetSuccessScript() ([]byte, error) { + if s == nil || s.receiverPubKey == nil { + return nil, fmt.Errorf("receiver public key is required") + } + if s.policy != LegacyDepositV0 { + return nil, fmt.Errorf("unknown asset HTLC policy: %d", s.policy) + } + + return GenSuccessPathScript(s.receiverPubKey, s.swapHash) +} + +// GetTimeoutScript returns the timeout path script of the swap HTLC. +func (s *SwapKit) GetTimeoutScript() ([]byte, error) { + if s == nil { + return nil, fmt.Errorf("swap kit is required") + } + if s.policy != LegacyDepositV0 { + return nil, fmt.Errorf("unknown asset HTLC policy: %d", s.policy) + } + + return GenTimeoutPathScript(s.senderPubKey, int64(s.csvExpiry)) +} + +// GetAggregateKey returns the sorted MuSig2 aggregate key used in the swap +// HTLC. The key is deliberately returned before any Taproot tweak is applied. +func (s *SwapKit) GetAggregateKey() (*btcec.PublicKey, error) { + if err := s.validateScripts(); err != nil { + return nil, err + } + + aggregateKey, err := input.MuSig2CombineKeys( + input.MuSig2Version100RC2, + []*btcec.PublicKey{s.senderPubKey, s.receiverPubKey}, true, + &input.MuSig2Tweaks{}, + ) + if err != nil { + return nil, err + } + + return aggregateKey.PreTweakedKey, nil +} + +// GetTimeoutLeaf returns the timeout leaf of the swap. +func (s *SwapKit) GetTimeoutLeaf() (txscript.TapLeaf, error) { + timeoutScript, err := s.GetTimeoutScript() + if err != nil { + return txscript.TapLeaf{}, err + } + + return txscript.NewBaseTapLeaf(timeoutScript), nil +} + +// GetTimeOutLeaf returns the timeout leaf of the swap. The historical method +// capitalization is retained while callers migrate to GetTimeoutLeaf. +func (s *SwapKit) GetTimeOutLeaf() (txscript.TapLeaf, error) { + return s.GetTimeoutLeaf() +} + +// GetSuccessLeaf returns the success leaf of the swap. +func (s *SwapKit) GetSuccessLeaf() (txscript.TapLeaf, error) { + successScript, err := s.GetSuccessScript() + if err != nil { + return txscript.TapLeaf{}, err + } + + return txscript.NewBaseTapLeaf(successScript), nil +} + +// GetSiblingPreimage returns the branch preimage placed beside the Taproot +// Asset commitment in the Bitcoin output tree. +func (s *SwapKit) GetSiblingPreimage() ( + commitment.TapscriptPreimage, error) { + + timeoutLeaf, err := s.GetTimeoutLeaf() + if err != nil { + return commitment.TapscriptPreimage{}, err + } + + successLeaf, err := s.GetSuccessLeaf() + if err != nil { + return commitment.TapscriptPreimage{}, err + } + + branch := txscript.NewTapBranch(timeoutLeaf, successLeaf) + + return commitment.NewPreimageFromBranch(branch), nil +} + +// CreateHtlcVpkt creates the version-one virtual packet for the HTLC. The +// split-root and HTLC output indices and their interactive flags are consensus +// with the existing server implementation. +func (s *SwapKit) CreateHtlcVpkt() (*tappsbt.VPacket, error) { + if err := s.Validate(); err != nil { + return nil, err + } + + btcInternalKey, err := s.GetAggregateKey() + if err != nil { + return nil, err + } + + siblingPreimage, err := s.GetSiblingPreimage() + if err != nil { + return nil, err + } + + tapScriptKey, _, _, _, err := CreateOpTrueLeaf() + if err != nil { + return nil, err + } + + pkt := &tappsbt.VPacket{ + Inputs: []*tappsbt.VInput{{ + PrevID: asset.PrevID{ID: s.assetID}, + }}, + Outputs: make([]*tappsbt.VOutput, 0, 2), + ChainParams: cloneAddressParams(s.addressParams), + Version: tappsbt.V1, + } + pkt.Outputs = append(pkt.Outputs, &tappsbt.VOutput{ + AssetVersion: asset.V1, + Amount: 0, + Type: tappsbt.TypeSplitRoot, + AnchorOutputIndex: 0, + ScriptKey: asset.NUMSScriptKey, + Interactive: true, + }) + pkt.Outputs = append(pkt.Outputs, &tappsbt.VOutput{ + AssetVersion: asset.V1, + Amount: s.amount, + Interactive: true, + AnchorOutputIndex: 1, + ScriptKey: asset.NewScriptKey(tapScriptKey.PubKey), + AnchorOutputInternalKey: btcInternalKey, + AnchorOutputTapscriptSibling: &siblingPreimage, + }) + + return pkt, nil +} + +// GenTimeoutBtcControlBlock generates the Bitcoin control block for the +// timeout path. The supplied root must be the exact Taproot Asset commitment +// root committed to by the anchor output. +func (s *SwapKit) GenTimeoutBtcControlBlock(taprootAssetRoot []byte) ( + *txscript.ControlBlock, error) { + + return s.genBtcControlBlock(false, taprootAssetRoot) +} + +// GenSuccessBtcControlBlock generates the Bitcoin control block for the +// success path. +func (s *SwapKit) GenSuccessBtcControlBlock(taprootAssetRoot []byte) ( + *txscript.ControlBlock, error) { + + return s.genBtcControlBlock(true, taprootAssetRoot) +} + +// GetPkScriptFromRoot returns the Bitcoin anchor script for an exact Taproot +// Asset commitment root. +func (s *SwapKit) GetPkScriptFromRoot(taprootAssetRoot []byte) ( + []byte, error) { + + controlBlock, err := s.GenSuccessBtcControlBlock(taprootAssetRoot) + if err != nil { + return nil, err + } + successScript, err := s.GetSuccessScript() + if err != nil { + return nil, err + } + + rootHash := controlBlock.RootHash(successScript) + internalKey, err := s.GetAggregateKey() + if err != nil { + return nil, err + } + outputKey := txscript.ComputeTaprootOutputKey(internalKey, rootHash) + + return txscript.PayToTaprootScript(outputKey) +} + +// genBtcControlBlock derives a control block for either the success or timeout +// leaf under the proof-derived Taproot Asset root. +func (s *SwapKit) genBtcControlBlock(success bool, + taprootAssetRoot []byte) (*txscript.ControlBlock, error) { + + if len(taprootAssetRoot) != 32 { + return nil, fmt.Errorf("Taproot Asset root must be 32 bytes") + } + + internalKey, err := s.GetAggregateKey() + if err != nil { + return nil, err + } + + timeoutLeaf, err := s.GetTimeoutLeaf() + if err != nil { + return nil, err + } + successLeaf, err := s.GetSuccessLeaf() + if err != nil { + return nil, err + } + + spendLeaf := timeoutLeaf + siblingLeaf := successLeaf + if success { + spendLeaf = successLeaf + siblingLeaf = timeoutLeaf + } + + siblingHash := siblingLeaf.TapHash() + inclusionProof := make([]byte, 0, 64) + inclusionProof = append(inclusionProof, siblingHash[:]...) + inclusionProof = append(inclusionProof, taprootAssetRoot...) + + controlBlock := &txscript.ControlBlock{ + InternalKey: internalKey, + LeafVersion: txscript.BaseLeafVersion, + InclusionProof: inclusionProof, + } + + rootHash := controlBlock.RootHash(spendLeaf.Script) + tapKey := txscript.ComputeTaprootOutputKey(internalKey, rootHash) + if tapKey.SerializeCompressed()[0] == + secp256k1.PubKeyFormatCompressedOdd { + + controlBlock.OutputKeyYIsOdd = true + } + + return controlBlock, nil +} + +// GenTaprootAssetRootFromProof verifies the inclusion, exclusion, and optional +// split-root commitment proofs before returning the committed Taproot Asset +// root. It does not verify proof provenance, chain inclusion, confirmation +// depth, or whether the anchor outpoint remains unspent. +func GenTaprootAssetRootFromProof(assetProof *proof.Proof) ([]byte, error) { + if assetProof == nil { + return nil, fmt.Errorf("asset proof is required") + } + + assetCommitment, err := assetProof.VerifyProofs() + if err != nil { + return nil, fmt.Errorf("invalid asset proof: %w", err) + } + + taprootAssetRoot := assetCommitment.TapscriptRoot(nil) + + return taprootAssetRoot[:], nil +} + +// GetPkScriptFromProof returns the top-level Bitcoin script that commits to +// the verified proof's exact Taproot Asset commitment under this kit's HTLC +// tree. The proof is required because an asset alone does not identify its +// anchor commitment version or any co-anchored leaves. +func (s *SwapKit) GetPkScriptFromProof(assetProof *proof.Proof) ( + []byte, error) { + + if assetProof == nil { + return nil, fmt.Errorf("asset proof is required") + } + if err := s.validateAsset(&assetProof.Asset); err != nil { + return nil, err + } + + taprootAssetRoot, err := GenTaprootAssetRootFromProof(assetProof) + if err != nil { + return nil, err + } + + return s.GetPkScriptFromRoot(taprootAssetRoot) +} + +// validateAsset binds an asset leaf to the exact HTLC identity, amount, and +// script policy. +func (s *SwapKit) validateAsset(htlcAsset *asset.Asset) error { + if err := s.validateScripts(); err != nil { + return err + } + if s.amount == 0 { + return fmt.Errorf("asset amount must be positive") + } + if htlcAsset == nil { + return fmt.Errorf("asset is required") + } + + proofID := htlcAsset.Genesis.ID() + if !bytes.Equal(s.assetID[:], proofID[:]) { + return fmt.Errorf("asset proof ID does not match swap") + } + if htlcAsset.Amount != s.amount { + return fmt.Errorf("asset proof amount does not match swap") + } + if htlcAsset.Version != asset.V0 && + htlcAsset.Version != asset.V1 { + + return fmt.Errorf("unsupported legacy deposit asset version") + } + if htlcAsset.ScriptVersion != asset.ScriptV0 { + return fmt.Errorf("asset proof script version does not match swap") + } + if htlcAsset.LockTime != 0 || htlcAsset.RelativeLockTime != 0 { + return fmt.Errorf("asset proof contains an unexpected locktime") + } + + expectedScriptKey, _, _, _, err := CreateOpTrueLeaf() + if err != nil { + return err + } + expectedScriptKey = asset.NewScriptKey(expectedScriptKey.PubKey) + if htlcAsset.ScriptKey.PubKey == nil || + !htlcAsset.ScriptKey.PubKey.IsEqual(expectedScriptKey.PubKey) { + + return fmt.Errorf("asset proof script key does not match swap") + } + + return nil +} + +type validatedSweep struct { + assetInputIndex int + prevOutputs []*wire.TxOut + assetRoot []byte +} + +// SpendWitness binds a witness stack to the exact transaction input selected +// by the proof outpoint. +type SpendWitness struct { + InputIndex uint32 + Witness wire.TxWitness +} + +// findUniqueInput returns the sole transaction input that spends outpoint. +func findUniqueInput(tx *wire.MsgTx, outpoint wire.OutPoint) (int, error) { + inputIndex := -1 + for idx, txIn := range tx.TxIn { + if txIn == nil { + return 0, fmt.Errorf("sweep input %d is nil", idx) + } + if txIn.PreviousOutPoint != outpoint { + continue + } + if inputIndex >= 0 { + return 0, fmt.Errorf("proof outpoint appears more than once") + } + + inputIndex = idx + } + if inputIndex < 0 { + return 0, fmt.Errorf("asset input does not spend proof outpoint") + } + + return inputIndex, nil +} + +// validateSweep binds a PSBT input and witness UTXO to the HTLC proof and +// reconstructs the exact Taproot output being spent. +func (s *SwapKit) validateSweep(assetProof *proof.Proof, + sweepPacket *psbt.Packet) (*validatedSweep, error) { + + if assetProof == nil { + return nil, fmt.Errorf("asset proof is required") + } + if err := s.validateAsset(&assetProof.Asset); err != nil { + return nil, err + } + assetCommitment, err := assetProof.VerifyProofs() + if err != nil { + return nil, fmt.Errorf("invalid asset proof: %w", err) + } + assetRootHash := assetCommitment.TapscriptRoot(nil) + assetRoot := append([]byte(nil), assetRootHash[:]...) + if sweepPacket == nil || sweepPacket.UnsignedTx == nil { + return nil, fmt.Errorf("sweep PSBT is required") + } + if len(sweepPacket.UnsignedTx.TxIn) == 0 || + len(sweepPacket.UnsignedTx.TxIn) != len(sweepPacket.Inputs) { + + return nil, fmt.Errorf("sweep PSBT input metadata is incomplete") + } + if sweepPacket.UnsignedTx.Version < 2 { + return nil, fmt.Errorf("sweep transaction must use version 2") + } + + proofOutpoint := assetProof.OutPoint() + assetInputIndex, err := findUniqueInput( + sweepPacket.UnsignedTx, proofOutpoint, + ) + if err != nil { + return nil, err + } + prevOutputs := make([]*wire.TxOut, len(sweepPacket.Inputs)) + for idx := range sweepPacket.Inputs { + witnessUtxo := sweepPacket.Inputs[idx].WitnessUtxo + if witnessUtxo == nil { + return nil, fmt.Errorf( + "sweep input %d requires a witness UTXO", idx, + ) + } + prevOutputs[idx] = &wire.TxOut{ + Value: witnessUtxo.Value, + PkScript: append([]byte(nil), witnessUtxo.PkScript...), + } + } + siblingPreimage, err := s.GetSiblingPreimage() + if err != nil { + return nil, err + } + siblingHash, err := siblingPreimage.TapHash() + if err != nil { + return nil, err + } + internalKey, err := s.GetAggregateKey() + if err != nil { + return nil, err + } + expectedPkScript, err := tapscript.PayToAddrScript( + *internalKey, siblingHash, *assetCommitment, + ) + if err != nil { + return nil, err + } + proofOutputIndex := int(proofOutpoint.Index) + if proofOutputIndex >= len(assetProof.AnchorTx.TxOut) { + return nil, fmt.Errorf("proof output index is out of bounds") + } + proofTxOut := assetProof.AnchorTx.TxOut[proofOutputIndex] + if proofTxOut == nil { + return nil, fmt.Errorf("proof anchor output is nil") + } + assetPrevOut := prevOutputs[assetInputIndex] + if proofTxOut.Value != assetPrevOut.Value || + !bytes.Equal(proofTxOut.PkScript, assetPrevOut.PkScript) { + + return nil, fmt.Errorf("asset prevout does not match proof anchor") + } + if !bytes.Equal(expectedPkScript, assetPrevOut.PkScript) { + return nil, fmt.Errorf("asset input script does not match proof") + } + + return &validatedSweep{ + assetInputIndex: assetInputIndex, + prevOutputs: prevOutputs, + assetRoot: assetRoot, + }, nil +} + +// AssetInputIndex returns the unique input that spends the proof outpoint. It +// validates all PSBT prevouts and the proof-bound anchor output before exposing +// the index. Callers use this index to set the required relative sequence +// before asking the kit to sign. +func (s *SwapKit) AssetInputIndex(assetProof *proof.Proof, + sweepPacket *psbt.Packet) (uint32, error) { + + sweep, err := s.validateSweep(assetProof, sweepPacket) + if err != nil { + return 0, err + } + + return uint32(sweep.assetInputIndex), nil +} + +// validateSequence requires the proof-selected input to use the contract's +// relative lock value before a witness is signed. +func validateSequence(sweep *validatedSweep, sweepPacket *psbt.Packet, + required uint32) error { + + sequence := sweepPacket.UnsignedTx.TxIn[sweep.assetInputIndex].Sequence + if sequence != required { + return fmt.Errorf( + "asset input sequence must be %d, got %d", + required, sequence, + ) + } + + return nil +} + +// verifyTapscriptSignature checks a signer response against the exact input, +// prevouts, script, and public key used by an HTLC spend. +func verifyTapscriptSignature(tx *wire.MsgTx, sweep *validatedSweep, + witnessScript []byte, pubKey *btcec.PublicKey, signature []byte) error { + + parsedSignature, err := schnorr.ParseSignature(signature) + if err != nil { + return fmt.Errorf("signer returned an invalid Schnorr signature: %w", + err) + } + + prevOutFetcher := txscript.NewMultiPrevOutFetcher(nil) + for idx, txIn := range tx.TxIn { + prevOutFetcher.AddPrevOut( + txIn.PreviousOutPoint, sweep.prevOutputs[idx], + ) + } + sigHashes := txscript.NewTxSigHashes(tx, prevOutFetcher) + tapLeaf := txscript.NewBaseTapLeaf(witnessScript) + sigHash, err := txscript.CalcTapscriptSignaturehash( + sigHashes, txscript.SigHashDefault, tx, + sweep.assetInputIndex, prevOutFetcher, tapLeaf, + ) + if err != nil { + return fmt.Errorf("unable to calculate asset input sighash: %w", err) + } + if !parsedSignature.Verify(sigHash, pubKey) { + return fmt.Errorf("signer returned a signature for the wrong key") + } + + return nil +} + +// CreatePreimageWitness signs the exact proof-bound asset input and returns a +// success-path witness in the legacy stack order. The caller must set the +// proof-selected input's sequence to SuccessSequence before calling this +// method; the PSBT is never mutated here. +func (s *SwapKit) CreatePreimageWitness(ctx context.Context, + signer lndclient.SignerClient, htlcProof *proof.Proof, + sweepBtcPacket *psbt.Packet, keyLocator keychain.KeyLocator, + preimage lntypes.Preimage) (*SpendWitness, error) { + + if signer == nil { + return nil, fmt.Errorf("signer is required") + } + if preimage.Hash() != s.swapHash { + return nil, fmt.Errorf("preimage does not match swap hash") + } + + sweep, err := s.validateSweep(htlcProof, sweepBtcPacket) + if err != nil { + return nil, err + } + if err := validateSequence( + sweep, sweepBtcPacket, SuccessSequence, + ); err != nil { + return nil, err + } + + successScript, err := s.GetSuccessScript() + if err != nil { + return nil, err + } + + signDesc := &lndclient.SignDescriptor{ + KeyDesc: keychain.KeyDescriptor{KeyLocator: keyLocator}, + SignMethod: input.TaprootScriptSpendSignMethod, + WitnessScript: successScript, + Output: sweep.prevOutputs[sweep.assetInputIndex], + InputIndex: sweep.assetInputIndex, + } + sigs, err := signer.SignOutputRaw( + ctx, sweepBtcPacket.UnsignedTx, + []*lndclient.SignDescriptor{signDesc}, sweep.prevOutputs, + ) + if err != nil { + return nil, err + } + if len(sigs) != 1 || len(sigs[0]) == 0 { + return nil, fmt.Errorf("signer returned an invalid signature set") + } + if err := verifyTapscriptSignature( + sweepBtcPacket.UnsignedTx, sweep, successScript, + s.receiverPubKey, sigs[0], + ); err != nil { + return nil, err + } + + successControlBlock, err := s.GenSuccessBtcControlBlock( + sweep.assetRoot, + ) + if err != nil { + return nil, err + } + controlBlockBytes, err := successControlBlock.ToBytes() + if err != nil { + return nil, err + } + + return &SpendWitness{ + InputIndex: uint32(sweep.assetInputIndex), + Witness: wire.TxWitness{ + preimage[:], sigs[0], successScript, controlBlockBytes, + }, + }, nil +} + +// CreateTimeoutWitness signs the exact proof-bound asset input and returns a +// timeout-path witness in the legacy stack order. The caller must set the +// proof-selected input's sequence to CsvExpiry before calling this method; the +// PSBT is never mutated here. +func (s *SwapKit) CreateTimeoutWitness(ctx context.Context, + signer lndclient.SignerClient, htlcProof *proof.Proof, + sweepBtcPacket *psbt.Packet, keyLocator keychain.KeyLocator) ( + *SpendWitness, error) { + + if signer == nil { + return nil, fmt.Errorf("signer is required") + } + + sweep, err := s.validateSweep(htlcProof, sweepBtcPacket) + if err != nil { + return nil, err + } + if err := validateSequence( + sweep, sweepBtcPacket, s.csvExpiry, + ); err != nil { + return nil, err + } + + timeoutScript, err := s.GetTimeoutScript() + if err != nil { + return nil, err + } + + signDesc := &lndclient.SignDescriptor{ + KeyDesc: keychain.KeyDescriptor{KeyLocator: keyLocator}, + SignMethod: input.TaprootScriptSpendSignMethod, + WitnessScript: timeoutScript, + Output: sweep.prevOutputs[sweep.assetInputIndex], + InputIndex: sweep.assetInputIndex, + } + sigs, err := signer.SignOutputRaw( + ctx, sweepBtcPacket.UnsignedTx, + []*lndclient.SignDescriptor{signDesc}, sweep.prevOutputs, + ) + if err != nil { + return nil, err + } + if len(sigs) != 1 || len(sigs[0]) == 0 { + return nil, fmt.Errorf("signer returned an invalid signature set") + } + if err := verifyTapscriptSignature( + sweepBtcPacket.UnsignedTx, sweep, timeoutScript, + s.senderPubKey, sigs[0], + ); err != nil { + return nil, err + } + + timeoutControlBlock, err := s.GenTimeoutBtcControlBlock( + sweep.assetRoot, + ) + if err != nil { + return nil, err + } + controlBlockBytes, err := timeoutControlBlock.ToBytes() + if err != nil { + return nil, err + } + + return &SpendWitness{ + InputIndex: uint32(sweep.assetInputIndex), + Witness: wire.TxWitness{ + sigs[0], timeoutScript, controlBlockBytes, + }, + }, nil +} diff --git a/assets/htlc/swapkit_test.go b/assets/htlc/swapkit_test.go new file mode 100644 index 000000000..5e389e86d --- /dev/null +++ b/assets/htlc/swapkit_test.go @@ -0,0 +1,1226 @@ +package htlc + +import ( + "bytes" + "context" + "encoding/hex" + "fmt" + "testing" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil/psbt" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" + "github.com/lightninglabs/lndclient" + "github.com/lightninglabs/taproot-assets/address" + "github.com/lightninglabs/taproot-assets/asset" + "github.com/lightninglabs/taproot-assets/commitment" + "github.com/lightninglabs/taproot-assets/proof" + "github.com/lightninglabs/taproot-assets/tappsbt" + "github.com/lightninglabs/taproot-assets/tapscript" + "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/keychain" + "github.com/lightningnetwork/lnd/lntypes" + "github.com/stretchr/testify/require" +) + +const ( + legacySuccessScript = "20c6047f9441ed7d6d3045406e95c07cd85c778e" + + "4b8cef3ca7abac09b95c709ee5ad82012088a914e6babb9619d7a812" + + "72711fc546a16b211dd939578851b2" + legacyTimeoutScript = "2079be667ef9dcbbac55a06295ce870b07029bfcdb2d" + + "ce28d959f2815b16f81798ad029000b2" + legacyAggregateKey = "023b46d262d2f610e9038b44beabdfe97ab5a0feb" + + "89870acc2264edfb7f63ec2ec" + legacySibling = "01cbf40123d0ca1191c0dba575c7a92ea255f9e9fc81484e" + + "3929afeaa1a6f459d600114fbfd01b5de82dfa6f54f0f27af41d5a66" + + "ed39ac1a87d614fa12808f9adf" + legacyOpTrueKey = "037bbbb85ff774141ee36c2cc9f38b40be4a02c2a156c8a" + + "1def8781cf39177deca" + legacyOpTrueTweak = "a85b2107f791b26a84e7586c28cec7cb61202ed3d019" + + "44d832500f363782d675" + legacyOpTrueControl = "c17c79b9b26e463895eef5679d8558942c86c4ad2233" + + "adef01bc3e6d540b3653fe" + legacyOpTrueScriptKey = "027bbbb85ff774141ee36c2cc9f38b40be4a02c2a" + + "156c8a1def8781cf39177deca" + legacySuccessControl = "c13b46d262d2f610e9038b44beabdfe97ab5a0feb89" + + "870acc2264edfb7f63ec2eccbf40123d0ca1191c0dba575c7a92ea255" + + "f9e9fc81484e3929afeaa1a6f459d6a0a1a2a3a4a5a6a7a8a9aaab" + + "acadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + legacyTimeoutControl = "c13b46d262d2f610e9038b44beabdfe97ab5a0feb89" + + "870acc2264edfb7f63ec2ec00114fbfd01b5de82dfa6f54f0f27af41" + + "d5a66ed39ac1a87d614fa12808f9adfa0a1a2a3a4a5a6a7a8a9aaab" + + "acadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + legacyVPacket = "70736274ff010089020000000100000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000000002000000" + + "00000000002251207c79b9b26e463895eef5679d8558942c86c4ad2233" + + "adef01bc3e6d540b3653fee8030000000000002251207bbbb85ff77414" + + "1ee36c2cc9f38b40be4a02c2a156c8a1def8781cf39177deca00000000" + + "0170010101710574617072740172010100017065000000000000000000" + + "0000000000000000000000000000000000000000000000000000000001" + + "02030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e" + + "1f00000000000000000000000000000000000000000000000000000000" + + "0000000000017108000000000000000001720001730800000000000000" + + "0001750001780000017001010171010101720800000000000000000179" + + "0101017c080000000000000000017d0800000000000000000001700100" + + "017101010172080000000000000001017321023b46d262d2f610e9038b" + + "44beabdfe97ab5a0feb89870acc2264edfb7f63ec2ec01784101cbf401" + + "23d0ca1191c0dba575c7a92ea255f9e9fc81484e3929afeaa1a6f459d6" + + "00114fbfd01b5de82dfa6f54f0f27af41d5a66ed39ac1a87d614fa1280" + + "8f9adf01790101017c080000000000000000017d080000000000000000" + + "00" + legacyAnchorPkScript = "512021b15bddf2d991b8791ec7c2105fa69be61008d78" + + "b67d261451290d7a44dce5f" +) + +// scalarKey derives a deterministic test key from a one-byte scalar. +func scalarKey(t *testing.T, scalar byte) (*btcec.PrivateKey, + *btcec.PublicKey) { + + t.Helper() + + keyBytes := make([]byte, 32) + keyBytes[31] = scalar + privateKey, publicKey := btcec.PrivKeyFromBytes(keyBytes) + + return privateKey, publicKey +} + +// vectorParams returns the immutable inputs used by the legacy contract +// vectors. +func vectorParams(t *testing.T) Params { + t.Helper() + + _, sender := scalarKey(t, 1) + _, receiver := scalarKey(t, 2) + var assetID asset.ID + var swapHash lntypes.Hash + for idx := range assetID { + assetID[idx] = byte(idx) + swapHash[idx] = byte(idx) + } + + return Params{ + SenderPubKey: sender, + ReceiverPubKey: receiver, + AssetID: assetID, + Amount: 1000, + SwapHash: swapHash, + CsvExpiry: 144, + AddressParams: cloneAddressParams(address.RegressionNetTap), + } +} + +// newVectorKit creates a swap kit from the legacy contract vector inputs. +func newVectorKit(t *testing.T, policy Policy) *SwapKit { + t.Helper() + + kit, err := NewSwapKit(policy, vectorParams(t)) + require.NoError(t, err) + + return kit +} + +// TestLegacyDepositVectors freezes the scripts and aggregate key used by the +// existing valid server deposit HTLC contract. +func TestLegacyDepositVectors(t *testing.T) { + legacyKit := newVectorKit(t, LegacyDepositV0) + + successScript, err := legacyKit.GetSuccessScript() + require.NoError(t, err) + require.Equal(t, legacySuccessScript, + hex.EncodeToString(successScript)) + + timeoutScript, err := legacyKit.GetTimeoutScript() + require.NoError(t, err) + require.Equal(t, legacyTimeoutScript, + hex.EncodeToString(timeoutScript)) + + aggregateKey, err := legacyKit.GetAggregateKey() + require.NoError(t, err) + require.Equal(t, legacyAggregateKey, + hex.EncodeToString(aggregateKey.SerializeCompressed())) + + sibling, err := legacyKit.GetSiblingPreimage() + require.NoError(t, err) + siblingBytes, _, err := commitment.MaybeEncodeTapscriptPreimage( + &sibling, + ) + require.NoError(t, err) + require.Equal(t, legacySibling, hex.EncodeToString(siblingBytes)) + + opTrueKey, _, _, opTrueControl, err := CreateOpTrueLeaf() + require.NoError(t, err) + require.Equal(t, legacyOpTrueKey, hex.EncodeToString( + opTrueKey.PubKey.SerializeCompressed(), + )) + require.Equal(t, legacyOpTrueTweak, + hex.EncodeToString(opTrueKey.TweakedScriptKey.Tweak)) + opTrueControlBytes, err := opTrueControl.ToBytes() + require.NoError(t, err) + require.Equal(t, legacyOpTrueControl, + hex.EncodeToString(opTrueControlBytes)) + opTrueScriptKey, err := GetOpTrueScriptKey() + require.NoError(t, err) + require.Equal(t, legacyOpTrueScriptKey, + hex.EncodeToString(opTrueScriptKey)) + + assetRoot := make([]byte, 32) + for idx := range assetRoot { + assetRoot[idx] = byte(0xa0 + idx) + } + successControl, err := legacyKit.GenSuccessBtcControlBlock(assetRoot) + require.NoError(t, err) + successControlBytes, err := successControl.ToBytes() + require.NoError(t, err) + require.Equal(t, legacySuccessControl, + hex.EncodeToString(successControlBytes)) + timeoutControl, err := legacyKit.GenTimeoutBtcControlBlock(assetRoot) + require.NoError(t, err) + timeoutControlBytes, err := timeoutControl.ToBytes() + require.NoError(t, err) + require.Equal(t, legacyTimeoutControl, + hex.EncodeToString(timeoutControlBytes)) + anchorPkScript, err := legacyKit.GetPkScriptFromRoot(assetRoot) + require.NoError(t, err) + require.Equal(t, legacyAnchorPkScript, + hex.EncodeToString(anchorPkScript)) + + packet, err := legacyKit.CreateHtlcVpkt() + require.NoError(t, err) + var packetBytes bytes.Buffer + require.NoError(t, packet.Serialize(&packetBytes)) + require.Equal(t, legacyVPacket, + hex.EncodeToString(packetBytes.Bytes())) +} + +// TestTimeoutScriptNumberEncoding freezes BIP68 boundary encodings so a +// library update cannot silently change an already negotiated script. +func TestTimeoutScriptNumberEncoding(t *testing.T) { + _, sender := scalarKey(t, 1) + const prefix = "2079be667ef9dcbbac55a06295ce870b07029bfcdb2dce" + + "28d959f2815b16f81798ad" + tests := []struct { + expiry int64 + hex string + }{ + {expiry: 1, hex: prefix + "51b2"}, + {expiry: 16, hex: prefix + "60b2"}, + {expiry: 128, hex: prefix + "028000b2"}, + {expiry: 256, hex: prefix + "020001b2"}, + } + + for _, testCase := range tests { + script, err := GenTimeoutPathScript(sender, testCase.expiry) + require.NoError(t, err) + require.Equal(t, testCase.hex, hex.EncodeToString(script)) + } +} + +// TestNewSwapKitValidation verifies malformed contracts fail before any +// scripts or addresses can be derived. +func TestNewSwapKitValidation(t *testing.T) { + validParams := vectorParams(t) + _, err := NewSwapKit(PolicyUnknown, validParams) + require.Error(t, err) + _, err = NewSwapKit(Policy(255), validParams) + require.Error(t, err) + + tests := []struct { + name string + mutate func(*Params) + }{ + { + name: "missing sender", + mutate: func(params *Params) { + params.SenderPubKey = nil + }, + }, + { + name: "missing receiver", + mutate: func(params *Params) { + params.ReceiverPubKey = nil + }, + }, + { + name: "identical keys", + mutate: func(params *Params) { + params.ReceiverPubKey = params.SenderPubKey + }, + }, + { + name: "zero amount", + mutate: func(params *Params) { + params.Amount = 0 + }, + }, + { + name: "zero asset ID", + mutate: func(params *Params) { + params.AssetID = asset.ID{} + }, + }, + { + name: "zero swap hash", + mutate: func(params *Params) { + params.SwapHash = lntypes.Hash{} + }, + }, + { + name: "zero expiry", + mutate: func(params *Params) { + params.CsvExpiry = 0 + }, + }, + { + name: "expiry equals success sequence", + mutate: func(params *Params) { + params.CsvExpiry = SuccessSequence + }, + }, + { + name: "time based expiry", + mutate: func(params *Params) { + params.CsvExpiry = wire.SequenceLockTimeIsSeconds + }, + }, + { + name: "missing address params", + mutate: func(params *Params) { + params.AddressParams = nil + }, + }, + { + name: "incomplete address params", + mutate: func(params *Params) { + params.AddressParams = &address.ChainParams{} + }, + }, + { + name: "mismatched address params", + mutate: func(params *Params) { + mismatch := address.RegressionNetTap + mismatch.TapHRP = address.MainNetTap.TapHRP + params.AddressParams = &mismatch + }, + }, + { + name: "unsupported address params", + mutate: func(params *Params) { + unsupported := address.RegressionNetTap + unsupported.TapHRP = "tapunknown" + params.AddressParams = &unsupported + }, + }, + } + + for _, testCase := range tests { + t.Run(testCase.name, func(t *testing.T) { + params := validParams + if testCase.mutate != nil { + testCase.mutate(¶ms) + } + _, err := NewSwapKit(LegacyDepositV0, params) + require.Error(t, err) + }) + } + + _, err = GenSuccessPathScript(nil, lntypes.Hash{}) + require.Error(t, err) + _, err = GenTimeoutPathScript(nil, 1) + require.Error(t, err) + _, err = GenTimeoutPathScript(validParams.SenderPubKey, 0) + require.Error(t, err) +} + +// TestSupportedNetworks ensures shared testnet HRPs do not collapse signet or +// testnet4 into testnet3, and both native and lnd-compatible simnet coin types +// remain supported. +func TestSupportedNetworks(t *testing.T) { + rawSimNet := cloneAddressParams(address.SimNetTap) + rawSimNet.HDCoinType = rawSimNetHDCoinType + lndSimNet := cloneAddressParams( + address.ParamsForChain(address.SimNetTap.Name), + ) + + networks := []*address.ChainParams{ + &address.MainNetTap, + &address.TestNet3Tap, + &address.TestNet4Tap, + &address.RegressionNetTap, + &address.SigNetTap, + rawSimNet, + lndSimNet, + } + for _, network := range networks { + params := vectorParams(t) + params.AddressParams = network + kit, err := NewSwapKit(LegacyDepositV0, params) + require.NoError(t, err) + require.Equal(t, network.Net, kit.AddressParams().Net) + require.Equal(t, network.TapHRP, kit.AddressParams().TapHRP) + require.Equal(t, network.HDCoinType, + kit.AddressParams().HDCoinType) + } +} + +// TestSwapKitIsImmutable verifies constructor inputs and returned address +// parameters cannot alter a previously constructed contract. +func TestSwapKitIsImmutable(t *testing.T) { + params := vectorParams(t) + kit, err := NewSwapKit(LegacyDepositV0, params) + require.NoError(t, err) + + params.AssetID[0] = 99 + params.AddressParams.TapHRP = "mutated" + require.Zero(t, kit.AssetID()[0]) + require.Equal(t, address.RegressionNetTap.TapHRP, + kit.AddressParams().TapHRP) + + returnedParams := kit.AddressParams() + returnedParams.TapHRP = "also-mutated" + returnedParams.Params.Name = "mutated-chain" + require.Equal(t, address.RegressionNetTap.TapHRP, + kit.AddressParams().TapHRP) + require.Equal(t, address.RegressionNetTap.Params.Name, + kit.AddressParams().Params.Name) + + packet, err := kit.CreateHtlcVpkt() + require.NoError(t, err) + packet.ChainParams.TapHRP = "packet-mutated" + nextPacket, err := kit.CreateHtlcVpkt() + require.NoError(t, err) + require.Equal(t, address.RegressionNetTap.TapHRP, + nextPacket.ChainParams.TapHRP) +} + +// TestCreateHtlcVpkt freezes the output roles and flags that existing Taproot +// Assets deposit transfers depend upon. +func TestCreateHtlcVpkt(t *testing.T) { + kit := newVectorKit(t, LegacyDepositV0) + packet, err := kit.CreateHtlcVpkt() + require.NoError(t, err) + + require.Equal(t, tappsbt.V1, packet.Version) + require.Len(t, packet.Inputs, 1) + require.Equal(t, kit.AssetID(), packet.Inputs[0].PrevID.ID) + require.Len(t, packet.Outputs, 2) + + splitRoot := packet.Outputs[0] + require.Equal(t, asset.V1, splitRoot.AssetVersion) + require.Zero(t, splitRoot.Amount) + require.Equal(t, uint32(0), splitRoot.AnchorOutputIndex) + require.True(t, splitRoot.Interactive) + require.Equal(t, asset.NUMSScriptKey.PubKey.SerializeCompressed(), + splitRoot.ScriptKey.PubKey.SerializeCompressed()) + + htlcOutput := packet.Outputs[1] + require.Equal(t, asset.V1, htlcOutput.AssetVersion) + require.Equal(t, kit.Amount(), htlcOutput.Amount) + require.Equal(t, uint32(1), htlcOutput.AnchorOutputIndex) + require.True(t, htlcOutput.Interactive) + require.NotNil(t, htlcOutput.AnchorOutputInternalKey) + require.NotNil(t, htlcOutput.AnchorOutputTapscriptSibling) +} + +// TestAssetHtlcScriptEngine proves both paths execute and reject the wrong +// preimage, signer, and relative sequence. +func TestAssetHtlcScriptEngine(t *testing.T) { + senderPriv, senderPub := scalarKey(t, 1) + receiverPriv, receiverPub := scalarKey(t, 2) + var assetID asset.ID + var preimage lntypes.Preimage + for idx := range preimage { + assetID[idx] = byte(idx) + preimage[idx] = byte(31 - idx) + } + + kit, err := NewSwapKit(LegacyDepositV0, Params{ + SenderPubKey: senderPub, ReceiverPubKey: receiverPub, + AssetID: assetID, Amount: 1000, SwapHash: preimage.Hash(), + CsvExpiry: 144, AddressParams: &address.RegressionNetTap, + }) + require.NoError(t, err) + + tests := []struct { + name string + success bool + sequence uint32 + signingKey *btcec.PrivateKey + preimage lntypes.Preimage + valid bool + }{ + { + name: "success", success: true, + sequence: SuccessSequence, signingKey: receiverPriv, + preimage: preimage, valid: true, + }, + { + name: "wrong preimage", success: true, + sequence: SuccessSequence, signingKey: receiverPriv, + preimage: lntypes.Preimage{1}, + }, + { + name: "wrong success key", success: true, + sequence: SuccessSequence, signingKey: senderPriv, + preimage: preimage, + }, + { + name: "timeout", sequence: kit.CsvExpiry(), + signingKey: senderPriv, valid: true, + }, + { + name: "timeout one block early", + sequence: kit.CsvExpiry() - 1, signingKey: senderPriv, + }, + { + name: "wrong timeout key", sequence: kit.CsvExpiry(), + signingKey: receiverPriv, + }, + } + + for _, testCase := range tests { + t.Run(testCase.name, func(t *testing.T) { + assertScriptSpend(t, kit, testCase.success, + testCase.sequence, testCase.signingKey, + testCase.preimage, testCase.valid) + }) + } +} + +// assertScriptSpend executes one HTLC script path and checks its result. +func assertScriptSpend(t *testing.T, kit *SwapKit, success bool, + sequence uint32, signingKey *btcec.PrivateKey, + preimage lntypes.Preimage, valid bool) { + + t.Helper() + + assetRoot := bytes.Repeat([]byte{0x42}, 32) + var ( + controlBlock *txscript.ControlBlock + leaf txscript.TapLeaf + script []byte + err error + ) + if success { + controlBlock, err = kit.GenSuccessBtcControlBlock(assetRoot) + require.NoError(t, err) + leaf, err = kit.GetSuccessLeaf() + require.NoError(t, err) + script = leaf.Script + } else { + controlBlock, err = kit.GenTimeoutBtcControlBlock(assetRoot) + require.NoError(t, err) + leaf, err = kit.GetTimeoutLeaf() + require.NoError(t, err) + script = leaf.Script + } + + rootHash := controlBlock.RootHash(script) + internalKey, err := kit.GetAggregateKey() + require.NoError(t, err) + outputKey := txscript.ComputeTaprootOutputKey(internalKey, rootHash) + pkScript, err := txscript.PayToTaprootScript(outputKey) + require.NoError(t, err) + + const value = int64(50_000) + tx := wire.NewMsgTx(2) + tx.AddTxIn(&wire.TxIn{ + PreviousOutPoint: wire.OutPoint{ + Hash: chainhash.Hash{1}, Index: 2, + }, + Sequence: sequence, + }) + tx.AddTxOut(&wire.TxOut{Value: value - 1000, + PkScript: []byte{txscript.OP_TRUE}}) + prevOutFetcher := txscript.NewCannedPrevOutputFetcher(pkScript, value) + sigHashes := txscript.NewTxSigHashes(tx, prevOutFetcher) + signature, err := txscript.RawTxInTapscriptSignature( + tx, sigHashes, 0, value, pkScript, leaf, + txscript.SigHashDefault, signingKey, + ) + require.NoError(t, err) + controlBytes, err := controlBlock.ToBytes() + require.NoError(t, err) + + if success { + tx.TxIn[0].Witness = wire.TxWitness{ + preimage[:], signature, script, controlBytes, + } + } else { + tx.TxIn[0].Witness = wire.TxWitness{ + signature, script, controlBytes, + } + } + + engine, err := txscript.NewEngine( + pkScript, tx, 0, txscript.StandardVerifyFlags, nil, + sigHashes, value, prevOutFetcher, + ) + require.NoError(t, err) + if valid { + require.NoError(t, engine.Execute()) + } else { + require.Error(t, engine.Execute()) + } +} + +type localSigner struct { + lndclient.SignerClient + + privateKey *btcec.PrivateKey + expectedInput int + calls int +} + +func (s *localSigner) SignOutputRaw(_ context.Context, tx *wire.MsgTx, + descriptors []*lndclient.SignDescriptor, + prevOutputs []*wire.TxOut) ([][]byte, error) { + + s.calls++ + if len(descriptors) != 1 { + return nil, fmt.Errorf("expected one sign descriptor") + } + if len(prevOutputs) != len(tx.TxIn) { + return nil, fmt.Errorf("expected all previous outputs") + } + + descriptor := descriptors[0] + if descriptor.InputIndex != s.expectedInput { + return nil, fmt.Errorf("unexpected input index: %d", + descriptor.InputIndex) + } + if descriptor.SignMethod != input.TaprootScriptSpendSignMethod { + return nil, fmt.Errorf("unexpected signing method") + } + + prevOutFetcher := txscript.NewMultiPrevOutFetcher(nil) + for idx, txIn := range tx.TxIn { + prevOutFetcher.AddPrevOut( + txIn.PreviousOutPoint, prevOutputs[idx], + ) + } + sigHashes := txscript.NewTxSigHashes(tx, prevOutFetcher) + tapLeaf := txscript.NewBaseTapLeaf(descriptor.WitnessScript) + signature, err := txscript.RawTxInTapscriptSignature( + tx, sigHashes, descriptor.InputIndex, + descriptor.Output.Value, descriptor.Output.PkScript, tapLeaf, + txscript.SigHashDefault, s.privateKey, + ) + if err != nil { + return nil, err + } + + return [][]byte{signature}, nil +} + +type witnessFixture struct { + kit *SwapKit + proof *proof.Proof + packet *psbt.Packet + prevOutputs []*wire.TxOut + senderKey *btcec.PrivateKey + receiverKey *btcec.PrivateKey + preimage lntypes.Preimage + assetInIndex int +} + +// newWitnessFixture creates a proof-bound HTLC and sweep packet using the +// default asset and proof versions. +func newWitnessFixture(t *testing.T, sequence uint32) *witnessFixture { + return newWitnessFixtureWithVersions( + t, sequence, asset.V1, commitment.TapCommitmentV2, + ) +} + +// newWitnessFixtureWithVersions creates a proof-bound HTLC and sweep packet +// using explicit asset and proof versions. +func newWitnessFixtureWithVersions(t *testing.T, sequence uint32, + assetVersion asset.Version, + commitmentVersion commitment.TapCommitmentVersion) *witnessFixture { + + t.Helper() + + senderKey, senderPubKey := scalarKey(t, 1) + receiverKey, receiverPubKey := scalarKey(t, 2) + var preimage lntypes.Preimage + for idx := range preimage { + preimage[idx] = byte(31 - idx) + } + + genesis := asset.Genesis{ + FirstPrevOut: wire.OutPoint{ + Hash: chainhash.Hash{0x31}, + Index: 3, + }, + Tag: "asset htlc witness test", + OutputIndex: 0, + Type: asset.Normal, + } + opTrueScriptKey, _, _, _, err := CreateOpTrueLeaf() + require.NoError(t, err) + opTrueScriptKey = asset.NewScriptKey(opTrueScriptKey.PubKey) + htlcAsset, err := asset.New( + genesis, 1000, 0, 0, opTrueScriptKey, nil, + asset.WithAssetVersion(assetVersion), + ) + require.NoError(t, err) + + kit, err := NewSwapKit(LegacyDepositV0, Params{ + SenderPubKey: senderPubKey, + ReceiverPubKey: receiverPubKey, + AssetID: genesis.ID(), + Amount: htlcAsset.Amount, + SwapHash: preimage.Hash(), + CsvExpiry: 144, + AddressParams: &address.RegressionNetTap, + }) + require.NoError(t, err) + + tapCommitment, err := commitment.FromAssets( + &commitmentVersion, htlcAsset, + ) + require.NoError(t, err) + _, commitmentProof, err := tapCommitment.Proof( + htlcAsset.TapCommitmentKey(), + htlcAsset.AssetCommitmentKey(), + ) + require.NoError(t, err) + sibling, err := kit.GetSiblingPreimage() + require.NoError(t, err) + siblingHash, err := sibling.TapHash() + require.NoError(t, err) + internalKey, err := kit.GetAggregateKey() + require.NoError(t, err) + anchorPkScript, err := tapscript.PayToAddrScript( + *internalKey, siblingHash, *tapCommitment, + ) + require.NoError(t, err) + + const anchorValue = int64(50_000) + anchorTx := wire.NewMsgTx(2) + anchorTx.AddTxIn(&wire.TxIn{ + PreviousOutPoint: genesis.FirstPrevOut, + }) + anchorTx.AddTxOut(&wire.TxOut{ + Value: 1000, + PkScript: []byte{txscript.OP_TRUE}, + }) + anchorTx.AddTxOut(&wire.TxOut{ + Value: anchorValue, + PkScript: anchorPkScript, + }) + + assetProof := &proof.Proof{ + AnchorTx: *anchorTx, + Asset: *htlcAsset, + InclusionProof: proof.TaprootProof{ + OutputIndex: 1, + InternalKey: internalKey, + CommitmentProof: &proof.CommitmentProof{ + Proof: *commitmentProof, + TapSiblingPreimage: &sibling, + }, + }, + } + _, err = assetProof.VerifyProofs() + require.NoError(t, err) + + feeOutPoint := wire.OutPoint{ + Hash: chainhash.Hash{0x42}, + Index: 5, + } + assetInIndex := 1 + sweepTx := wire.NewMsgTx(2) + sweepTx.AddTxIn(&wire.TxIn{ + PreviousOutPoint: feeOutPoint, + Sequence: wire.MaxTxInSequenceNum, + }) + sweepTx.AddTxIn(&wire.TxIn{ + PreviousOutPoint: assetProof.OutPoint(), + Sequence: sequence, + }) + sweepTx.AddTxOut(&wire.TxOut{ + Value: anchorValue - 2000, + PkScript: []byte{txscript.OP_TRUE}, + }) + sweepPacket, err := psbt.NewFromUnsignedTx(sweepTx) + require.NoError(t, err) + prevOutputs := []*wire.TxOut{ + { + Value: 3000, + PkScript: []byte{txscript.OP_TRUE}, + }, + { + Value: anchorValue, + PkScript: append([]byte(nil), anchorPkScript...), + }, + } + for idx := range prevOutputs { + sweepPacket.Inputs[idx].WitnessUtxo = prevOutputs[idx] + } + + return &witnessFixture{ + kit: kit, proof: assetProof, packet: sweepPacket, + prevOutputs: prevOutputs, senderKey: senderKey, + receiverKey: receiverKey, preimage: preimage, + assetInIndex: assetInIndex, + } +} + +// TestGetPkScriptFromProof verifies that anchor reconstruction follows the +// commitment version proven on chain. The asset version alone cannot +// distinguish a legacy commitment from a version-two commitment. +func TestGetPkScriptFromProof(t *testing.T) { + tests := []struct { + name string + assetVersion asset.Version + commitmentVersion commitment.TapCommitmentVersion + }{ + { + name: "legacy v0", + assetVersion: asset.V0, + commitmentVersion: commitment.TapCommitmentV0, + }, + { + name: "legacy v1", + assetVersion: asset.V1, + commitmentVersion: commitment.TapCommitmentV1, + }, + { + name: "version two", + assetVersion: asset.V1, + commitmentVersion: commitment.TapCommitmentV2, + }, + } + + for _, testCase := range tests { + t.Run(testCase.name, func(t *testing.T) { + fixture := newWitnessFixtureWithVersions( + t, SuccessSequence, testCase.assetVersion, + testCase.commitmentVersion, + ) + pkScript, err := fixture.kit.GetPkScriptFromProof( + fixture.proof, + ) + require.NoError(t, err) + require.Equal( + t, fixture.prevOutputs[fixture.assetInIndex].PkScript, + pkScript, + ) + }) + } +} + +// executeWitness runs the virtual asset VM and Bitcoin script engine against a +// generated witness. +func (f *witnessFixture) executeWitness(t *testing.T, + witness *SpendWitness) { + + t.Helper() + + require.Equal(t, uint32(f.assetInIndex), witness.InputIndex) + tx := f.packet.UnsignedTx + tx.TxIn[witness.InputIndex].Witness = witness.Witness + + prevOutFetcher := txscript.NewMultiPrevOutFetcher(nil) + for idx, txIn := range tx.TxIn { + prevOutFetcher.AddPrevOut( + txIn.PreviousOutPoint, f.prevOutputs[idx], + ) + } + sigHashes := txscript.NewTxSigHashes(tx, prevOutFetcher) + prevOutput := f.prevOutputs[witness.InputIndex] + engine, err := txscript.NewEngine( + prevOutput.PkScript, tx, int(witness.InputIndex), + txscript.StandardVerifyFlags, nil, sigHashes, + prevOutput.Value, prevOutFetcher, + ) + require.NoError(t, err) + require.NoError(t, engine.Execute()) +} + +// TestCreateProofBoundWitnesses proves both witness builders sign the input +// selected by the asset proof even when an unrelated input precedes it. +func TestCreateProofBoundWitnesses(t *testing.T) { + t.Run("success", func(t *testing.T) { + fixture := newWitnessFixture(t, SuccessSequence) + inputIndex, err := fixture.kit.AssetInputIndex( + fixture.proof, fixture.packet, + ) + require.NoError(t, err) + require.Equal(t, uint32(fixture.assetInIndex), inputIndex) + + signer := &localSigner{ + privateKey: fixture.receiverKey, + expectedInput: fixture.assetInIndex, + } + witness, err := fixture.kit.CreatePreimageWitness( + t.Context(), signer, fixture.proof, fixture.packet, + keychain.KeyLocator{}, fixture.preimage, + ) + require.NoError(t, err) + require.Equal(t, 1, signer.calls) + require.Len(t, witness.Witness, 4) + fixture.executeWitness(t, witness) + }) + + t.Run("timeout", func(t *testing.T) { + fixture := newWitnessFixture(t, 144) + signer := &localSigner{ + privateKey: fixture.senderKey, + expectedInput: fixture.assetInIndex, + } + witness, err := fixture.kit.CreateTimeoutWitness( + t.Context(), signer, fixture.proof, fixture.packet, + keychain.KeyLocator{}, + ) + require.NoError(t, err) + require.Equal(t, 1, signer.calls) + require.Len(t, witness.Witness, 3) + fixture.executeWitness(t, witness) + }) +} + +// TestProofBoundWitnessValidation freezes the checks that keep proof, PSBT, +// contract, and signing key bound to the same funded asset output. +func TestProofBoundWitnessValidation(t *testing.T) { + tests := []struct { + name string + mutate func(*witnessFixture) + sign func(*testing.T, *witnessFixture, *localSigner) error + }{ + { + name: "wrong success sequence", + mutate: func(fixture *witnessFixture) { + fixture.packet.UnsignedTx.TxIn[1].Sequence = 2 + }, + }, + { + name: "wrong preimage", + sign: func(t *testing.T, fixture *witnessFixture, + signer *localSigner) error { + + _, err := fixture.kit.CreatePreimageWitness( + t.Context(), signer, fixture.proof, + fixture.packet, keychain.KeyLocator{}, + lntypes.Preimage{1}, + ) + return err + }, + }, + { + name: "wrong timeout sequence", + mutate: func(fixture *witnessFixture) { + fixture.packet.UnsignedTx.TxIn[1].Sequence = 143 + }, + sign: func(t *testing.T, fixture *witnessFixture, + signer *localSigner) error { + + _, err := fixture.kit.CreateTimeoutWitness( + t.Context(), signer, fixture.proof, + fixture.packet, keychain.KeyLocator{}, + ) + return err + }, + }, + { + name: "wrong success signing key", + mutate: func(fixture *witnessFixture) { + fixture.receiverKey = fixture.senderKey + }, + }, + { + name: "wrong timeout signing key", + sign: func(t *testing.T, fixture *witnessFixture, + signer *localSigner) error { + + fixture.packet.UnsignedTx.TxIn[1].Sequence = + fixture.kit.CsvExpiry() + _, err := fixture.kit.CreateTimeoutWitness( + t.Context(), signer, fixture.proof, + fixture.packet, keychain.KeyLocator{}, + ) + return err + }, + }, + { + name: "witness value mismatch", + mutate: func(fixture *witnessFixture) { + fixture.packet.Inputs[1].WitnessUtxo.Value++ + }, + }, + { + name: "witness script mismatch", + mutate: func(fixture *witnessFixture) { + fixture.packet.Inputs[1].WitnessUtxo.PkScript = + []byte{txscript.OP_TRUE} + }, + }, + { + name: "missing proof input", + mutate: func(fixture *witnessFixture) { + fixture.packet.UnsignedTx.TxIn = + fixture.packet.UnsignedTx.TxIn[:1] + fixture.packet.Inputs = fixture.packet.Inputs[:1] + }, + }, + { + name: "duplicate proof input", + mutate: func(fixture *witnessFixture) { + assetInput := *fixture.packet.UnsignedTx.TxIn[1] + fixture.packet.UnsignedTx.TxIn = append( + fixture.packet.UnsignedTx.TxIn, &assetInput, + ) + fixture.packet.Inputs = append( + fixture.packet.Inputs, + psbt.PInput{WitnessUtxo: fixture.prevOutputs[1]}, + ) + }, + }, + { + name: "missing fee input metadata", + mutate: func(fixture *witnessFixture) { + fixture.packet.Inputs[0].WitnessUtxo = nil + }, + }, + { + name: "version one sweep", + mutate: func(fixture *witnessFixture) { + fixture.packet.UnsignedTx.Version = 1 + }, + }, + { + name: "asset version", + mutate: func(fixture *witnessFixture) { + fixture.proof.Asset.Version = asset.V0 + }, + }, + { + name: "asset script key", + mutate: func(fixture *witnessFixture) { + _, publicKey := scalarKey(t, 3) + fixture.proof.Asset.ScriptKey = + asset.NewScriptKey(publicKey) + }, + }, + { + name: "asset script version", + mutate: func(fixture *witnessFixture) { + fixture.proof.Asset.ScriptVersion++ + }, + }, + { + name: "asset lock time", + mutate: func(fixture *witnessFixture) { + fixture.proof.Asset.LockTime = 1 + }, + }, + { + name: "asset relative lock time", + mutate: func(fixture *witnessFixture) { + fixture.proof.Asset.RelativeLockTime = 1 + }, + }, + } + + for _, testCase := range tests { + t.Run(testCase.name, func(t *testing.T) { + fixture := newWitnessFixture(t, SuccessSequence) + if testCase.mutate != nil { + testCase.mutate(fixture) + } + signer := &localSigner{ + privateKey: fixture.receiverKey, + expectedInput: fixture.assetInIndex, + } + if testCase.sign != nil { + require.Error(t, testCase.sign(t, fixture, signer)) + return + } + + _, err := fixture.kit.CreatePreimageWitness( + t.Context(), signer, fixture.proof, + fixture.packet, keychain.KeyLocator{}, + fixture.preimage, + ) + require.Error(t, err) + }) + } +} + +// TestValidateAssetPolicy isolates the asset-layer checks from proof +// verification so weakening one boundary cannot be masked by the other. +func TestValidateAssetPolicy(t *testing.T) { + fixture := newWitnessFixture(t, SuccessSequence) + require.NoError(t, fixture.kit.validateAsset(&fixture.proof.Asset)) + + tests := []struct { + name string + mutate func(*asset.Asset) + }{ + { + name: "asset ID", + mutate: func(candidate *asset.Asset) { + candidate.Genesis.Tag = "different asset" + }, + }, + { + name: "amount", + mutate: func(candidate *asset.Asset) { + candidate.Amount++ + }, + }, + { + name: "asset version", + mutate: func(candidate *asset.Asset) { + candidate.Version = asset.Version(255) + }, + }, + { + name: "script version", + mutate: func(candidate *asset.Asset) { + candidate.ScriptVersion++ + }, + }, + { + name: "script key", + mutate: func(candidate *asset.Asset) { + _, publicKey := scalarKey(t, 3) + candidate.ScriptKey = asset.NewScriptKey(publicKey) + }, + }, + { + name: "absolute locktime", + mutate: func(candidate *asset.Asset) { + candidate.LockTime = 1 + }, + }, + { + name: "relative locktime", + mutate: func(candidate *asset.Asset) { + candidate.RelativeLockTime = 1 + }, + }, + } + + for _, testCase := range tests { + t.Run(testCase.name, func(t *testing.T) { + candidate := fixture.proof.Asset.CopySpendTemplate() + testCase.mutate(candidate) + require.Error(t, fixture.kit.validateAsset(candidate)) + }) + } + + legacyV0Asset := fixture.proof.Asset.CopySpendTemplate() + legacyV0Asset.Version = asset.V0 + require.NoError(t, fixture.kit.validateAsset(legacyV0Asset)) +} + +// TestControlBlockRootLength rejects roots that cannot represent a Taproot +// branch hash. +func TestControlBlockRootLength(t *testing.T) { + kit := newVectorKit(t, LegacyDepositV0) + _, err := kit.GenSuccessBtcControlBlock(make([]byte, 31)) + require.Error(t, err) + _, err = kit.GenTimeoutBtcControlBlock(make([]byte, 33)) + require.Error(t, err) +} + +// TestFindUniqueInput proves sweep input selection is based on the exact +// proof outpoint rather than a positional convention. +func TestFindUniqueInput(t *testing.T) { + target := wire.OutPoint{Hash: chainhash.Hash{9}, Index: 7} + other := wire.OutPoint{Hash: chainhash.Hash{8}, Index: 3} + + tests := []struct { + name string + inputs []*wire.TxIn + expected int + expectErr bool + }{ + { + name: "first", + inputs: []*wire.TxIn{ + {PreviousOutPoint: target}, + {PreviousOutPoint: other}, + }, + expected: 0, + }, + { + name: "middle of three", + inputs: []*wire.TxIn{ + {PreviousOutPoint: other}, + {PreviousOutPoint: target}, + { + PreviousOutPoint: wire.OutPoint{ + Hash: chainhash.Hash{7}, + }, + }, + }, + expected: 1, + }, + { + name: "missing", + inputs: []*wire.TxIn{ + {PreviousOutPoint: other}, + }, + expectErr: true, + }, + { + name: "duplicate", + inputs: []*wire.TxIn{ + {PreviousOutPoint: target}, + {PreviousOutPoint: target}, + }, + expectErr: true, + }, + { + name: "nil input", + inputs: []*wire.TxIn{ + {PreviousOutPoint: target}, nil, + }, + expectErr: true, + }, + } + + for _, testCase := range tests { + t.Run(testCase.name, func(t *testing.T) { + tx := wire.NewMsgTx(2) + tx.TxIn = testCase.inputs + index, err := findUniqueInput(tx, target) + if testCase.expectErr { + require.Error(t, err) + return + } + + require.NoError(t, err) + require.Equal(t, testCase.expected, index) + }) + } +} + +// TestSiblingPreimageRoundTrip ensures the branch preimage retains its +// Taproot hash when encoded for an address RPC. +func TestSiblingPreimageRoundTrip(t *testing.T) { + kit := newVectorKit(t, LegacyDepositV0) + sibling, err := kit.GetSiblingPreimage() + require.NoError(t, err) + encoded, _, err := commitment.MaybeEncodeTapscriptPreimage(&sibling) + require.NoError(t, err) + require.NotEmpty(t, encoded) + + timeoutLeaf, err := kit.GetTimeOutLeaf() + require.NoError(t, err) + successLeaf, err := kit.GetSuccessLeaf() + require.NoError(t, err) + expectedPreimage := commitment.NewPreimageFromBranch( + txscript.NewTapBranch(timeoutLeaf, successLeaf), + ) + decoded, err := expectedPreimage.TapHash() + require.NoError(t, err) + actualHash, err := sibling.TapHash() + require.NoError(t, err) + require.Equal(t, decoded, actualHash) +} diff --git a/go.mod b/go.mod index 322497f84..b497edbc8 100644 --- a/go.mod +++ b/go.mod @@ -44,6 +44,8 @@ require ( modernc.org/sqlite v1.34.5 ) +require github.com/lightninglabs/lightning-node-connect/hashmailrpc v1.0.4-0.20250610182311-2f1d46ef18b7 // indirect + require ( dario.cat/mergo v1.0.1 // indirect github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect diff --git a/go.sum b/go.sum index bd17f2c30..c7c2f6e28 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,7 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT 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.44.3/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= @@ -13,30 +14,594 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV 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/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.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +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.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U= +cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= +cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= +cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= +cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= +cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= +cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= +cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= +cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= +cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= +cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= +cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= +cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= +cloud.google.com/go/accesscontextmanager v1.6.0/go.mod h1:8XCvZWfYw3K/ji0iVnp+6pu7huxoQTLmxAbVjbloTtM= +cloud.google.com/go/accesscontextmanager v1.7.0/go.mod h1:CEGLewx8dwa33aDAZQujl7Dx+uYhS0eay198wB/VumQ= +cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= +cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= +cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg= +cloud.google.com/go/aiplatform v1.35.0/go.mod h1:7MFT/vCaOyZT/4IIFfxH4ErVg/4ku6lKv3w0+tFTgXQ= +cloud.google.com/go/aiplatform v1.36.1/go.mod h1:WTm12vJRPARNvJ+v6P52RDHCNe4AhvjcIZ/9/RRHy/k= +cloud.google.com/go/aiplatform v1.37.0/go.mod h1:IU2Cv29Lv9oCn/9LkFiiuKfwrRTq+QQMbW+hPCxJGZw= +cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= +cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= +cloud.google.com/go/analytics v0.17.0/go.mod h1:WXFa3WSym4IZ+JiKmavYdJwGG/CvpqiqczmL59bTD9M= +cloud.google.com/go/analytics v0.18.0/go.mod h1:ZkeHGQlcIPkw0R/GW+boWHhCOR43xz9RN/jn7WcqfIE= +cloud.google.com/go/analytics v0.19.0/go.mod h1:k8liqf5/HCnOUkbawNtrWWc+UAzyDlW89doe8TtoDsE= +cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= +cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc= +cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8= +cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc= +cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04= +cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8= +cloud.google.com/go/apigeeregistry v0.4.0/go.mod h1:EUG4PGcsZvxOXAdyEghIdXwAEi/4MEaoqLMLDMIwKXY= +cloud.google.com/go/apigeeregistry v0.5.0/go.mod h1:YR5+s0BVNZfVOUkMa5pAR2xGd0A473vA5M7j247o1wM= +cloud.google.com/go/apigeeregistry v0.6.0/go.mod h1:BFNzW7yQVLZ3yj0TKcwzb8n25CFBri51GVGOEUcgQsc= +cloud.google.com/go/apikeys v0.4.0/go.mod h1:XATS/yqZbaBK0HOssf+ALHp8jAlNHUgyfprvNcBIszU= +cloud.google.com/go/apikeys v0.5.0/go.mod h1:5aQfwY4D+ewMMWScd3hm2en3hCj+BROlyrt3ytS7KLI= +cloud.google.com/go/apikeys v0.6.0/go.mod h1:kbpXu5upyiAlGkKrJgQl8A0rKNNJ7dQ377pdroRSSi8= +cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno= +cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak= +cloud.google.com/go/appengine v1.6.0/go.mod h1:hg6i0J/BD2cKmDJbaFSYHFyZkgBEfQrDg/X0V5fJn84= +cloud.google.com/go/appengine v1.7.0/go.mod h1:eZqpbHFCqRGa2aCdope7eC0SWLV1j0neb/QnMJVWx6A= +cloud.google.com/go/appengine v1.7.1/go.mod h1:IHLToyb/3fKutRysUlFO0BPt5j7RiQ45nrzEJmKTo6E= +cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= +cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= +cloud.google.com/go/area120 v0.7.0/go.mod h1:a3+8EUD1SX5RUcCs3MY5YasiO1z6yLiNLRiFrykbynY= +cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k= +cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= +cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= +cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0= +cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc= +cloud.google.com/go/artifactregistry v1.11.1/go.mod h1:lLYghw+Itq9SONbCa1YWBoWs1nOucMH0pwXN1rOBZFI= +cloud.google.com/go/artifactregistry v1.11.2/go.mod h1:nLZns771ZGAwVLzTX/7Al6R9ehma4WUEhZGWV6CeQNQ= +cloud.google.com/go/artifactregistry v1.12.0/go.mod h1:o6P3MIvtzTOnmvGagO9v/rOjjA0HmhJ+/6KAXrmYDCI= +cloud.google.com/go/artifactregistry v1.13.0/go.mod h1:uy/LNfoOIivepGhooAUpL1i30Hgee3Cu0l4VTWHUC08= +cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= +cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= +cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= +cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ= +cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY= +cloud.google.com/go/asset v1.11.1/go.mod h1:fSwLhbRvC9p9CXQHJ3BgFeQNM4c9x10lqlrdEUYXlJo= +cloud.google.com/go/asset v1.12.0/go.mod h1:h9/sFOa4eDIyKmH6QMpm4eUK3pDojWnUhTgJlk762Hg= +cloud.google.com/go/asset v1.13.0/go.mod h1:WQAMyYek/b7NBpYq/K4KJWcRqzoalEsxz/t/dTk4THw= +cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= +cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= +cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= +cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo= +cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= +cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= +cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= +cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= +cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= +cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM= +cloud.google.com/go/automl v1.12.0/go.mod h1:tWDcHDp86aMIuHmyvjuKeeHEGq76lD7ZqfGLN6B0NuU= +cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc= +cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI= +cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss= +cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE= +cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE= +cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oevL159g= +cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4= +cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8= +cloud.google.com/go/beyondcorp v0.4.0/go.mod h1:3ApA0mbhHx6YImmuubf5pyW8srKnCEPON32/5hj+RmM= +cloud.google.com/go/beyondcorp v0.5.0/go.mod h1:uFqj9X+dSfrheVp7ssLTaRHd2EHqSL4QZmH4e8WXGGU= 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/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= +cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw= +cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc= +cloud.google.com/go/bigquery v1.47.0/go.mod h1:sA9XOgy0A8vQK9+MWhEQTY6Tix87M/ZurWFIxmF9I/E= +cloud.google.com/go/bigquery v1.48.0/go.mod h1:QAwSz+ipNgfL5jxiaK7weyOhzdoAy1zFm0Nf1fysJac= +cloud.google.com/go/bigquery v1.49.0/go.mod h1:Sv8hMmTFFYBlt/ftw2uN6dFdQPzBlREY9yBh7Oy7/4Q= +cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU= +cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= +cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= +cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= +cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y= +cloud.google.com/go/billing v1.12.0/go.mod h1:yKrZio/eu+okO/2McZEbch17O5CB5NpZhhXG6Z766ss= +cloud.google.com/go/billing v1.13.0/go.mod h1:7kB2W9Xf98hP9Sr12KfECgfGclsH3CQR0R08tnRlRbc= +cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= +cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= +cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0= +cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk= +cloud.google.com/go/binaryauthorization v1.5.0/go.mod h1:OSe4OU1nN/VswXKRBmciKpo9LulY41gch5c68htf3/Q= +cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg= +cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590= +cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5vQ/fE1sh8o+Mdd6KPgY8= +cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk= +cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk= +cloud.google.com/go/channel v1.11.0/go.mod h1:IdtI0uWGqhEeatSB62VOoJ8FSUhJ9/+iGkJVqp74CGE= +cloud.google.com/go/channel v1.12.0/go.mod h1:VkxCGKASi4Cq7TbXxlaBezonAYpp1GCnKMY6tnMQnLU= +cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U= +cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA= +cloud.google.com/go/cloudbuild v1.6.0/go.mod h1:UIbc/w9QCbH12xX+ezUsgblrWv+Cv4Tw83GiSMHOn9M= +cloud.google.com/go/cloudbuild v1.7.0/go.mod h1:zb5tWh2XI6lR9zQmsm1VRA+7OCuve5d8S+zJUul8KTg= +cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb4wQGAbIgL1s= +cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM= +cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk= +cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA= +cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= +cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= +cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4= +cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI= +cloud.google.com/go/cloudtasks v1.9.0/go.mod h1:w+EyLsVkLWHcOaqNEyvcKAsWp9p29dL6uL9Nst1cI7Y= +cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs= +cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= +cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= +cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= +cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= +cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= +cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= +cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= +cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= +cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= +cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= +cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= +cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= +cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= +cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= +cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= +cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= +cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= +cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= +cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo= +cloud.google.com/go/container v1.13.1/go.mod h1:6wgbMPeQRw9rSnKBCAJXnds3Pzj03C4JHamr8asWKy4= +cloud.google.com/go/container v1.14.0/go.mod h1:3AoJMPhHfLDxLvrlVWaK57IXzaPnLaZq63WX59aQBfM= +cloud.google.com/go/container v1.15.0/go.mod h1:ft+9S0WGjAyjDggg5S06DXj+fHJICWg8L7isCQe9pQA= +cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= +cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= +cloud.google.com/go/containeranalysis v0.7.0/go.mod h1:9aUL+/vZ55P2CXfuZjS4UjQ9AgXoSw8Ts6lemfmxBxI= +cloud.google.com/go/containeranalysis v0.9.0/go.mod h1:orbOANbwk5Ejoom+s+DUCTTJ7IBdBQJDcSylAx/on9s= +cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= +cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= +cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= +cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H0/tc8f8ZbZIE= +cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM= +cloud.google.com/go/datacatalog v1.8.1/go.mod h1:RJ58z4rMp3gvETA465Vg+ag8BGgBdnRPEMMSTr5Uv+M= +cloud.google.com/go/datacatalog v1.12.0/go.mod h1:CWae8rFkfp6LzLumKOnmVh4+Zle4A3NXLzVJ1d1mRm0= +cloud.google.com/go/datacatalog v1.13.0/go.mod h1:E4Rj9a5ZtAxcQJlEBTLgMTphfP11/lNaAshpoBgemX8= +cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= +cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= +cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE= +cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= +cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= +cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0= +cloud.google.com/go/dataform v0.6.0/go.mod h1:QPflImQy33e29VuapFdf19oPbE4aYTJxr31OAPV+ulA= +cloud.google.com/go/dataform v0.7.0/go.mod h1:7NulqnVozfHvWUBpMDfKMUESr+85aJsC/2O0o3jWPDE= +cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38= +cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w= +cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8= +cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= +cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= +cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxByuW2E+FU+wXcM= +cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA= +cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A= +cloud.google.com/go/dataplex v1.5.2/go.mod h1:cVMgQHsmfRoI5KFYq4JtIBEUbYwc3c7tXmIDhRmNNVQ= +cloud.google.com/go/dataplex v1.6.0/go.mod h1:bMsomC/aEJOSpHXdFKFGQ1b0TDPIeL28nJObeO1ppRs= +cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s= +cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI= +cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= +cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= +cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= +cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZWwP12Qq3c= 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/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM= +cloud.google.com/go/datastore v1.11.0/go.mod h1:TvGxBIHCS50u8jzG+AW/ppf87v1of8nwzFNgEZU1D3c= +cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= +cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= +cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= +cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4= +cloud.google.com/go/datastream v1.6.0/go.mod h1:6LQSuswqLa7S4rPAOZFVjHIG3wJIjZcZrw8JDEDJuIs= +cloud.google.com/go/datastream v1.7.0/go.mod h1:uxVRMm2elUSPuh65IbZpzJNMbuzkcvu5CjMqVIUHrww= +cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c= +cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s= +cloud.google.com/go/deploy v1.6.0/go.mod h1:f9PTHehG/DjCom3QH0cntOVRm93uGBDt2vKzAPwpXQI= +cloud.google.com/go/deploy v1.8.0/go.mod h1:z3myEJnA/2wnB4sgjqdMfgxCA0EqC3RBTNcVPs93mtQ= +cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= +cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= +cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= +cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz0njv7sMx/iek= +cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0= +cloud.google.com/go/dialogflow v1.29.0/go.mod h1:b+2bzMe+k1s9V+F2jbJwpHPzrnIyHihAdRFMtn2WXuM= +cloud.google.com/go/dialogflow v1.31.0/go.mod h1:cuoUccuL1Z+HADhyIA7dci3N5zUssgpBJmCzI6fNRB4= +cloud.google.com/go/dialogflow v1.32.0/go.mod h1:jG9TRJl8CKrDhMEcvfcfFkkpp8ZhgPz3sBGmAUYJ2qE= +cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM= +cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q= +cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4= +cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= +cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= +cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k= +cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4= +cloud.google.com/go/documentai v1.16.0/go.mod h1:o0o0DLTEZ+YnJZ+J4wNfTxmDVyrkzFvttBXXtYRMHkM= +cloud.google.com/go/documentai v1.18.0/go.mod h1:F6CK6iUH8J81FehpskRmhLq/3VlwQvb7TvwOceQ2tbs= +cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= +cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= +cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE= +cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= +cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= +cloud.google.com/go/edgecontainer v0.3.0/go.mod h1:FLDpP4nykgwwIfcLt6zInhprzw0lEi2P1fjO6Ie0qbc= +cloud.google.com/go/edgecontainer v1.0.0/go.mod h1:cttArqZpBB2q58W/upSG++ooo6EsblxDIolxa3jSjbY= +cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= +cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= +cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= +cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aUF2CTzdNtvv42niCX0M= +cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= +cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw= +cloud.google.com/go/eventarc v1.10.0/go.mod h1:u3R35tmZ9HvswGRBnF48IlYgYeBcPUCjkr4BTdem2Kw= +cloud.google.com/go/eventarc v1.11.0/go.mod h1:PyUjsUKPWoRBCHeOxZd/lbOOjahV41icXyUY5kSTvVY= +cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= +cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= +cloud.google.com/go/filestore v1.5.0/go.mod h1:FqBXDWBp4YLHqRnVGveOkHDf8svj9r5+mUDLupOWEDs= +cloud.google.com/go/filestore v1.6.0/go.mod h1:di5unNuss/qfZTw2U9nhFqo8/ZDSc466dre85Kydllg= +cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= +cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= +cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= +cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= +cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08= +cloud.google.com/go/functions v1.10.0/go.mod h1:0D3hEOe3DbEvCXtYOZHQZmD+SzYsi1YbI7dGvHfldXw= +cloud.google.com/go/functions v1.12.0/go.mod h1:AXWGrF3e2C/5ehvwYo/GH6O5s09tOPksiKhz+hH8WkA= +cloud.google.com/go/functions v1.13.0/go.mod h1:EU4O007sQm6Ef/PwRsI8N2umygGqPBS/IZQKBQBcJ3c= +cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= +cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= +cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w= +cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM= +cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0= +cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60= +cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo= +cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg= +cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= +cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= +cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+obZ+QTky2Myw= +cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= +cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= +cloud.google.com/go/gkehub v0.11.0/go.mod h1:JOWHlmN+GHyIbuWQPl47/C2RFhnFKH38jH9Ascu3n0E= +cloud.google.com/go/gkehub v0.12.0/go.mod h1:djiIwwzTTBrF5NaXCGv3mf7klpEMcST17VBTVVDcuaw= +cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA= +cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI= +cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y= +cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= +cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM= +cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o= +cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo= +cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= +cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= +cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= +cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc= +cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= +cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= +cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY= +cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= +cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= +cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= +cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= +cloud.google.com/go/iap v1.6.0/go.mod h1:NSuvI9C/j7UdjGjIde7t7HBz+QTwBcapPE07+sSRcLk= +cloud.google.com/go/iap v1.7.0/go.mod h1:beqQx56T9O1G1yNPph+spKpNibDlYIiIixiqsQXxLIo= +cloud.google.com/go/iap v1.7.1/go.mod h1:WapEwPc7ZxGt2jFGB/C/bm+hP0Y6NXzOYGjpPnmMS74= +cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= +cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= +cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4= +cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= +cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= +cloud.google.com/go/iot v1.5.0/go.mod h1:mpz5259PDl3XJthEmh9+ap0affn/MqNSP4My77Qql9o= +cloud.google.com/go/iot v1.6.0/go.mod h1:IqdAsmE2cTYYNO1Fvjfzo9po179rAtJeVGUvkLN3rLE= +cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= +cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= +cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= +cloud.google.com/go/kms v1.8.0/go.mod h1:4xFEhYFqvW+4VMELtZyxomGSYtSQKzM178ylFW4jMAg= +cloud.google.com/go/kms v1.9.0/go.mod h1:qb1tPTgfF9RQP8e1wq4cLFErVuTJv7UsSC915J8dh3w= +cloud.google.com/go/kms v1.10.0/go.mod h1:ng3KTUtQQU9bPX3+QGLsflZIHlkbn8amFAMY63m8d24= +cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI= +cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= +cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= +cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= +cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8= +cloud.google.com/go/language v1.9.0/go.mod h1:Ns15WooPM5Ad/5no/0n81yUetis74g3zrbeJBE+ptUY= +cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= +cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= +cloud.google.com/go/lifesciences v0.8.0/go.mod h1:lFxiEOMqII6XggGbOnKiyZ7IBwoIqA84ClvoezaA/bo= +cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw= +cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= +cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= +cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= +cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= +cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= +cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= +cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA= +cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= +cloud.google.com/go/maps v0.6.0/go.mod h1:o6DAMMfb+aINHz/p/jbcY+mYeXBoZoxTfdSQ8VAJaCw= +cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY= +cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= +cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= +cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I= +cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= +cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= +cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA= +cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY= +cloud.google.com/go/memcache v1.9.0/go.mod h1:8oEyzXCu+zo9RzlEaEjHl4KkgjlNDaXbCQeQWlzNFJM= +cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= +cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= +cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8= +cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI= +cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJPWOodSaf45Eo= +cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk= +cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= +cloud.google.com/go/monitoring v1.12.0/go.mod h1:yx8Jj2fZNEkL/GYZyTLS4ZtZEZN8WtDEiEqG4kLK50w= +cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw= +cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= +cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= +cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= +cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8= +cloud.google.com/go/networkconnectivity v1.10.0/go.mod h1:UP4O4sWXJG13AqrTdQCD9TnLGEbtNRqjuaaA7bNjF5E= +cloud.google.com/go/networkconnectivity v1.11.0/go.mod h1:iWmDD4QF16VCDLXUqvyspJjIEtBR/4zq5hwnY2X3scM= +cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8= +cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4= +cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY= +cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= +cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= +cloud.google.com/go/networksecurity v0.7.0/go.mod h1:mAnzoxx/8TBSyXEeESMy9OOYwo1v+gZ5eMRnsT5bC8k= +cloud.google.com/go/networksecurity v0.8.0/go.mod h1:B78DkqsxFG5zRSVuwYFRZ9Xz8IcQ5iECsNrPn74hKHU= +cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= +cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= +cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA= +cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0= +cloud.google.com/go/notebooks v1.7.0/go.mod h1:PVlaDGfJgj1fl1S3dUwhFMXFgfYGhYQt2164xOMONmE= +cloud.google.com/go/notebooks v1.8.0/go.mod h1:Lq6dYKOYOWUCTvw5t2q1gp1lAp0zxAxRycayS0iJcqQ= +cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4= +cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs= +cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI= +cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA= +cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk= +cloud.google.com/go/orchestration v1.6.0/go.mod h1:M62Bevp7pkxStDfFfTuCOaXgaaqRAga1yKyoMtEoWPQ= +cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE= +cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc= +cloud.google.com/go/orgpolicy v1.10.0/go.mod h1:w1fo8b7rRqlXlIJbVhOMPrwVljyuW5mqssvBtU18ONc= +cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= +cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= +cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo= +cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw= +cloud.google.com/go/osconfig v1.11.0/go.mod h1:aDICxrur2ogRd9zY5ytBLV89KEgT2MKB2L/n6x1ooPw= +cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= +cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= +cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70= +cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo= +cloud.google.com/go/oslogin v1.9.0/go.mod h1:HNavntnH8nzrn8JCTT5fj18FuJLFJc4NaZJtBnQtKFs= +cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= +cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= +cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2omRLSLYSu9bU0EKCNI+Lk= +cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg= +cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE= +cloud.google.com/go/policytroubleshooter v1.5.0/go.mod h1:Rz1WfV+1oIpPdN2VvvuboLVRsB1Hclg3CKQ53j9l8vw= +cloud.google.com/go/policytroubleshooter v1.6.0/go.mod h1:zYqaPTsmfvpjm5ULxAyD/lINQxJ0DDsnWOP/GZ7xzBc= +cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= +cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= +cloud.google.com/go/privatecatalog v0.7.0/go.mod h1:2s5ssIFO69F5csTXcwBP7NPFTZvps26xGzvQ2PQaBYg= +cloud.google.com/go/privatecatalog v0.8.0/go.mod h1:nQ6pfaegeDAq/Q5lrfCQzQLhubPiZhSaNhIgfJlnIXs= 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.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI= +cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0= +cloud.google.com/go/pubsub v1.28.0/go.mod h1:vuXFpwaVoIPQMGXqRyUQigu/AX1S3IWugR9xznmcXX8= +cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4= +cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg= +cloud.google.com/go/pubsublite v1.6.0/go.mod h1:1eFCS0U11xlOuMFV/0iBqw3zP12kddMeCbj/F3FSj9k= +cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM= +cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= +cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= +cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= +cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= +cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE= +cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U= +cloud.google.com/go/recaptchaenterprise/v2 v2.6.0/go.mod h1:RPauz9jeLtB3JVzg6nCbe12qNoaa8pXc4d/YukAmcnA= +cloud.google.com/go/recaptchaenterprise/v2 v2.7.0/go.mod h1:19wVj/fs5RtYtynAPJdDTb69oW0vNHYDBTbB4NvMD9c= +cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= +cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= +cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac= +cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= +cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= +cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs= +cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70= +cloud.google.com/go/recommender v1.9.0/go.mod h1:PnSsnZY7q+VL1uax2JWkt/UegHssxjUVVCrX52CuEmQ= +cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= +cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= +cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA= +cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM= +cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0fWAJ7uQ= +cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA= +cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0= +cloud.google.com/go/resourcemanager v1.5.0/go.mod h1:eQoXNAiAvCf5PXxWxXjhKQoTMaUSNrEfg+6qdf/wots= +cloud.google.com/go/resourcemanager v1.6.0/go.mod h1:YcpXGRs8fDzcUl1Xw8uOVmI8JEadvhRIkoXXUNVYcVo= +cloud.google.com/go/resourcemanager v1.7.0/go.mod h1:HlD3m6+bwhzj9XCouqmeiGuni95NTrExfhoSrkC/3EI= +cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU= +cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg= +cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA= +cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= +cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= +cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc= +cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y= +cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQkVPU5kF14= +cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do= +cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo= +cloud.google.com/go/run v0.8.0/go.mod h1:VniEnuBwqjigv0A7ONfQUaEItaiCRVujlMqerPPiktM= +cloud.google.com/go/run v0.9.0/go.mod h1:Wwu+/vvg8Y+JUApMwEDfVfhetv30hCG4ZwDR/IXl2Qg= +cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= +cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= +cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk= +cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44= +cloud.google.com/go/scheduler v1.8.0/go.mod h1:TCET+Y5Gp1YgHT8py4nlg2Sew8nUHMqcpousDgXJVQc= +cloud.google.com/go/scheduler v1.9.0/go.mod h1:yexg5t+KSmqu+njTIh3b7oYPheFtBWGcbVUYF1GGMIc= +cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= +cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= +cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4= +cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU= +cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= +cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= +cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= +cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q= +cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA= +cloud.google.com/go/security v1.12.0/go.mod h1:rV6EhrpbNHrrxqlvW0BWAIawFWq3X90SduMJdFwtLB8= +cloud.google.com/go/security v1.13.0/go.mod h1:Q1Nvxl1PAgmeW0y3HTt54JYIvUdtcpYKVfIB8AOMZ+0= +cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= +cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= +cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk= +cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk= +cloud.google.com/go/securitycenter v1.18.1/go.mod h1:0/25gAzCM/9OL9vVx4ChPeM/+DlfGQJDwBy/UC8AKK0= +cloud.google.com/go/securitycenter v1.19.0/go.mod h1:LVLmSg8ZkkyaNy4u7HCIshAngSQ8EcIRREP3xBnyfag= +cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU= +cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s= +cloud.google.com/go/servicecontrol v1.10.0/go.mod h1:pQvyvSRh7YzUF2efw7H87V92mxU8FnFDawMClGCNuAA= +cloud.google.com/go/servicecontrol v1.11.0/go.mod h1:kFmTzYzTUIuZs0ycVqRHNaNhgR+UMUpw9n02l/pY+mc= +cloud.google.com/go/servicecontrol v1.11.1/go.mod h1:aSnNNlwEFBY+PWGQ2DoM0JJ/QUXqV5/ZD9DOLB7SnUk= +cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= +cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= +cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4= +cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U= +cloud.google.com/go/servicedirectory v1.8.0/go.mod h1:srXodfhY1GFIPvltunswqXpVxFPpZjf8nkKQT7XcXaY= +cloud.google.com/go/servicedirectory v1.9.0/go.mod h1:29je5JjiygNYlmsGz8k6o+OZ8vd4f//bQLtvzkPPT/s= +cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco= +cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo= +cloud.google.com/go/servicemanagement v1.6.0/go.mod h1:aWns7EeeCOtGEX4OvZUWCCJONRZeFKiptqKf1D0l/Jc= +cloud.google.com/go/servicemanagement v1.8.0/go.mod h1:MSS2TDlIEQD/fzsSGfCdJItQveu9NXnUniTrq/L8LK4= +cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E= +cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU= +cloud.google.com/go/serviceusage v1.5.0/go.mod h1:w8U1JvqUqwJNPEOTQjrMHkw3IaIFLoLsPLvsE3xueec= +cloud.google.com/go/serviceusage v1.6.0/go.mod h1:R5wwQcbOWsyuOfbP9tGdAnCAc6B9DRwPG1xtWMDeuPA= +cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= +cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= +cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A= +cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= +cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= +cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= +cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= +cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= +cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= +cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco= +cloud.google.com/go/speech v1.14.1/go.mod h1:gEosVRPJ9waG7zqqnsHpYTOoAS4KouMRLDFMekpJ0J0= +cloud.google.com/go/speech v1.15.0/go.mod h1:y6oH7GhqCaZANH7+Oe0BhgIogsNInLlz542tg3VqeYI= 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= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= +cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= +cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= +cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= +cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= +cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= +cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= +cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4= +cloud.google.com/go/storagetransfer v1.8.0/go.mod h1:JpegsHHU1eXg7lMHkvf+KE5XDJ7EQu0GwNJbbVGanEw= +cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= +cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= +cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM= +cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA= +cloud.google.com/go/talent v1.5.0/go.mod h1:G+ODMj9bsasAEJkQSzO2uHQWXHHXUomArjWQQYkqK6c= +cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8= +cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4= +cloud.google.com/go/texttospeech v1.6.0/go.mod h1:YmwmFT8pj1aBblQOI3TfKmwibnsfvhIBzPXcW4EBovc= +cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ= +cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg= +cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV61fPM= +cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28= +cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= +cloud.google.com/go/trace v1.8.0/go.mod h1:zH7vcsbAhklH8hWFig58HvxcxyQbaIqMarMg9hn5ECA= +cloud.google.com/go/trace v1.9.0/go.mod h1:lOQqpE5IaWY0Ixg7/r2SjixMuc6lfTFeO4QGM4dQWOk= +cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs= +cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg= +cloud.google.com/go/translate v1.5.0/go.mod h1:29YDSYveqqpA1CQFD7NQuP49xymq17RXNaUDdc0mNu0= +cloud.google.com/go/translate v1.6.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= +cloud.google.com/go/translate v1.7.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= +cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk= +cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw= +cloud.google.com/go/video v1.12.0/go.mod h1:MLQew95eTuaNDEGriQdcYn0dTwf9oWiA4uYebxM5kdg= +cloud.google.com/go/video v1.13.0/go.mod h1:ulzkYlYgCp15N2AokzKjy7MQ9ejuynOJdf1tR5lGthk= +cloud.google.com/go/video v1.14.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= +cloud.google.com/go/video v1.15.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= +cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= +cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= +cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M= +cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU= +cloud.google.com/go/videointelligence v1.10.0/go.mod h1:LHZngX1liVtUhZvi2uNS0VQuOzNi2TkY1OakiuoUOjU= +cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= +cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= +cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= +cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY= +cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= +cloud.google.com/go/vision/v2 v2.6.0/go.mod h1:158Hes0MvOS9Z/bDMSFpjwsUrZ5fPrdwuyyvKSGAGMY= +cloud.google.com/go/vision/v2 v2.7.0/go.mod h1:H89VysHy21avemp6xcf9b9JvZHVehWbET0uT/bcuY/0= +cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= +cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= +cloud.google.com/go/vmmigration v1.5.0/go.mod h1:E4YQ8q7/4W9gobHjQg4JJSgXXSgY21nA5r8swQV+Xxc= +cloud.google.com/go/vmmigration v1.6.0/go.mod h1:bopQ/g4z+8qXzichC7GW1w2MjbErL54rk3/C843CjfY= +cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208= +cloud.google.com/go/vmwareengine v0.2.2/go.mod h1:sKdctNJxb3KLZkE/6Oui94iw/xs9PRNC2wnNLXsHvH8= +cloud.google.com/go/vmwareengine v0.3.0/go.mod h1:wvoyMvNWdIzxMYSpH/R7y2h5h3WFkx6d+1TIsP39WGY= +cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= +cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= +cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes= +cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= +cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= +cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc= +cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A= +cloud.google.com/go/webrisk v1.8.0/go.mod h1:oJPDuamzHXgUc+b8SiHRcVInZQuybnvEW72PqTc7sSg= +cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo= +cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ= +cloud.google.com/go/websecurityscanner v1.5.0/go.mod h1:Y6xdCPy81yi0SQnDY1xdNTNpfY1oAgXUlcfN3B3eSng= +cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= +cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= +cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= +cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= +cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= +git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= 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/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/NebulousLabs/fastrand v0.0.0-20181203155948-6fb6489aac4e h1:n+DcnTNkQnHlwpsrHoQtkrJIO7CBx029fw6oR4vIob4= @@ -45,24 +610,34 @@ github.com/NebulousLabs/go-upnp v0.0.0-20180202185039-29b680b06c82 h1:MG93+PZYs9 github.com/NebulousLabs/go-upnp v0.0.0-20180202185039-29b680b06c82/go.mod h1:GbuBk21JqF+driLX3XtJYNZjGa45YDoa9IqCTzNSfEc= 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/Yawning/aez v0.0.0-20211027044916-e49e68abd344 h1:cDVUiFo+npB0ZASqnw4q90ylaVAbnYyx0JYqK4YcGok= github.com/Yawning/aez v0.0.0-20211027044916-e49e68abd344/go.mod h1:9pIqrY6SXNL8vjRQE5Hd/OL5GyK/9MrGUWs87z/eFfk= 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= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= +github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= +github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= 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/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= +github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI= +github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= 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/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= 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= @@ -118,8 +693,12 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f 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/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/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= +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/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0/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= @@ -127,6 +706,18 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P 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-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/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/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-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 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= @@ -173,16 +764,30 @@ github.com/docker/go-connections v0.7.0 h1:6SsRfJddP22WMrCkj19x9WKjEDTB+ahsdiGYf github.com/docker/go-connections v0.7.0/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q= 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/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 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/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.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= +github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= +github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= +github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= +github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= 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/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/frankban/quicktest v1.0.0/go.mod h1:R98jIehRai+d1/3Hv2//jOVCTJhW1VBavT6B6CuGq2k= @@ -196,6 +801,10 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4 github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= +github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= +github.com/go-fonts/liberation v0.2.0/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= 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= @@ -203,6 +812,7 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 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-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= 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= @@ -214,18 +824,24 @@ 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-macaroon-bakery/macaroonpb v1.0.0 h1:It9exBaRMZ9iix1iJ6gwzfwsDE6ExNuwtAJ9e09v6XE= github.com/go-macaroon-bakery/macaroonpb v1.0.0/go.mod h1:UzrGOcbiwTXISFP2XDLDPjfhMINZa+fX/7A2lMd31zc= +github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= +github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= 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/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= 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/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= +github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= 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= @@ -236,6 +852,8 @@ 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.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= @@ -247,31 +865,46 @@ 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/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.3/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/gonum/gonum v0.11.0 h1:Lffpf1Aq8WeVUJTbfiKHlOVlFm+c021iePrlwvE5woI= github.com/gonum/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= +github.com/gonum/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo= 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/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= 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.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.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 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/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/martian/v3 v3.3.2/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= @@ -279,16 +912,41 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf 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-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-20201218002935-b9804c9f04c2/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-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/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo= github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= 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.3.0/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/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= +github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= 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/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= +github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= +github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= +github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= +github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= +github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= +github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= +github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -298,6 +956,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92Bcuy 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.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -308,7 +968,9 @@ github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9 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/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/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/pgconn v1.14.3 h1:bVoTr12EGANZz66nZPkMInAV/KHD2TxH9npjXXgiB3w= @@ -355,18 +1017,25 @@ github.com/juju/schema v1.0.0/go.mod h1:Y+ThzXpUJ0E7NYYocAbuvJ7vTivXfrof/IfRPq/0 github.com/juju/webbrowser v0.0.0-20160309143629-54b8c57083b4/go.mod h1:G6PCelgkM6cuvyD10iYJsjLBsSadVXtJ+nBxFAxE2BU= 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/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +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/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= +github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= 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/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.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -426,13 +1095,22 @@ github.com/lightningnetwork/lnd/tor v1.1.6/go.mod h1:qSRB8llhAK+a6kaTPWOLLXSZc6H 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= +github.com/lukechampine/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= +github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= +github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 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-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= +github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= +github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= 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/moby/api v1.54.2 h1:wiat9QAhnDQjA7wk1kh/TqHz2I1uUA7M7t9SAl/JNXg= @@ -480,10 +1158,17 @@ github.com/opencontainers/runc v1.3.6/go.mod h1:o1wyv76EDlTkcf0KTFgN8bMWLPvgF/Hf 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/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= +github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +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/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= 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/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -512,16 +1197,21 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= 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/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 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.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= 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/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= +github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= 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= @@ -529,6 +1219,10 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -540,9 +1234,13 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/ 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/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 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= @@ -571,6 +1269,10 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de 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.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= +github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec h1:FpfFs4EhNehiVfzQttTuxanPIT43FtkkCFypIod8LHo= gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec/go.mod h1:BZ1RAoRPbCxum9Grlv5aeksu2H8BiKehBYooU2LFiOQ= go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo= @@ -594,6 +1296,9 @@ 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.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= 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= @@ -614,6 +1319,9 @@ go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRk go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= +go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= 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.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -636,24 +1344,39 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/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-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988= golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc= 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= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= 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-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= 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/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/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= 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= @@ -664,6 +1387,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= @@ -672,7 +1397,15 @@ 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.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.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= golang.org/x/net v0.0.0-20150829230318-ea47fc708ee3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -709,12 +1442,39 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R 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-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-20201202161906-c7110b5ffcbb/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-20201224014010-6772e930b67b/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-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/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-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.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.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -722,8 +1482,30 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr 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-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= +golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= +golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= +golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= 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= @@ -735,6 +1517,11 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ 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/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/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.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -760,6 +1547,7 @@ golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7w 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= @@ -776,25 +1564,72 @@ golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7w 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-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-20210104204734-6f8348627aad/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-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/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-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-20210514084401-e8d321eab015/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-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-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-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-20211025201205-69cdffdb9359/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-20211210111614-af8b64212486/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-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/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-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/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-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220624220833-87e55d714810/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-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.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.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY= golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= 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.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= +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.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -802,13 +1637,25 @@ 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.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.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.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= 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-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -826,6 +1673,7 @@ golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgw 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-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/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-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -854,14 +1702,36 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY 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-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/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-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +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.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +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.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= 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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= 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= @@ -878,12 +1748,54 @@ 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.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= +google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= +google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= +google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= +google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= +google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= +google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= +google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= +google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g= +google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= +google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= +google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI= +google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08= +google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= +google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= +google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= +google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= +google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= +google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= 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/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/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= @@ -910,10 +1822,113 @@ google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfG 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-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-20210108203827-ffc7fda8c3d7/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-20210226172003-ab064af71705/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-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +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-20211118181313-81c1377c94b1/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/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE= +google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= +google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw= +google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= +google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= +google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= +google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= +google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= +google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= +google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= +google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo= +google.golang.org/genproto v0.0.0-20221109142239-94d6d90a7d66/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221117204609-8f9c96812029/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221201204527-e3fa12d562f3/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= +google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230112194545-e10362b5ecf9/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230123190316-2c411cf9d197/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230125152338-dcaf20b6aeaa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230127162408-596548ed4efa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA= +google.golang.org/genproto v0.0.0-20230222225845-10f96fb3dbec/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= +google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= +google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= +google.golang.org/genproto v0.0.0-20230320184635-7606e756e683/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= +google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= 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-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8= @@ -932,9 +1947,38 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa 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.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= +google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= +google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= +google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/grpc v1.83.1 h1:HIO0+BEtBP6soyqvqC8sNUjZ7bTs+0hFQuFF+RAy++Y= google.golang.org/grpc v1.83.1/go.mod h1:kDyl6SKsiHKt0uylY5gtn5cEjkrIOhQOGDgIc4JGwzQ= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= 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= @@ -979,33 +2023,66 @@ 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.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= +modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ= modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= +modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= +modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= +modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= +modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= +modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws= +modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo= modernc.org/ccgo/v4 v4.19.2 h1:lwQZgvboKD0jBwdaeVCTouxhxAyN6iawF3STraAal8Y= modernc.org/ccgo/v4 v4.19.2/go.mod h1:ysS3mxiMV38XGRTTcgo0DQTeTmAO4oCmJl1nX9VFI3s= +modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw= modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU= +modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= +modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= +modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= +modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU= +modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= +modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= +modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0= +modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s= modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U= modernc.org/libc v1.55.3/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w= +modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= +modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= +modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= +modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= +modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc= modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= +modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4= modernc.org/sqlite v1.34.5 h1:Bb6SR13/fjp15jt70CL4f18JIN7p7dnMExd+UFnF15g= modernc.org/sqlite v1.34.5/go.mod h1:YLuNmX9NKs8wRNK2ko1LW1NGYcc9FkBO69JOt1AR9JE= +modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= +modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= +modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= +modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk= pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= 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= From 2ee5b52b68459169236a0bb59e3d5226f405caa6 Mon Sep 17 00:00:00 2001 From: Slyghtning Date: Thu, 3 Sep 2026 09:37:22 +0200 Subject: [PATCH 2/5] assets: Move legacy deposit kit into Loop Consolidate the remaining deposit and OP_TRUE virtual-packet helpers behind Loop-owned packages. Replace positional sweep assumptions with proof-bound input selection, complete prevout validation, and explicit signature verification. --- assets/deposit/doc.go | 5 + assets/deposit/kit.go | 650 +++++++++++++++++++++++++++++++++++++ assets/deposit/kit_test.go | 465 ++++++++++++++++++++++++++ assets/tapkit.go | 146 +++++++++ assets/tapkit_test.go | 107 ++++++ go.sum | 4 + 6 files changed, 1377 insertions(+) create mode 100644 assets/deposit/doc.go create mode 100644 assets/deposit/kit.go create mode 100644 assets/deposit/kit_test.go create mode 100644 assets/tapkit.go create mode 100644 assets/tapkit_test.go diff --git a/assets/deposit/doc.go b/assets/deposit/doc.go new file mode 100644 index 000000000..53198dc66 --- /dev/null +++ b/assets/deposit/doc.go @@ -0,0 +1,5 @@ +// Package deposit contains the legacy Taproot Asset deposit contract used by +// the Loop integration environment. It owns deposit address construction, +// proof validation, and the unilateral timeout path. Asset HTLC construction +// remains in the sibling htlc package. +package deposit diff --git a/assets/deposit/kit.go b/assets/deposit/kit.go new file mode 100644 index 000000000..c4ea54cac --- /dev/null +++ b/assets/deposit/kit.go @@ -0,0 +1,650 @@ +package deposit + +import ( + "bytes" + "context" + "fmt" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/btcsuite/btcd/btcec/v2/schnorr/musig2" + "github.com/btcsuite/btcd/btcutil/psbt" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" + "github.com/decred/dcrd/dcrec/secp256k1/v4" + "github.com/lightninglabs/lndclient" + "github.com/lightninglabs/loop/assets/htlc" + "github.com/lightninglabs/taproot-assets/address" + "github.com/lightninglabs/taproot-assets/asset" + "github.com/lightninglabs/taproot-assets/commitment" + "github.com/lightninglabs/taproot-assets/proof" + "github.com/lightninglabs/taproot-assets/rpcutils" + "github.com/lightninglabs/taproot-assets/taprpc" + "github.com/lightninglabs/taproot-assets/tapscript" + "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/keychain" + "github.com/lightningnetwork/lnd/lntypes" + "google.golang.org/grpc" +) + +// AddressProofClient is the narrow tapd boundary needed to create deposit +// addresses and export their proofs. +type AddressProofClient interface { + NewAddr(context.Context, *taprpc.NewAddrRequest, + ...grpc.CallOption) (*taprpc.Addr, error) + ExportProof(context.Context, *taprpc.ExportProofRequest, + ...grpc.CallOption) (*taprpc.ProofFile, error) +} + +// Kit contains the immutable information needed to create and operate a +// two-party MuSig2 asset deposit. +type Kit struct { + funderKey *btcec.PublicKey + coSignerKey *btcec.PublicKey + keyLocator keychain.KeyLocator + assetID asset.ID + csvExpiry uint32 + muSig2Key *musig2.AggregateKey + chainParams *address.ChainParams +} + +// NewKit creates a validated legacy asset deposit kit. +func NewKit(funderKey, coSignerKey *btcec.PublicKey, + keyLocator keychain.KeyLocator, assetID asset.ID, csvExpiry uint32, + chainParams *address.ChainParams) (*Kit, error) { + + if funderKey == nil { + return nil, fmt.Errorf("funder public key is required") + } + if coSignerKey == nil { + return nil, fmt.Errorf("co-signer public key is required") + } + if funderKey.IsEqual(coSignerKey) { + return nil, fmt.Errorf("funder and co-signer keys must differ") + } + if assetID == (asset.ID{}) { + return nil, fmt.Errorf("asset ID is required") + } + if csvExpiry == 0 { + return nil, fmt.Errorf("CSV expiry must be positive") + } + if chainParams == nil || chainParams.Params == nil || + chainParams.TapHRP == "" { + + return nil, fmt.Errorf("address parameters are incomplete") + } + + funderKeyCopy, err := btcec.ParsePubKey( + funderKey.SerializeCompressed(), + ) + if err != nil { + return nil, fmt.Errorf("invalid funder public key: %w", err) + } + coSignerKeyCopy, err := btcec.ParsePubKey( + coSignerKey.SerializeCompressed(), + ) + if err != nil { + return nil, fmt.Errorf("invalid co-signer public key: %w", err) + } + + sortKeys := true + muSig2Key, err := input.MuSig2CombineKeys( + input.MuSig2Version100RC2, + []*btcec.PublicKey{funderKeyCopy, coSignerKeyCopy}, sortKeys, + // The actual BIP341 tweak includes the asset and timeout roots, + // which are only known once the deposit proof is available. + &input.MuSig2Tweaks{}, + ) + if err != nil { + return nil, err + } + + return &Kit{ + funderKey: funderKeyCopy, + coSignerKey: coSignerKeyCopy, + keyLocator: keyLocator, + assetID: assetID, + csvExpiry: csvExpiry, + muSig2Key: muSig2Key, + chainParams: cloneAddressParams(*chainParams), + }, nil +} + +// cloneAddressParams returns an independent copy of address parameters, +// including the nested Bitcoin network parameters when present. +func cloneAddressParams(params address.ChainParams) *address.ChainParams { + paramsCopy := params + if params.Params != nil { + bitcoinParams := *params.Params + paramsCopy.Params = &bitcoinParams + } + + return ¶msCopy +} + +// GenTimeoutPathScript constructs the deposit funder's CSV timeout script. +// +// OP_CHECKSIGVERIFY OP_CHECKSEQUENCEVERIFY +func (d *Kit) GenTimeoutPathScript() ([]byte, error) { + if d == nil || d.funderKey == nil { + return nil, fmt.Errorf("deposit kit is incomplete") + } + + builder := txscript.NewScriptBuilder() + builder.AddData(schnorr.SerializePubKey(d.funderKey)) + builder.AddOp(txscript.OP_CHECKSIGVERIFY) + builder.AddInt64(int64(d.csvExpiry)) + builder.AddOp(txscript.OP_CHECKSEQUENCEVERIFY) + + return builder.Script() +} + +// timeoutPathSibling returns the timeout leaf as a Taproot Asset sibling +// preimage. +func (d *Kit) timeoutPathSibling() (*commitment.TapscriptPreimage, error) { + timeoutScript, err := d.GenTimeoutPathScript() + if err != nil { + return nil, err + } + + btcTapLeaf := txscript.NewBaseTapLeaf(timeoutScript) + sibling, err := commitment.NewPreimageFromLeaf(btcTapLeaf) + if err != nil { + return nil, err + } + + return sibling, nil +} + +// encodedTimeoutPathSibling returns the timeout sibling in its canonical wire +// encoding. +func (d *Kit) encodedTimeoutPathSibling() ([]byte, error) { + sibling, err := d.timeoutPathSibling() + if err != nil { + return nil, err + } + + siblingBytes, _, err := commitment.MaybeEncodeTapscriptPreimage(sibling) + if err != nil { + return nil, err + } + + return siblingBytes, nil +} + +// NewAddr creates a two-party MuSig2 deposit address with a unilateral funder +// timeout path. +func (d *Kit) NewAddr(ctx context.Context, client AddressProofClient, + amount uint64) (*taprpc.Addr, error) { + + if d == nil { + return nil, fmt.Errorf("deposit kit is required") + } + if client == nil { + return nil, fmt.Errorf("tapd client is required") + } + if amount == 0 { + return nil, fmt.Errorf("deposit amount must be positive") + } + + siblingBytes, err := d.encodedTimeoutPathSibling() + if err != nil { + return nil, err + } + tapScriptKey, _, _, _, err := htlc.CreateOpTrueLeaf() + if err != nil { + return nil, err + } + + return client.NewAddr(ctx, &taprpc.NewAddrRequest{ + AssetId: d.assetID[:], + Amt: amount, + ScriptKey: rpcutils.MarshalScriptKey(tapScriptKey), + InternalKey: &taprpc.KeyDescriptor{ + RawKeyBytes: d.muSig2Key.PreTweakedKey.SerializeCompressed(), + }, + TapscriptSibling: siblingBytes, + }) +} + +// NewHtlcAddr creates an HTLC address using the deposit parties as sender and +// receiver under the immutable legacy deposit policy. +func (d *Kit) NewHtlcAddr(ctx context.Context, client AddressProofClient, + amount uint64, swapHash lntypes.Hash, csvExpiry uint32) ( + *taprpc.Addr, *htlc.SwapKit, error) { + + if d == nil { + return nil, nil, fmt.Errorf("deposit kit is required") + } + if client == nil { + return nil, nil, fmt.Errorf("tapd client is required") + } + + swapKit, err := d.newHtlcSwapKit(amount, swapHash, csvExpiry) + if err != nil { + return nil, nil, err + } + btcInternalKey, err := swapKit.GetAggregateKey() + if err != nil { + return nil, nil, err + } + sibling, err := swapKit.GetSiblingPreimage() + if err != nil { + return nil, nil, err + } + siblingBytes, _, err := commitment.MaybeEncodeTapscriptPreimage(&sibling) + if err != nil { + return nil, nil, err + } + tapScriptKey, _, _, _, err := htlc.CreateOpTrueLeaf() + if err != nil { + return nil, nil, err + } + + htlcAddr, err := client.NewAddr(ctx, &taprpc.NewAddrRequest{ + AssetId: d.assetID[:], + Amt: amount, + ScriptKey: rpcutils.MarshalScriptKey(tapScriptKey), + InternalKey: &taprpc.KeyDescriptor{ + RawKeyBytes: btcInternalKey.SerializeCompressed(), + }, + TapscriptSibling: siblingBytes, + }) + if err != nil { + return nil, nil, err + } + + return htlcAddr, swapKit, nil +} + +// newHtlcSwapKit derives the immutable legacy HTLC contract for a deposit. +func (d *Kit) newHtlcSwapKit(amount uint64, swapHash lntypes.Hash, + csvExpiry uint32) (*htlc.SwapKit, error) { + + return htlc.NewSwapKit(htlc.LegacyDepositV0, htlc.Params{ + SenderPubKey: d.funderKey, + ReceiverPubKey: d.coSignerKey, + AssetID: d.assetID, + Amount: amount, + SwapHash: swapHash, + CsvExpiry: csvExpiry, + AddressParams: d.chainParams, + }) +} + +// TapScriptKey returns the OP_TRUE asset script key used by deposits. +func (d *Kit) TapScriptKey() (asset.ScriptKey, error) { + tapScriptKey, _, _, _, err := htlc.CreateOpTrueLeaf() + if err != nil { + return asset.ScriptKey{}, err + } + + return asset.NewScriptKey(tapScriptKey.PubKey), nil +} + +// ExportProof exports the proof for an exact deposit outpoint. +func (d *Kit) ExportProof(ctx context.Context, client AddressProofClient, + outpoint *wire.OutPoint) (*taprpc.ProofFile, error) { + + if d == nil { + return nil, fmt.Errorf("deposit kit is required") + } + if client == nil { + return nil, fmt.Errorf("tapd client is required") + } + if outpoint == nil { + return nil, fmt.Errorf("deposit outpoint is required") + } + scriptKey, err := d.TapScriptKey() + if err != nil { + return nil, err + } + + return client.ExportProof(ctx, &taprpc.ExportProofRequest{ + AssetId: d.assetID[:], + ScriptKey: scriptKey.PubKey.SerializeCompressed(), + Outpoint: &taprpc.OutPoint{ + Txid: outpoint.Hash[:], + OutputIndex: outpoint.Index, + }, + }) +} + +// validateAsset binds an asset leaf to the identity and script policy of this +// deposit kit. Exact amounts are checked by the protocol operation that knows +// the expected deposit amount. +func (d *Kit) validateAsset(depositAsset *asset.Asset) error { + if depositAsset == nil { + return fmt.Errorf("deposit asset is required") + } + proofID := depositAsset.Genesis.ID() + if !bytes.Equal(d.assetID[:], proofID[:]) { + return fmt.Errorf("asset proof ID does not match deposit") + } + if depositAsset.Amount == 0 { + return fmt.Errorf("deposit asset amount must be positive") + } + if depositAsset.Version != asset.V0 && depositAsset.Version != asset.V1 { + return fmt.Errorf("unsupported legacy deposit asset version") + } + if depositAsset.ScriptVersion != asset.ScriptV0 { + return fmt.Errorf("asset proof script version does not match deposit") + } + if depositAsset.LockTime != 0 || depositAsset.RelativeLockTime != 0 { + return fmt.Errorf("asset proof contains an unexpected locktime") + } + + expectedScriptKey, err := d.TapScriptKey() + if err != nil { + return err + } + if depositAsset.ScriptKey.PubKey == nil || + !depositAsset.ScriptKey.PubKey.IsEqual(expectedScriptKey.PubKey) { + + return fmt.Errorf("asset proof script key does not match deposit") + } + + return nil +} + +// validateProof verifies the proof's commitment structure and binds its +// internal key and timeout sibling to this deposit kit. +func (d *Kit) validateProof(depositProof *proof.Proof) ( + *commitment.TapCommitment, error) { + + if d == nil { + return nil, fmt.Errorf("deposit kit is required") + } + if depositProof == nil { + return nil, fmt.Errorf("deposit proof is required") + } + if err := d.validateAsset(&depositProof.Asset); err != nil { + return nil, err + } + + tapCommitment, err := depositProof.VerifyProofs() + if err != nil { + return nil, fmt.Errorf("invalid deposit proof: %w", err) + } + internalKey := depositProof.InclusionProof.InternalKey + if internalKey == nil || + !internalKey.IsEqual(d.muSig2Key.PreTweakedKey) { + + return nil, fmt.Errorf("deposit internal key mismatch") + } + commitmentProof := depositProof.InclusionProof.CommitmentProof + if commitmentProof == nil || + commitmentProof.TapSiblingPreimage == nil { + + return nil, fmt.Errorf("deposit sibling preimage is required") + } + expectedSibling, err := d.encodedTimeoutPathSibling() + if err != nil { + return nil, err + } + actualSibling, _, err := commitment.MaybeEncodeTapscriptPreimage( + commitmentProof.TapSiblingPreimage, + ) + if err != nil { + return nil, fmt.Errorf("invalid deposit sibling preimage: %w", err) + } + if !bytes.Equal(expectedSibling, actualSibling) { + return nil, fmt.Errorf("deposit sibling preimage mismatch") + } + + return tapCommitment, nil +} + +// VerifyProof verifies the proof commitment and binds it to this deposit's +// asset, internal key, and timeout sibling. It returns the complete Taproot +// Asset commitment root. +func (d *Kit) VerifyProof(depositProof *proof.Proof) ([]byte, error) { + tapCommitment, err := d.validateProof(depositProof) + if err != nil { + return nil, err + } + root := tapCommitment.TapscriptRoot(nil) + + return append([]byte(nil), root[:]...), nil +} + +// GenTimeoutBtcControlBlock creates the deposit timeout-path control block. +func (d *Kit) GenTimeoutBtcControlBlock(taprootAssetRoot []byte) ( + *txscript.ControlBlock, error) { + + if d == nil || d.muSig2Key == nil { + return nil, fmt.Errorf("deposit kit is incomplete") + } + if len(taprootAssetRoot) != chainhash.HashSize { + return nil, fmt.Errorf("asset root must be %d bytes", + chainhash.HashSize) + } + controlBlock := &txscript.ControlBlock{ + InternalKey: d.muSig2Key.PreTweakedKey, + LeafVersion: txscript.BaseLeafVersion, + InclusionProof: append([]byte(nil), taprootAssetRoot...), + } + timeoutScript, err := d.GenTimeoutPathScript() + if err != nil { + return nil, err + } + rootHash := controlBlock.RootHash(timeoutScript) + tapKey := txscript.ComputeTaprootOutputKey( + d.muSig2Key.PreTweakedKey, rootHash, + ) + controlBlock.OutputKeyYIsOdd = tapKey.SerializeCompressed()[0] == + secp256k1.PubKeyFormatCompressedOdd + + return controlBlock, nil +} + +type validatedSweep struct { + assetInputIndex int + prevOutputs []*wire.TxOut + assetRoot []byte +} + +// findUniqueInput returns the sole transaction input that spends outpoint. +func findUniqueInput(tx *wire.MsgTx, outpoint wire.OutPoint) (int, error) { + inputIndex := -1 + for idx, txIn := range tx.TxIn { + if txIn == nil { + return 0, fmt.Errorf("sweep input %d is nil", idx) + } + if txIn.PreviousOutPoint != outpoint { + continue + } + if inputIndex >= 0 { + return 0, fmt.Errorf("proof outpoint appears more than once") + } + inputIndex = idx + } + if inputIndex < 0 { + return 0, fmt.Errorf("asset input does not spend proof outpoint") + } + + return inputIndex, nil +} + +// validateSweep binds a PSBT input and witness UTXO to the deposit proof and +// reconstructs the exact Taproot output being spent. +func (d *Kit) validateSweep(depositProof *proof.Proof, + sweepPacket *psbt.Packet) (*validatedSweep, error) { + + tapCommitment, err := d.validateProof(depositProof) + if err != nil { + return nil, err + } + if sweepPacket == nil || sweepPacket.UnsignedTx == nil { + return nil, fmt.Errorf("sweep PSBT is required") + } + if len(sweepPacket.UnsignedTx.TxIn) == 0 || + len(sweepPacket.UnsignedTx.TxIn) != len(sweepPacket.Inputs) { + + return nil, fmt.Errorf("sweep PSBT input metadata is incomplete") + } + if sweepPacket.UnsignedTx.Version < 2 { + return nil, fmt.Errorf("sweep transaction must use version 2") + } + + assetInputIndex, err := findUniqueInput( + sweepPacket.UnsignedTx, depositProof.OutPoint(), + ) + if err != nil { + return nil, err + } + prevOutputs := make([]*wire.TxOut, len(sweepPacket.Inputs)) + for idx := range sweepPacket.Inputs { + witnessUtxo := sweepPacket.Inputs[idx].WitnessUtxo + if witnessUtxo == nil { + return nil, fmt.Errorf( + "sweep input %d requires a witness UTXO", idx, + ) + } + prevOutputs[idx] = &wire.TxOut{ + Value: witnessUtxo.Value, + PkScript: append( + []byte(nil), witnessUtxo.PkScript..., + ), + } + } + + proofOutputIndex := int(depositProof.InclusionProof.OutputIndex) + if proofOutputIndex >= len(depositProof.AnchorTx.TxOut) { + return nil, fmt.Errorf("proof output index is out of bounds") + } + proofTxOut := depositProof.AnchorTx.TxOut[proofOutputIndex] + if proofTxOut == nil { + return nil, fmt.Errorf("proof anchor output is nil") + } + assetPrevOut := prevOutputs[assetInputIndex] + if proofTxOut.Value != assetPrevOut.Value || + !bytes.Equal(proofTxOut.PkScript, assetPrevOut.PkScript) { + + return nil, fmt.Errorf("asset prevout does not match proof anchor") + } + + sibling, err := d.timeoutPathSibling() + if err != nil { + return nil, err + } + siblingHash, err := sibling.TapHash() + if err != nil { + return nil, err + } + expectedPkScript, err := tapscript.PayToAddrScript( + *d.muSig2Key.PreTweakedKey, siblingHash, *tapCommitment, + ) + if err != nil { + return nil, err + } + if !bytes.Equal(expectedPkScript, assetPrevOut.PkScript) { + return nil, fmt.Errorf("asset input script does not match proof") + } + + assetRootHash := tapCommitment.TapscriptRoot(nil) + return &validatedSweep{ + assetInputIndex: assetInputIndex, + prevOutputs: prevOutputs, + assetRoot: append([]byte(nil), assetRootHash[:]...), + }, nil +} + +// verifyTapscriptSignature checks a signer response against the exact input, +// prevouts, script, and public key used by the timeout spend. +func verifyTapscriptSignature(tx *wire.MsgTx, sweep *validatedSweep, + witnessScript []byte, pubKey *btcec.PublicKey, signature []byte) error { + + parsedSignature, err := schnorr.ParseSignature(signature) + if err != nil { + return fmt.Errorf("signer returned an invalid Schnorr signature: %w", + err) + } + prevOutFetcher := txscript.NewMultiPrevOutFetcher(nil) + for idx, txIn := range tx.TxIn { + prevOutFetcher.AddPrevOut( + txIn.PreviousOutPoint, sweep.prevOutputs[idx], + ) + } + sigHashes := txscript.NewTxSigHashes(tx, prevOutFetcher) + tapLeaf := txscript.NewBaseTapLeaf(witnessScript) + sigHash, err := txscript.CalcTapscriptSignaturehash( + sigHashes, txscript.SigHashDefault, tx, + sweep.assetInputIndex, prevOutFetcher, tapLeaf, + ) + if err != nil { + return fmt.Errorf("unable to calculate asset input sighash: %w", err) + } + if !parsedSignature.Verify(sigHash, pubKey) { + return fmt.Errorf("signer returned a signature for the wrong key") + } + + return nil +} + +// CreateTimeoutWitness signs the exact proof-bound deposit input and returns +// its input index and timeout-path witness. The method sets the required CSV +// sequence on a transaction copy before signing, then writes that sequence to +// the caller's PSBT only after the signature has been verified. +func (d *Kit) CreateTimeoutWitness(ctx context.Context, + signer lndclient.SignerClient, depositProof *proof.Proof, + sweepPacket *psbt.Packet) (*htlc.SpendWitness, error) { + + if signer == nil { + return nil, fmt.Errorf("signer is required") + } + sweep, err := d.validateSweep(depositProof, sweepPacket) + if err != nil { + return nil, err + } + sweepTx := sweepPacket.UnsignedTx.Copy() + sweepTx.TxIn[sweep.assetInputIndex].Sequence = d.csvExpiry + timeoutScript, err := d.GenTimeoutPathScript() + if err != nil { + return nil, err + } + + signDesc := &lndclient.SignDescriptor{ + KeyDesc: keychain.KeyDescriptor{ + KeyLocator: d.keyLocator, + }, + SignMethod: input.TaprootScriptSpendSignMethod, + WitnessScript: timeoutScript, + Output: sweep.prevOutputs[sweep.assetInputIndex], + InputIndex: sweep.assetInputIndex, + } + sigs, err := signer.SignOutputRaw( + ctx, sweepTx, + []*lndclient.SignDescriptor{signDesc}, sweep.prevOutputs, + ) + if err != nil { + return nil, err + } + if len(sigs) != 1 || len(sigs[0]) == 0 { + return nil, fmt.Errorf("signer returned an invalid signature set") + } + if err := verifyTapscriptSignature( + sweepTx, sweep, timeoutScript, d.funderKey, + sigs[0], + ); err != nil { + return nil, err + } + + controlBlock, err := d.GenTimeoutBtcControlBlock(sweep.assetRoot) + if err != nil { + return nil, err + } + controlBlockBytes, err := controlBlock.ToBytes() + if err != nil { + return nil, err + } + sweepPacket.UnsignedTx.TxIn[sweep.assetInputIndex].Sequence = d.csvExpiry + + return &htlc.SpendWitness{ + InputIndex: uint32(sweep.assetInputIndex), + Witness: wire.TxWitness{ + sigs[0], timeoutScript, controlBlockBytes, + }, + }, nil +} diff --git a/assets/deposit/kit_test.go b/assets/deposit/kit_test.go new file mode 100644 index 000000000..31e27529b --- /dev/null +++ b/assets/deposit/kit_test.go @@ -0,0 +1,465 @@ +package deposit + +import ( + "context" + "encoding/hex" + "fmt" + "testing" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil/psbt" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" + "github.com/lightninglabs/lndclient" + "github.com/lightninglabs/loop/assets/htlc" + "github.com/lightninglabs/taproot-assets/address" + "github.com/lightninglabs/taproot-assets/asset" + "github.com/lightninglabs/taproot-assets/commitment" + "github.com/lightninglabs/taproot-assets/proof" + "github.com/lightninglabs/taproot-assets/tapscript" + "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/keychain" + "github.com/lightningnetwork/lnd/lntypes" + "github.com/stretchr/testify/require" +) + +const ( + legacySuccessScript = "20c6047f9441ed7d6d3045406e95c07cd85c778e" + + "4b8cef3ca7abac09b95c709ee5ad82012088a914e6babb9619d7a812" + + "72711fc546a16b211dd939578851b2" + legacyTimeoutScript = "2079be667ef9dcbbac55a06295ce870b07029bfcdb2d" + + "ce28d959f2815b16f81798ad029000b2" + legacyAggregateKey = "023b46d262d2f610e9038b44beabdfe97ab5a0feb" + + "89870acc2264edfb7f63ec2ec" + legacySibling = "01cbf40123d0ca1191c0dba575c7a92ea255f9e9fc81484e" + + "3929afeaa1a6f459d600114fbfd01b5de82dfa6f54f0f27af41d5a66" + + "ed39ac1a87d614fa12808f9adf" + legacyAnchorPkScript = "512021b15bddf2d991b8791ec7c2105fa69be61008d78" + + "b67d261451290d7a44dce5f" +) + +// scalarKey derives a deterministic test key from a one-byte scalar. +func scalarKey(t *testing.T, scalar byte) (*btcec.PrivateKey, + *btcec.PublicKey) { + + t.Helper() + keyBytes := make([]byte, 32) + keyBytes[31] = scalar + privateKey, publicKey := btcec.PrivKeyFromBytes(keyBytes) + + return privateKey, publicKey +} + +// TestNewHtlcSwapKitLegacyContract proves the moved deposit adapter retains +// the exact contract used by the existing valid asset deposit flow. +func TestNewHtlcSwapKitLegacyContract(t *testing.T) { + _, funderKey := scalarKey(t, 1) + _, coSignerKey := scalarKey(t, 2) + var assetID asset.ID + var swapHash lntypes.Hash + for idx := range assetID { + assetID[idx] = byte(idx) + swapHash[idx] = byte(idx) + } + + depositKit, err := NewKit( + funderKey, coSignerKey, keychain.KeyLocator{}, assetID, 4032, + &address.RegressionNetTap, + ) + require.NoError(t, err) + + swapKit, err := depositKit.newHtlcSwapKit(1000, swapHash, 144) + require.NoError(t, err) + require.Equal(t, htlc.LegacyDepositV0, swapKit.Policy()) + + successScript, err := swapKit.GetSuccessScript() + require.NoError(t, err) + require.Equal(t, legacySuccessScript, hex.EncodeToString(successScript)) + timeoutScript, err := swapKit.GetTimeoutScript() + require.NoError(t, err) + require.Equal(t, legacyTimeoutScript, hex.EncodeToString(timeoutScript)) + aggregateKey, err := swapKit.GetAggregateKey() + require.NoError(t, err) + require.Equal(t, legacyAggregateKey, + hex.EncodeToString(aggregateKey.SerializeCompressed())) + sibling, err := swapKit.GetSiblingPreimage() + require.NoError(t, err) + siblingBytes, _, err := commitment.MaybeEncodeTapscriptPreimage(&sibling) + require.NoError(t, err) + require.Equal(t, legacySibling, hex.EncodeToString(siblingBytes)) + + assetRoot := make([]byte, chainhash.HashSize) + for idx := range assetRoot { + assetRoot[idx] = byte(0xa0 + idx) + } + pkScript, err := swapKit.GetPkScriptFromRoot(assetRoot) + require.NoError(t, err) + require.Equal(t, legacyAnchorPkScript, hex.EncodeToString(pkScript)) + + packet, err := swapKit.CreateHtlcVpkt() + require.NoError(t, err) + require.Equal(t, &address.RegressionNetTap, packet.ChainParams) + require.Len(t, packet.Outputs, 2) + require.Equal(t, uint32(0), packet.Outputs[0].AnchorOutputIndex) + require.Equal(t, uint32(1), packet.Outputs[1].AnchorOutputIndex) + require.Equal(t, uint64(1000), packet.Outputs[1].Amount) + require.True(t, packet.Outputs[0].Interactive) + require.True(t, packet.Outputs[1].Interactive) +} + +// TestNewKitValidation verifies invalid or mutable constructor inputs cannot +// create or alter a deposit contract. +func TestNewKitValidation(t *testing.T) { + _, funderKey := scalarKey(t, 1) + _, coSignerKey := scalarKey(t, 2) + assetID := asset.ID{1} + params := cloneAddressParams(address.RegressionNetTap) + emptyParams := cloneAddressParams(address.ChainParams{}) + require.Nil(t, emptyParams.Params) + + tests := []struct { + name string + funder *btcec.PublicKey + coSigner *btcec.PublicKey + assetID asset.ID + expiry uint32 + chainParams *address.ChainParams + }{ + { + name: "nil funder", coSigner: coSignerKey, + assetID: assetID, expiry: 1, chainParams: params, + }, + { + name: "nil co-signer", funder: funderKey, + assetID: assetID, expiry: 1, chainParams: params, + }, + { + name: "same keys", funder: funderKey, coSigner: funderKey, + assetID: assetID, expiry: 1, chainParams: params, + }, + { + name: "zero asset ID", funder: funderKey, + coSigner: coSignerKey, expiry: 1, chainParams: params, + }, + { + name: "zero expiry", funder: funderKey, + coSigner: coSignerKey, assetID: assetID, + chainParams: params, + }, + { + name: "nil chain parameters", funder: funderKey, + coSigner: coSignerKey, assetID: assetID, expiry: 1, + }, + } + + for _, testCase := range tests { + t.Run(testCase.name, func(t *testing.T) { + _, err := NewKit( + testCase.funder, testCase.coSigner, + keychain.KeyLocator{}, testCase.assetID, + testCase.expiry, testCase.chainParams, + ) + require.Error(t, err) + }) + } + + kit, err := NewKit( + funderKey, coSignerKey, keychain.KeyLocator{}, assetID, 144, + params, + ) + require.NoError(t, err) + params.TapHRP = "mutated" + params.Params.Name = "mutated" + swapKit, err := kit.newHtlcSwapKit(1, lntypes.Hash{1}, 2) + require.NoError(t, err) + require.Equal(t, address.RegressionNetTap.TapHRP, + swapKit.AddressParams().TapHRP) + require.Equal(t, address.RegressionNetTap.Name, + swapKit.AddressParams().Name) + + var nilKit *Kit + _, err = nilKit.NewAddr(t.Context(), nil, 1) + require.Error(t, err) +} + +type localSigner struct { + lndclient.SignerClient + + privateKey *btcec.PrivateKey + expectedInput int + calls int + invalidSet bool +} + +func (s *localSigner) SignOutputRaw(_ context.Context, tx *wire.MsgTx, + descriptors []*lndclient.SignDescriptor, + prevOutputs []*wire.TxOut) ([][]byte, error) { + + s.calls++ + if s.invalidSet { + return nil, nil + } + if len(descriptors) != 1 { + return nil, fmt.Errorf("expected one sign descriptor") + } + if len(prevOutputs) != len(tx.TxIn) { + return nil, fmt.Errorf("expected all previous outputs") + } + descriptor := descriptors[0] + if descriptor.InputIndex != s.expectedInput { + return nil, fmt.Errorf("unexpected input index: %d", + descriptor.InputIndex) + } + if descriptor.SignMethod != input.TaprootScriptSpendSignMethod { + return nil, fmt.Errorf("unexpected signing method") + } + + prevOutFetcher := txscript.NewMultiPrevOutFetcher(nil) + for idx, txIn := range tx.TxIn { + prevOutFetcher.AddPrevOut( + txIn.PreviousOutPoint, prevOutputs[idx], + ) + } + sigHashes := txscript.NewTxSigHashes(tx, prevOutFetcher) + tapLeaf := txscript.NewBaseTapLeaf(descriptor.WitnessScript) + signature, err := txscript.RawTxInTapscriptSignature( + tx, sigHashes, descriptor.InputIndex, + descriptor.Output.Value, descriptor.Output.PkScript, tapLeaf, + txscript.SigHashDefault, s.privateKey, + ) + if err != nil { + return nil, err + } + + return [][]byte{signature}, nil +} + +type witnessFixture struct { + kit *Kit + proof *proof.Proof + packet *psbt.Packet + prevOutputs []*wire.TxOut + funderKey *btcec.PrivateKey + assetInIndex int +} + +// newWitnessFixture creates a proof-bound deposit and multi-input sweep packet. +func newWitnessFixture(t *testing.T) *witnessFixture { + t.Helper() + + funderKey, funderPubKey := scalarKey(t, 1) + _, coSignerPubKey := scalarKey(t, 2) + genesis := asset.Genesis{ + FirstPrevOut: wire.OutPoint{ + Hash: chainhash.Hash{0x31}, Index: 3, + }, + Tag: "asset deposit witness test", OutputIndex: 0, + Type: asset.Normal, + } + kit, err := NewKit( + funderPubKey, coSignerPubKey, keychain.KeyLocator{Family: 7, + Index: 9}, genesis.ID(), 144, &address.RegressionNetTap, + ) + require.NoError(t, err) + opTrueScriptKey, _, _, _, err := htlc.CreateOpTrueLeaf() + require.NoError(t, err) + depositAsset, err := asset.New( + genesis, 1000, 0, 0, + asset.NewScriptKey(opTrueScriptKey.PubKey), nil, + asset.WithAssetVersion(asset.V1), + ) + require.NoError(t, err) + commitmentVersion := commitment.TapCommitmentV2 + tapCommitment, err := commitment.FromAssets( + &commitmentVersion, depositAsset, + ) + require.NoError(t, err) + _, commitmentProof, err := tapCommitment.Proof( + depositAsset.TapCommitmentKey(), + depositAsset.AssetCommitmentKey(), + ) + require.NoError(t, err) + sibling, err := kit.timeoutPathSibling() + require.NoError(t, err) + siblingHash, err := sibling.TapHash() + require.NoError(t, err) + anchorPkScript, err := tapscript.PayToAddrScript( + *kit.muSig2Key.PreTweakedKey, siblingHash, *tapCommitment, + ) + require.NoError(t, err) + + const anchorValue = int64(50_000) + anchorTx := wire.NewMsgTx(2) + anchorTx.AddTxIn(&wire.TxIn{PreviousOutPoint: genesis.FirstPrevOut}) + anchorTx.AddTxOut(&wire.TxOut{ + Value: 1000, PkScript: []byte{txscript.OP_TRUE}, + }) + anchorTx.AddTxOut(&wire.TxOut{ + Value: anchorValue, PkScript: anchorPkScript, + }) + assetProof := &proof.Proof{ + AnchorTx: *anchorTx, + Asset: *depositAsset, + InclusionProof: proof.TaprootProof{ + OutputIndex: 1, + InternalKey: kit.muSig2Key.PreTweakedKey, + CommitmentProof: &proof.CommitmentProof{ + Proof: *commitmentProof, + TapSiblingPreimage: sibling, + }, + }, + } + _, err = assetProof.VerifyProofs() + require.NoError(t, err) + + feeOutpoint := wire.OutPoint{Hash: chainhash.Hash{0x42}, Index: 5} + assetInIndex := 1 + sweepTx := wire.NewMsgTx(2) + sweepTx.AddTxIn(&wire.TxIn{ + PreviousOutPoint: feeOutpoint, + Sequence: wire.MaxTxInSequenceNum, + }) + sweepTx.AddTxIn(&wire.TxIn{ + PreviousOutPoint: assetProof.OutPoint(), + Sequence: wire.MaxTxInSequenceNum, + }) + sweepTx.AddTxOut(&wire.TxOut{ + Value: anchorValue - 2000, PkScript: []byte{txscript.OP_TRUE}, + }) + packet, err := psbt.NewFromUnsignedTx(sweepTx) + require.NoError(t, err) + prevOutputs := []*wire.TxOut{ + {Value: 3000, PkScript: []byte{txscript.OP_TRUE}}, + {Value: anchorValue, PkScript: anchorPkScript}, + } + for idx := range prevOutputs { + packet.Inputs[idx].WitnessUtxo = prevOutputs[idx] + } + + return &witnessFixture{ + kit: kit, proof: assetProof, packet: packet, + prevOutputs: prevOutputs, funderKey: funderKey, + assetInIndex: assetInIndex, + } +} + +// TestCreateTimeoutWitness verifies the refund signature and witness bind to +// the proof-selected input rather than an assumed position. +func TestCreateTimeoutWitness(t *testing.T) { + fixture := newWitnessFixture(t) + signer := &localSigner{ + privateKey: fixture.funderKey, expectedInput: fixture.assetInIndex, + } + spend, err := fixture.kit.CreateTimeoutWitness( + t.Context(), signer, fixture.proof, fixture.packet, + ) + require.NoError(t, err) + require.Equal(t, uint32(fixture.assetInIndex), spend.InputIndex) + require.Equal(t, fixture.kit.csvExpiry, + fixture.packet.UnsignedTx.TxIn[fixture.assetInIndex].Sequence) + require.Len(t, spend.Witness, 3) + require.Equal(t, 1, signer.calls) + + tx := fixture.packet.UnsignedTx + tx.TxIn[fixture.assetInIndex].Witness = spend.Witness + prevOutFetcher := txscript.NewMultiPrevOutFetcher(nil) + for idx, txIn := range tx.TxIn { + prevOutFetcher.AddPrevOut( + txIn.PreviousOutPoint, fixture.prevOutputs[idx], + ) + } + sigHashes := txscript.NewTxSigHashes(tx, prevOutFetcher) + engine, err := txscript.NewEngine( + fixture.prevOutputs[fixture.assetInIndex].PkScript, tx, + fixture.assetInIndex, txscript.StandardVerifyFlags, nil, + sigHashes, fixture.prevOutputs[fixture.assetInIndex].Value, + prevOutFetcher, + ) + require.NoError(t, err) + require.NoError(t, engine.Execute()) +} + +// TestCreateTimeoutWitnessRejectsInvalidInputs covers the payment boundary +// checks that the legacy server helper previously omitted. +func TestCreateTimeoutWitnessRejectsInvalidInputs(t *testing.T) { + tests := []struct { + name string + mutate func(*witnessFixture, *localSigner) + }{ + { + name: "missing proof input", + mutate: func(f *witnessFixture, _ *localSigner) { + f.packet.UnsignedTx.TxIn[1].PreviousOutPoint.Index++ + }, + }, + { + name: "duplicate proof input", + mutate: func(f *witnessFixture, _ *localSigner) { + inputCopy := *f.packet.UnsignedTx.TxIn[1] + f.packet.UnsignedTx.TxIn = append( + f.packet.UnsignedTx.TxIn, &inputCopy, + ) + f.packet.Inputs = append( + f.packet.Inputs, + psbt.PInput{WitnessUtxo: f.prevOutputs[1]}, + ) + }, + }, + { + name: "missing fee prevout", + mutate: func(f *witnessFixture, _ *localSigner) { + f.packet.Inputs[0].WitnessUtxo = nil + }, + }, + { + name: "mismatched anchor value", + mutate: func(f *witnessFixture, _ *localSigner) { + f.packet.Inputs[1].WitnessUtxo.Value++ + }, + }, + { + name: "invalid signature set", + mutate: func(_ *witnessFixture, signer *localSigner) { + signer.invalidSet = true + }, + }, + { + name: "wrong signing key", + mutate: func(_ *witnessFixture, signer *localSigner) { + signer.privateKey, _ = scalarKey(t, 3) + }, + }, + } + + for _, testCase := range tests { + t.Run(testCase.name, func(t *testing.T) { + fixture := newWitnessFixture(t) + signer := &localSigner{ + privateKey: fixture.funderKey, + expectedInput: fixture.assetInIndex, + } + testCase.mutate(fixture, signer) + _, err := fixture.kit.CreateTimeoutWitness( + t.Context(), signer, fixture.proof, + fixture.packet, + ) + require.Error(t, err) + require.Equal( + t, uint32(wire.MaxTxInSequenceNum), + fixture.packet.UnsignedTx. + TxIn[fixture.assetInIndex].Sequence, + ) + }) + } + + fixture := newWitnessFixture(t) + _, err := fixture.kit.CreateTimeoutWitness( + t.Context(), nil, fixture.proof, fixture.packet, + ) + require.Error(t, err) + _, err = fixture.kit.CreateTimeoutWitness( + t.Context(), &localSigner{}, nil, fixture.packet, + ) + require.Error(t, err) +} diff --git a/assets/tapkit.go b/assets/tapkit.go new file mode 100644 index 000000000..a503db7a8 --- /dev/null +++ b/assets/tapkit.go @@ -0,0 +1,146 @@ +package assets + +import ( + "context" + "fmt" + "math" + + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/btcsuite/btcd/btcutil/psbt" + "github.com/btcsuite/btcd/wire" + "github.com/lightninglabs/loop/assets/htlc" + "github.com/lightninglabs/taproot-assets/address" + "github.com/lightninglabs/taproot-assets/asset" + "github.com/lightninglabs/taproot-assets/proof" + "github.com/lightninglabs/taproot-assets/tappsbt" + "github.com/lightninglabs/taproot-assets/tapsend" +) + +// CreateOpTrueSweepVpkt creates a virtual packet that spends proof-bound +// OP_TRUE assets to the given address. +func CreateOpTrueSweepVpkt(ctx context.Context, proofs []*proof.Proof, + addr *address.Tap) (*tappsbt.VPacket, error) { + + if len(proofs) == 0 { + return nil, fmt.Errorf("at least one asset proof is required") + } + if addr == nil { + return nil, fmt.Errorf("sweep address is required") + } + if addr.ChainParams == nil || addr.ChainParams.Params == nil || + addr.ChainParams.TapHRP == "" { + + return nil, fmt.Errorf("sweep address parameters are incomplete") + } + if addr.Amount == 0 { + return nil, fmt.Errorf("sweep address amount must be positive") + } + if addr.AssetID == asset.ZeroID { + return nil, fmt.Errorf("group sweep addresses are unsupported") + } + opTrueScriptKey, _, _, controlBlock, err := htlc.CreateOpTrueLeaf() + if err != nil { + return nil, err + } + + total := uint64(0) + for idx, assetProof := range proofs { + if assetProof == nil { + return nil, fmt.Errorf("asset proof %d is nil", idx) + } + if _, err := assetProof.VerifyProofs(); err != nil { + return nil, fmt.Errorf("invalid asset proof %d: %w", idx, err) + } + proofID := assetProof.Asset.Genesis.ID() + if proofID != addr.AssetID { + return nil, fmt.Errorf( + "asset proof %d does not match sweep address", idx, + ) + } + proofScriptKey := assetProof.Asset.ScriptKey.PubKey + if proofScriptKey == nil || + !proofScriptKey.IsEqual(opTrueScriptKey.PubKey) { + + return nil, fmt.Errorf( + "asset proof %d is not an OP_TRUE asset", idx, + ) + } + if math.MaxUint64-total < assetProof.Asset.Amount { + return nil, fmt.Errorf("asset proof amount overflow") + } + total += assetProof.Asset.Amount + } + if total != addr.Amount { + return nil, fmt.Errorf("total proof amount does not match address") + } + + sweepVpkt, err := tappsbt.FromProofs( + proofs, addr.ChainParams, tappsbt.V1, + ) + if err != nil { + return nil, err + } + if len(sweepVpkt.Inputs) != len(proofs) { + return nil, fmt.Errorf("proof inputs were not preserved") + } + for idx, input := range sweepVpkt.Inputs { + if input == nil || input.Anchor.InternalKey == nil { + return nil, fmt.Errorf("asset input %d is incomplete", idx) + } + inputKey := input.Anchor.InternalKey + input.Anchor.Bip32Derivation = []*psbt.Bip32Derivation{ + {PubKey: inputKey.SerializeCompressed()}, + } + input.Anchor.TrBip32Derivation = + []*psbt.TaprootBip32Derivation{ + { + XOnlyPubKey: schnorr.SerializePubKey( + inputKey, + ), + }, + } + } + + sweepVpkt.Outputs = append(sweepVpkt.Outputs, &tappsbt.VOutput{ + AssetVersion: addr.AssetVersion, + Amount: addr.Amount, + Interactive: true, + AnchorOutputIndex: 0, + ScriptKey: asset.NewScriptKey(&addr.ScriptKey), + AnchorOutputInternalKey: &addr.InternalKey, + AnchorOutputTapscriptSibling: addr.TapscriptSibling, + ProofDeliveryAddress: &addr.ProofCourierAddr, + }) + if err := tapsend.PrepareOutputAssets(ctx, sweepVpkt); err != nil { + return nil, err + } + + controlBlockBytes, err := controlBlock.ToBytes() + if err != nil { + return nil, err + } + opTrueScript, err := htlc.GetOpTrueScript() + if err != nil { + return nil, err + } + + if len(sweepVpkt.Outputs) == 0 || sweepVpkt.Outputs[0] == nil || + sweepVpkt.Outputs[0].Asset == nil || + len(sweepVpkt.Outputs[0].Asset.PrevWitnesses) == 0 { + + return nil, fmt.Errorf("prepared asset output is incomplete") + } + firstPrevWitness := &sweepVpkt.Outputs[0].Asset.PrevWitnesses[0] + if sweepVpkt.Outputs[0].Asset.HasSplitCommitmentWitness() { + rootAsset := firstPrevWitness.SplitCommitment.RootAsset + if len(rootAsset.PrevWitnesses) == 0 { + return nil, fmt.Errorf("split root asset witness is incomplete") + } + firstPrevWitness = &rootAsset.PrevWitnesses[0] + } + firstPrevWitness.TxWitness = wire.TxWitness{ + opTrueScript, controlBlockBytes, + } + + return sweepVpkt, nil +} diff --git a/assets/tapkit_test.go b/assets/tapkit_test.go new file mode 100644 index 000000000..3fa3c3ae1 --- /dev/null +++ b/assets/tapkit_test.go @@ -0,0 +1,107 @@ +package assets + +import ( + "testing" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" + "github.com/lightninglabs/taproot-assets/address" + "github.com/lightninglabs/taproot-assets/asset" + "github.com/lightninglabs/taproot-assets/commitment" + "github.com/lightninglabs/taproot-assets/proof" + "github.com/lightninglabs/taproot-assets/tapscript" + "github.com/stretchr/testify/require" +) + +func validNonOpTrueProof(t *testing.T) (*proof.Proof, *address.Tap) { + t.Helper() + + _, scriptKey := btcec.PrivKeyFromBytes([]byte{1}) + _, internalKey := btcec.PrivKeyFromBytes([]byte{2}) + genesis := asset.Genesis{ + FirstPrevOut: wire.OutPoint{ + Hash: chainhash.Hash{1}, Index: 1, + }, + Tag: "non OP_TRUE asset", OutputIndex: 0, Type: asset.Normal, + } + proofAsset, err := asset.New( + genesis, 1, 0, 0, asset.NewScriptKey(scriptKey), nil, + asset.WithAssetVersion(asset.V1), + ) + require.NoError(t, err) + version := commitment.TapCommitmentV2 + tapCommitment, err := commitment.FromAssets(&version, proofAsset) + require.NoError(t, err) + _, commitmentProof, err := tapCommitment.Proof( + proofAsset.TapCommitmentKey(), proofAsset.AssetCommitmentKey(), + ) + require.NoError(t, err) + anchorScript, err := tapscript.PayToAddrScript( + *internalKey, nil, *tapCommitment, + ) + require.NoError(t, err) + anchorTx := wire.NewMsgTx(2) + anchorTx.AddTxIn(&wire.TxIn{ + PreviousOutPoint: genesis.FirstPrevOut, + }) + anchorTx.AddTxOut(&wire.TxOut{ + Value: 1_000, PkScript: anchorScript, + }) + assetProof := &proof.Proof{ + AnchorTx: *anchorTx, Asset: *proofAsset, + InclusionProof: proof.TaprootProof{ + OutputIndex: 0, InternalKey: internalKey, + CommitmentProof: &proof.CommitmentProof{ + Proof: *commitmentProof, + }, + }, + } + _, err = assetProof.VerifyProofs() + require.NoError(t, err) + + return assetProof, &address.Tap{ + AssetID: genesis.ID(), Amount: 1, + ChainParams: &address.RegressionNetTap, + } +} + +// TestCreateOpTrueSweepVpktValidation verifies malformed proof and destination +// inputs fail before virtual-packet construction can index into them. +func TestCreateOpTrueSweepVpktValidation(t *testing.T) { + _, err := CreateOpTrueSweepVpkt(t.Context(), nil, nil) + require.Error(t, err) + + proofs := []*proof.Proof{{}} + _, err = CreateOpTrueSweepVpkt(t.Context(), proofs, nil) + require.Error(t, err) + + addr := &address.Tap{Amount: 1, AssetID: asset.ID{1}} + _, err = CreateOpTrueSweepVpkt(t.Context(), proofs, addr) + require.Error(t, err) + + addr.ChainParams = &address.RegressionNetTap + addr.Amount = 0 + _, err = CreateOpTrueSweepVpkt(t.Context(), proofs, addr) + require.Error(t, err) + + addr.Amount = 1 + addr.AssetID = asset.ZeroID + _, err = CreateOpTrueSweepVpkt(t.Context(), proofs, addr) + require.Error(t, err) + + addr.AssetID = asset.ID{1} + _, err = CreateOpTrueSweepVpkt( + t.Context(), []*proof.Proof{nil}, addr, + ) + require.Error(t, err) + + _, err = CreateOpTrueSweepVpkt(t.Context(), proofs, addr) + require.Error(t, err) + + nonOpTrueProof, matchingAddr := validNonOpTrueProof(t) + _, err = CreateOpTrueSweepVpkt( + t.Context(), []*proof.Proof{nonOpTrueProof}, matchingAddr, + ) + require.ErrorContains(t, err, "is not an OP_TRUE asset") +} diff --git a/go.sum b/go.sum index c7c2f6e28..06ea110a9 100644 --- a/go.sum +++ b/go.sum @@ -952,6 +952,10 @@ github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aN github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0-rc.0 h1:mdLirNAJBxnGgyB6pjZLcs6ue/6eZGBui6gXspfq4ks= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0-rc.0/go.mod h1:kdXbOySqcQeTxiqglW7aahTmWZy3Pgi6SYL36yvKeyA= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.3 h1:o95KDiV/b1xdkumY5YbLR0/n2+wBxUpgf3HgfKgTyLI= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.3/go.mod h1:hTxjzRcX49ogbTGVJ1sM5mz5s+SSgiGIyL3jjPxl32E= 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= From 0077d3a0d4bfc11027e85c58f5b03de3bb415c81 Mon Sep 17 00:00:00 2001 From: Slyghtning Date: Thu, 3 Sep 2026 10:43:14 +0200 Subject: [PATCH 3/5] assets: Harden shared asset validation Reject non-block deposit expiries. This prevents BIP68 flags from changing or disabling the intended block delay. Canonicalize OP_TRUE keys, populate and validate every virtual input witness, and reject unsupported addresses and duplicate anchor inputs. --- assets/deposit/kit.go | 3 + assets/deposit/kit_test.go | 8 +- assets/tapkit.go | 121 ++++++++++++++++---- assets/tapkit_test.go | 135 +++++++++++++++++++++++ docs/release-notes/release-notes-next.md | 3 + 5 files changed, 245 insertions(+), 25 deletions(-) diff --git a/assets/deposit/kit.go b/assets/deposit/kit.go index c4ea54cac..28704819d 100644 --- a/assets/deposit/kit.go +++ b/assets/deposit/kit.go @@ -69,6 +69,9 @@ func NewKit(funderKey, coSignerKey *btcec.PublicKey, if csvExpiry == 0 { return nil, fmt.Errorf("CSV expiry must be positive") } + if csvExpiry > wire.SequenceLockTimeMask { + return nil, fmt.Errorf("CSV expiry exceeds block-based BIP68 range") + } if chainParams == nil || chainParams.Params == nil || chainParams.TapHRP == "" { diff --git a/assets/deposit/kit_test.go b/assets/deposit/kit_test.go index 31e27529b..1d0f65e7b 100644 --- a/assets/deposit/kit_test.go +++ b/assets/deposit/kit_test.go @@ -147,6 +147,12 @@ func TestNewKitValidation(t *testing.T) { coSigner: coSignerKey, assetID: assetID, chainParams: params, }, + { + name: "non-block expiry", funder: funderKey, + coSigner: coSignerKey, assetID: assetID, + expiry: wire.SequenceLockTimeMask + 1, + chainParams: params, + }, { name: "nil chain parameters", funder: funderKey, coSigner: coSignerKey, assetID: assetID, expiry: 1, @@ -446,7 +452,7 @@ func TestCreateTimeoutWitnessRejectsInvalidInputs(t *testing.T) { ) require.Error(t, err) require.Equal( - t, uint32(wire.MaxTxInSequenceNum), + t, wire.MaxTxInSequenceNum, fixture.packet.UnsignedTx. TxIn[fixture.assetInIndex].Sequence, ) diff --git a/assets/tapkit.go b/assets/tapkit.go index a503db7a8..dba907d5f 100644 --- a/assets/tapkit.go +++ b/assets/tapkit.go @@ -11,9 +11,11 @@ import ( "github.com/lightninglabs/loop/assets/htlc" "github.com/lightninglabs/taproot-assets/address" "github.com/lightninglabs/taproot-assets/asset" + "github.com/lightninglabs/taproot-assets/commitment" "github.com/lightninglabs/taproot-assets/proof" "github.com/lightninglabs/taproot-assets/tappsbt" "github.com/lightninglabs/taproot-assets/tapsend" + "github.com/lightninglabs/taproot-assets/vm" ) // CreateOpTrueSweepVpkt creates a virtual packet that spends proof-bound @@ -38,12 +40,25 @@ func CreateOpTrueSweepVpkt(ctx context.Context, proofs []*proof.Proof, if addr.AssetID == asset.ZeroID { return nil, fmt.Errorf("group sweep addresses are unsupported") } + if address.IsUnknownVersion(addr.Version) { + return nil, fmt.Errorf("unsupported sweep address version") + } + if addr.Version >= address.V2 { + return nil, fmt.Errorf("version 2 sweep addresses are unsupported") + } + if addr.AssetVersion != asset.V0 && addr.AssetVersion != asset.V1 { + return nil, fmt.Errorf("unsupported sweep asset version") + } opTrueScriptKey, _, _, controlBlock, err := htlc.CreateOpTrueLeaf() if err != nil { return nil, err } + opTrueScriptKey = asset.NewScriptKey(opTrueScriptKey.PubKey) - total := uint64(0) + var ( + total uint64 + seenOutpoints = make(map[wire.OutPoint]struct{}, len(proofs)) + ) for idx, assetProof := range proofs { if assetProof == nil { return nil, fmt.Errorf("asset proof %d is nil", idx) @@ -68,14 +83,32 @@ func CreateOpTrueSweepVpkt(ctx context.Context, proofs []*proof.Proof, if math.MaxUint64-total < assetProof.Asset.Amount { return nil, fmt.Errorf("asset proof amount overflow") } + outpoint := assetProof.OutPoint() + if _, ok := seenOutpoints[outpoint]; ok { + return nil, fmt.Errorf( + "asset proof %d duplicates an input outpoint", idx, + ) + } + seenOutpoints[outpoint] = struct{}{} total += assetProof.Asset.Amount } if total != addr.Amount { return nil, fmt.Errorf("total proof amount does not match address") } + // An address always describes a non-interactive transfer. Let the + // Taproot Assets address constructor choose both the virtual packet + // version and the split-root/recipient output layout so these semantics + // stay aligned with the address version. + addressVpkt, err := tappsbt.FromAddresses( + []*address.Tap{addr}, 1, + ) + if err != nil { + return nil, err + } + sweepVpkt, err := tappsbt.FromProofs( - proofs, addr.ChainParams, tappsbt.V1, + proofs, addr.ChainParams, addressVpkt.Version, ) if err != nil { return nil, err @@ -101,16 +134,16 @@ func CreateOpTrueSweepVpkt(ctx context.Context, proofs []*proof.Proof, } } - sweepVpkt.Outputs = append(sweepVpkt.Outputs, &tappsbt.VOutput{ - AssetVersion: addr.AssetVersion, - Amount: addr.Amount, - Interactive: true, - AnchorOutputIndex: 0, - ScriptKey: asset.NewScriptKey(&addr.ScriptKey), - AnchorOutputInternalKey: &addr.InternalKey, - AnchorOutputTapscriptSibling: addr.TapscriptSibling, - ProofDeliveryAddress: &addr.ProofCourierAddr, - }) + destinationScriptKey, err := addr.ScriptKeyForAssetID(addr.AssetID) + if err != nil { + return nil, fmt.Errorf("invalid sweep script key: %w", err) + } + recipientOutput, err := addressVpkt.FirstNonSplitRootOutput() + if err != nil { + return nil, err + } + recipientOutput.ScriptKey = asset.NewScriptKey(destinationScriptKey) + sweepVpkt.Outputs = addressVpkt.Outputs if err := tapsend.PrepareOutputAssets(ctx, sweepVpkt); err != nil { return nil, err } @@ -124,22 +157,62 @@ func CreateOpTrueSweepVpkt(ctx context.Context, proofs []*proof.Proof, return nil, err } - if len(sweepVpkt.Outputs) == 0 || sweepVpkt.Outputs[0] == nil || - sweepVpkt.Outputs[0].Asset == nil || - len(sweepVpkt.Outputs[0].Asset.PrevWitnesses) == 0 { + for outputIdx, output := range sweepVpkt.Outputs { + if output == nil || output.Asset == nil { + return nil, fmt.Errorf( + "prepared asset output %d is incomplete", outputIdx, + ) + } + + outputAssets := []*asset.Asset{output.Asset} + if output.SplitAsset != nil { + outputAssets = append(outputAssets, output.SplitAsset) + } + for _, outputAsset := range outputAssets { + prevWitnesses := outputAsset.Witnesses() + if len(prevWitnesses) != len(sweepVpkt.Inputs) { + return nil, fmt.Errorf( + "prepared asset output %d witnesses are "+ + "incomplete", outputIdx, + ) + } + for idx := range prevWitnesses { + prevWitnesses[idx].TxWitness = wire.TxWitness{ + append([]byte(nil), opTrueScript...), + append([]byte(nil), controlBlockBytes...), + } + } + } + } - return nil, fmt.Errorf("prepared asset output is incomplete") + prevAssets := make(commitment.InputSet, len(sweepVpkt.Inputs)) + for _, input := range sweepVpkt.Inputs { + prevAssets[input.PrevID] = input.Asset() + } + splitRootOutput, err := sweepVpkt.SplitRootOutput() + if err != nil { + return nil, err } - firstPrevWitness := &sweepVpkt.Outputs[0].Asset.PrevWitnesses[0] - if sweepVpkt.Outputs[0].Asset.HasSplitCommitmentWitness() { - rootAsset := firstPrevWitness.SplitCommitment.RootAsset - if len(rootAsset.PrevWitnesses) == 0 { - return nil, fmt.Errorf("split root asset witness is incomplete") + splitAssets := make([]*commitment.SplitAsset, len(sweepVpkt.Outputs)) + for idx, output := range sweepVpkt.Outputs { + splitAsset := output.Asset + if output.Type.IsSplitRoot() { + splitAsset = output.SplitAsset + } + if splitAsset == nil { + return nil, fmt.Errorf( + "prepared split asset output %d is incomplete", idx, + ) + } + splitAssets[idx] = &commitment.SplitAsset{ + Asset: *splitAsset, + OutputIndex: output.AnchorOutputIndex, } - firstPrevWitness = &rootAsset.PrevWitnesses[0] } - firstPrevWitness.TxWitness = wire.TxWitness{ - opTrueScript, controlBlockBytes, + if err := vm.ValidateWitnesses( + splitRootOutput.Asset, splitAssets, prevAssets, + ); err != nil { + return nil, fmt.Errorf("invalid OP_TRUE asset witnesses: %w", err) } return sweepVpkt, nil diff --git a/assets/tapkit_test.go b/assets/tapkit_test.go index 3fa3c3ae1..c07fca83d 100644 --- a/assets/tapkit_test.go +++ b/assets/tapkit_test.go @@ -6,14 +6,18 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" + "github.com/lightninglabs/loop/assets/htlc" "github.com/lightninglabs/taproot-assets/address" "github.com/lightninglabs/taproot-assets/asset" "github.com/lightninglabs/taproot-assets/commitment" "github.com/lightninglabs/taproot-assets/proof" + "github.com/lightninglabs/taproot-assets/tappsbt" "github.com/lightninglabs/taproot-assets/tapscript" "github.com/stretchr/testify/require" ) +// validNonOpTrueProof creates a structurally valid proof whose asset cannot be +// spent through the OP_TRUE sweep path. func validNonOpTrueProof(t *testing.T) (*proof.Proof, *address.Tap) { t.Helper() @@ -66,6 +70,56 @@ func validNonOpTrueProof(t *testing.T) (*proof.Proof, *address.Tap) { } } +// validOpTrueProof creates a structurally valid OP_TRUE proof with the given +// asset identity, amount, and deterministic anchor key. +func validOpTrueProof(t *testing.T, genesis asset.Genesis, + amount uint64, keyScalar byte) *proof.Proof { + + t.Helper() + + _, internalKey := btcec.PrivKeyFromBytes([]byte{keyScalar}) + opTrueScriptKey, _, _, _, err := htlc.CreateOpTrueLeaf() + require.NoError(t, err) + proofAsset, err := asset.New( + genesis, amount, 0, 0, + asset.NewScriptKey(opTrueScriptKey.PubKey), nil, + asset.WithAssetVersion(asset.V1), + ) + require.NoError(t, err) + version := commitment.TapCommitmentV2 + tapCommitment, err := commitment.FromAssets(&version, proofAsset) + require.NoError(t, err) + _, commitmentProof, err := tapCommitment.Proof( + proofAsset.TapCommitmentKey(), + proofAsset.AssetCommitmentKey(), + ) + require.NoError(t, err) + anchorScript, err := tapscript.PayToAddrScript( + *internalKey, nil, *tapCommitment, + ) + require.NoError(t, err) + anchorTx := wire.NewMsgTx(2) + anchorTx.AddTxIn(&wire.TxIn{ + PreviousOutPoint: genesis.FirstPrevOut, + }) + anchorTx.AddTxOut(&wire.TxOut{ + Value: 1_000, PkScript: anchorScript, + }) + assetProof := &proof.Proof{ + AnchorTx: *anchorTx, Asset: *proofAsset, + InclusionProof: proof.TaprootProof{ + OutputIndex: 0, InternalKey: internalKey, + CommitmentProof: &proof.CommitmentProof{ + Proof: *commitmentProof, + }, + }, + } + _, err = assetProof.VerifyProofs() + require.NoError(t, err) + + return assetProof +} + // TestCreateOpTrueSweepVpktValidation verifies malformed proof and destination // inputs fail before virtual-packet construction can index into them. func TestCreateOpTrueSweepVpktValidation(t *testing.T) { @@ -104,4 +158,85 @@ func TestCreateOpTrueSweepVpktValidation(t *testing.T) { t.Context(), []*proof.Proof{nonOpTrueProof}, matchingAddr, ) require.ErrorContains(t, err, "is not an OP_TRUE asset") + + matchingAddr.Version = address.V2 + _, err = CreateOpTrueSweepVpkt( + t.Context(), []*proof.Proof{nonOpTrueProof}, matchingAddr, + ) + require.ErrorContains(t, err, "version 2") +} + +// TestCreateOpTrueSweepVpktMultipleInputs verifies every asset input receives +// its OP_TRUE virtual witness and duplicate anchor inputs are rejected. +func TestCreateOpTrueSweepVpktMultipleInputs(t *testing.T) { + genesis := asset.Genesis{ + FirstPrevOut: wire.OutPoint{ + Hash: chainhash.Hash{9}, Index: 1, + }, + Tag: "multi-input OP_TRUE asset", OutputIndex: 0, + Type: asset.Normal, + } + proofs := []*proof.Proof{ + validOpTrueProof(t, genesis, 2, 11), + validOpTrueProof(t, genesis, 3, 12), + } + _, destinationScriptKey := btcec.PrivKeyFromBytes([]byte{21}) + _, destinationInternalKey := btcec.PrivKeyFromBytes([]byte{22}) + addr := address.Tap{ + AssetVersion: asset.V1, + AssetID: genesis.ID(), + ScriptKey: *destinationScriptKey, + InternalKey: *destinationInternalKey, + Amount: 5, + ChainParams: &address.RegressionNetTap, + } + + tests := []struct { + name string + addressVersion address.Version + packetVersion tappsbt.VPacketVersion + }{ + { + name: "v0 address", addressVersion: address.V0, + packetVersion: tappsbt.V0, + }, + { + name: "v1 address", addressVersion: address.V1, + packetVersion: tappsbt.V1, + }, + } + for _, testCase := range tests { + t.Run(testCase.name, func(t *testing.T) { + addr := addr + addr.Version = testCase.addressVersion + packet, err := CreateOpTrueSweepVpkt( + t.Context(), proofs, &addr, + ) + require.NoError(t, err) + require.Equal(t, testCase.packetVersion, packet.Version) + require.Len(t, packet.Outputs, 2) + require.True(t, packet.Outputs[0].Type.IsSplitRoot()) + require.False(t, packet.Outputs[0].Interactive) + require.False(t, packet.Outputs[1].Interactive) + require.Equal(t, uint32(1), + packet.Outputs[1].AnchorOutputIndex) + require.Same(t, &addr, packet.Outputs[1].Address) + + for _, output := range packet.Outputs { + witnesses, err := output.PrevWitnesses() + require.NoError(t, err) + require.Len(t, witnesses, len(proofs)) + for _, witness := range witnesses { + require.Len(t, witness.TxWitness, 2) + } + } + }) + } + + addr.Version = address.V1 + addr.Amount = 4 + _, err := CreateOpTrueSweepVpkt( + t.Context(), []*proof.Proof{proofs[0], proofs[0]}, &addr, + ) + require.ErrorContains(t, err, "duplicates an input outpoint") } diff --git a/docs/release-notes/release-notes-next.md b/docs/release-notes/release-notes-next.md index 094d8ba28..f80313fdc 100644 --- a/docs/release-notes/release-notes-next.md +++ b/docs/release-notes/release-notes-next.md @@ -13,6 +13,9 @@ #### Bug Fixes +* Shared Taproot Asset sweep packets now preserve the destination address + version and use the required non-interactive split-root layout. + * Instant Out now attempts to cancel server-side swaps when client initialization fails, allowing locked reservations to be released without waiting for the server timeout. From c007b4a4c49c687d2b44a817818c5667357fad43 Mon Sep 17 00:00:00 2001 From: Slyghtning Date: Thu, 3 Sep 2026 12:17:27 +0200 Subject: [PATCH 4/5] assets: Restore deposit anchor root contract Return the complete anchor Merkle root from proof verification. This lets MuSig2 spends reproduce the output's Taproot tweak. --- assets/deposit/kit.go | 120 +++++++++++++++++++++++++++++++++++-- assets/deposit/kit_test.go | 87 +++++++++++++++++++++++++++ 2 files changed, 202 insertions(+), 5 deletions(-) diff --git a/assets/deposit/kit.go b/assets/deposit/kit.go index 28704819d..7c9383cf1 100644 --- a/assets/deposit/kit.go +++ b/assets/deposit/kit.go @@ -37,6 +37,15 @@ type AddressProofClient interface { ...grpc.CallOption) (*taprpc.ProofFile, error) } +// ProofVerifier is the narrow tapd boundary needed to verify a complete proof +// file against tapd's chain backend and asset transition verifier. +type ProofVerifier interface { + VerifyProof(context.Context, *taprpc.ProofFile, + ...grpc.CallOption) (*taprpc.VerifyProofResponse, error) +} + +var _ ProofVerifier = (taprpc.TaprootAssetsClient)(nil) + // Kit contains the immutable information needed to create and operate a // two-party MuSig2 asset deposit. type Kit struct { @@ -399,19 +408,120 @@ func (d *Kit) validateProof(depositProof *proof.Proof) ( return tapCommitment, nil } -// VerifyProof verifies the proof commitment and binds it to this deposit's -// asset, internal key, and timeout sibling. It returns the complete Taproot -// Asset commitment root. -func (d *Kit) VerifyProof(depositProof *proof.Proof) ([]byte, error) { +// anchorRootFromProofCommitment verifies the proof's commitment structure and +// returns the complete anchor Taproot Merkle root. +func (d *Kit) anchorRootFromProofCommitment(depositProof *proof.Proof) ( + []byte, error) { + tapCommitment, err := d.validateProof(depositProof) if err != nil { return nil, err } - root := tapCommitment.TapscriptRoot(nil) + sibling, err := d.timeoutPathSibling() + if err != nil { + return nil, err + } + siblingHash, err := sibling.TapHash() + if err != nil { + return nil, err + } + root := tapCommitment.TapscriptRoot(siblingHash) return append([]byte(nil), root[:]...), nil } +// AnchorRootFromProofCommitment verifies the proof's commitment structure, +// binds its asset ID, script key, internal key, timeout sibling, and exact +// amount to this deposit, then returns the complete anchor Taproot Merkle root. +// It does not verify the proof's chain inclusion, provenance, state transition, +// confirmation depth, or whether the anchor outpoint remains unspent. Use +// VerifyProofFile when a proof file has not already been fully verified. +func (d *Kit) AnchorRootFromProofCommitment(depositProof *proof.Proof, + expectedAmount uint64) ([]byte, error) { + + if d == nil { + return nil, fmt.Errorf("deposit kit is required") + } + if expectedAmount == 0 { + return nil, fmt.Errorf("expected deposit amount must be positive") + } + if depositProof == nil { + return nil, fmt.Errorf("deposit proof is required") + } + if depositProof.Asset.Amount != expectedAmount { + return nil, fmt.Errorf( + "deposit asset amount mismatch: expected %d, got %d", + expectedAmount, depositProof.Asset.Amount, + ) + } + + return d.anchorRootFromProofCommitment(depositProof) +} + +// VerifyProofFile asks tapd to fully verify a proof file, binds its terminal +// proof to the expected deposit outpoint and amount, and returns the complete +// anchor Taproot Merkle root. The caller must still enforce confirmation depth +// and verify that the anchor outpoint remains unspent. +func (d *Kit) VerifyProofFile(ctx context.Context, verifier ProofVerifier, + proofFile *taprpc.ProofFile, expectedOutpoint *wire.OutPoint, + expectedAmount uint64) ([]byte, error) { + + if d == nil { + return nil, fmt.Errorf("deposit kit is required") + } + if verifier == nil { + return nil, fmt.Errorf("proof verifier is required") + } + if proofFile == nil || len(proofFile.RawProofFile) == 0 { + return nil, fmt.Errorf("proof file is required") + } + if expectedOutpoint == nil { + return nil, fmt.Errorf("expected deposit outpoint is required") + } + if expectedAmount == 0 { + return nil, fmt.Errorf("expected deposit amount must be positive") + } + + proofFileCopy := &taprpc.ProofFile{ + RawProofFile: append([]byte(nil), proofFile.RawProofFile...), + GenesisPoint: proofFile.GenesisPoint, + } + verifyResponse, err := verifier.VerifyProof(ctx, proofFileCopy) + if err != nil { + return nil, fmt.Errorf("unable to verify deposit proof file: %w", err) + } + if verifyResponse == nil || !verifyResponse.Valid { + return nil, fmt.Errorf("invalid deposit proof file") + } + + decodedFile, err := proof.DecodeFile(proofFile.RawProofFile) + if err != nil { + return nil, fmt.Errorf("unable to decode deposit proof file: %w", err) + } + depositProof, err := decodedFile.LastProof() + if err != nil { + return nil, fmt.Errorf("unable to read terminal deposit proof: %w", err) + } + if depositProof.OutPoint() != *expectedOutpoint { + return nil, fmt.Errorf( + "deposit proof outpoint mismatch: expected %v, got %v", + *expectedOutpoint, depositProof.OutPoint(), + ) + } + + return d.AnchorRootFromProofCommitment(depositProof, expectedAmount) +} + +// VerifyProof verifies only the proof commitment and binds it to this +// deposit's asset, internal key, and timeout sibling. It does not validate the +// expected amount, provenance, chain inclusion, or unspent status. +// +// Deprecated: use VerifyProofFile for untrusted proof files, or +// AnchorRootFromProofCommitment for proofs that were already fully verified. +func (d *Kit) VerifyProof(depositProof *proof.Proof) ([]byte, error) { + return d.anchorRootFromProofCommitment(depositProof) +} + // GenTimeoutBtcControlBlock creates the deposit timeout-path control block. func (d *Kit) GenTimeoutBtcControlBlock(taprootAssetRoot []byte) ( *txscript.ControlBlock, error) { diff --git a/assets/deposit/kit_test.go b/assets/deposit/kit_test.go index 1d0f65e7b..7b6e344c9 100644 --- a/assets/deposit/kit_test.go +++ b/assets/deposit/kit_test.go @@ -1,6 +1,7 @@ package deposit import ( + "bytes" "context" "encoding/hex" "fmt" @@ -17,11 +18,13 @@ import ( "github.com/lightninglabs/taproot-assets/asset" "github.com/lightninglabs/taproot-assets/commitment" "github.com/lightninglabs/taproot-assets/proof" + "github.com/lightninglabs/taproot-assets/taprpc" "github.com/lightninglabs/taproot-assets/tapscript" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lntypes" "github.com/stretchr/testify/require" + "google.golang.org/grpc" ) const ( @@ -198,6 +201,23 @@ type localSigner struct { invalidSet bool } +type proofVerifierMock struct { + response *taprpc.VerifyProofResponse + err error + calls int +} + +// VerifyProof records a proof verification request and returns the configured +// tapd response. +func (m *proofVerifierMock) VerifyProof(_ context.Context, + _ *taprpc.ProofFile, _ ...grpc.CallOption) (*taprpc.VerifyProofResponse, + error) { + + m.calls++ + + return m.response, m.err +} + func (s *localSigner) SignOutputRaw(_ context.Context, tx *wire.MsgTx, descriptors []*lndclient.SignDescriptor, prevOutputs []*wire.TxOut) ([][]byte, error) { @@ -350,6 +370,73 @@ func newWitnessFixture(t *testing.T) *witnessFixture { } } +// TestVerifyProofReturnsAnchorRoot verifies the proof result can be used as +// the Taproot tweak for the deposit's cooperative MuSig2 key-path spend. +func TestVerifyProofReturnsAnchorRoot(t *testing.T) { + fixture := newWitnessFixture(t) + + root, err := fixture.kit.VerifyProof(fixture.proof) + require.NoError(t, err) + require.Len(t, root, chainhash.HashSize) + boundRoot, err := fixture.kit.AnchorRootFromProofCommitment( + fixture.proof, fixture.proof.Asset.Amount, + ) + require.NoError(t, err) + require.Equal(t, root, boundRoot) + + _, err = fixture.kit.AnchorRootFromProofCommitment( + fixture.proof, fixture.proof.Asset.Amount-1, + ) + require.ErrorContains(t, err, "deposit asset amount mismatch") + + outputKey := txscript.ComputeTaprootOutputKey( + fixture.kit.muSig2Key.PreTweakedKey, root, + ) + pkScript, err := txscript.PayToTaprootScript(outputKey) + require.NoError(t, err) + require.Equal( + t, fixture.prevOutputs[fixture.assetInIndex].PkScript, pkScript, + ) +} + +// TestVerifyProofFile verifies that untrusted proof files are first delegated +// to tapd and then bound to the expected deposit outpoint and amount. +func TestVerifyProofFile(t *testing.T) { + fixture := newWitnessFixture(t) + proofFile, err := proof.NewFile(proof.V0, *fixture.proof) + require.NoError(t, err) + var encodedProof bytes.Buffer + require.NoError(t, proofFile.Encode(&encodedProof)) + rpcProofFile := &taprpc.ProofFile{RawProofFile: encodedProof.Bytes()} + expectedOutpoint := fixture.proof.OutPoint() + + verifier := &proofVerifierMock{ + response: &taprpc.VerifyProofResponse{Valid: true}, + } + root, err := fixture.kit.VerifyProofFile( + t.Context(), verifier, rpcProofFile, &expectedOutpoint, + fixture.proof.Asset.Amount, + ) + require.NoError(t, err) + require.Len(t, root, chainhash.HashSize) + require.Equal(t, 1, verifier.calls) + + wrongOutpoint := expectedOutpoint + wrongOutpoint.Index++ + _, err = fixture.kit.VerifyProofFile( + t.Context(), verifier, rpcProofFile, &wrongOutpoint, + fixture.proof.Asset.Amount, + ) + require.ErrorContains(t, err, "deposit proof outpoint mismatch") + + verifier.response.Valid = false + _, err = fixture.kit.VerifyProofFile( + t.Context(), verifier, rpcProofFile, &expectedOutpoint, + fixture.proof.Asset.Amount, + ) + require.ErrorContains(t, err, "invalid deposit proof file") +} + // TestCreateTimeoutWitness verifies the refund signature and witness bind to // the proof-selected input rather than an assumed position. func TestCreateTimeoutWitness(t *testing.T) { From 81e876cd603203e5714f0591475dd93b4d6c80f9 Mon Sep 17 00:00:00 2001 From: Slyghtning Date: Fri, 4 Sep 2026 15:01:11 +0200 Subject: [PATCH 5/5] build: Update Taproot Assets to v0.8.3 Align taprpc and LND with the Taproot Assets v0.8.3 dependency graph. Raise the minimum Go build version to 1.25.13 and refresh module sums for both the main and client RPC modules. --- assets/deposit/kit_test.go | 7 +++++++ assets/htlc/swapkit_test.go | 17 +++++++++++++++++ docs/release-notes/release-notes-next.md | 3 +++ go.mod | 12 ++++++------ go.sum | 20 ++++++++++---------- looprpc/go.mod | 8 ++++---- looprpc/go.sum | 12 ++++++------ 7 files changed, 53 insertions(+), 26 deletions(-) diff --git a/assets/deposit/kit_test.go b/assets/deposit/kit_test.go index 7b6e344c9..77d54b538 100644 --- a/assets/deposit/kit_test.go +++ b/assets/deposit/kit_test.go @@ -389,6 +389,13 @@ func TestVerifyProofReturnsAnchorRoot(t *testing.T) { ) require.ErrorContains(t, err, "deposit asset amount mismatch") + malformedProof := *fixture.proof + malformedProof.InclusionProof.InternalKey = nil + _, err = fixture.kit.AnchorRootFromProofCommitment( + &malformedProof, malformedProof.Asset.Amount, + ) + require.Error(t, err) + outputKey := txscript.ComputeTaprootOutputKey( fixture.kit.muSig2Key.PreTweakedKey, root, ) diff --git a/assets/htlc/swapkit_test.go b/assets/htlc/swapkit_test.go index 5e389e86d..3fc1beefb 100644 --- a/assets/htlc/swapkit_test.go +++ b/assets/htlc/swapkit_test.go @@ -813,6 +813,23 @@ func TestGetPkScriptFromProof(t *testing.T) { } } +// TestMalformedProofReturnsError verifies the Taproot Assets structural proof +// verifier rejects missing keys instead of panicking at this exported boundary. +func TestMalformedProofReturnsError(t *testing.T) { + fixture := newWitnessFixture(t, SuccessSequence) + + missingInternalKey := *fixture.proof + missingInternalKey.InclusionProof.InternalKey = nil + _, err := GenTaprootAssetRootFromProof(&missingInternalKey) + require.ErrorContains(t, err, "internal key") + + missingScriptKey := *fixture.proof + missingScriptKey.Asset = *fixture.proof.Asset.Copy() + missingScriptKey.Asset.ScriptKey.PubKey = nil + _, err = GenTaprootAssetRootFromProof(&missingScriptKey) + require.Error(t, err) +} + // executeWitness runs the virtual asset VM and Bitcoin script engine against a // generated witness. func (f *witnessFixture) executeWitness(t *testing.T, diff --git a/docs/release-notes/release-notes-next.md b/docs/release-notes/release-notes-next.md index f80313fdc..35d72ac2c 100644 --- a/docs/release-notes/release-notes-next.md +++ b/docs/release-notes/release-notes-next.md @@ -40,6 +40,9 @@ #### Maintenance +* Update Taproot Assets to v0.8.3, taprpc to v1.3.3, and the LND dependency to + v0.21.3-beta. The minimum Go build version is now 1.25.13. + * The Docker image build now verifies that every platform of the image index holds binaries for the architecture it advertises, and gives a release its tag only once that check has passed. diff --git a/go.mod b/go.mod index b497edbc8..7ccdbd790 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/btcsuite/btcd/btcutil/psbt v1.1.10 github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 github.com/btcsuite/btclog/v2 v2.0.1-0.20250728225537-6090e87c6c5b - github.com/btcsuite/btcwallet v0.16.18 + github.com/btcsuite/btcwallet v0.16.19 github.com/btcsuite/btcwallet/wtxmgr v1.5.6 github.com/davecgh/go-spew v1.1.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 @@ -22,15 +22,15 @@ require ( github.com/lightninglabs/lndclient v0.21.0-2 github.com/lightninglabs/loop/looprpc v1.0.7 github.com/lightninglabs/loop/swapserverrpc v1.0.14 - github.com/lightninglabs/taproot-assets v0.8.1 - github.com/lightninglabs/taproot-assets/taprpc v1.2.0 - github.com/lightningnetwork/lnd v0.21.0-beta + github.com/lightninglabs/taproot-assets v0.8.3 + github.com/lightninglabs/taproot-assets/taprpc v1.3.3 + github.com/lightningnetwork/lnd v0.21.3-beta github.com/lightningnetwork/lnd/cert v1.2.2 github.com/lightningnetwork/lnd/clock v1.1.1 github.com/lightningnetwork/lnd/queue v1.2.0 github.com/lightningnetwork/lnd/ticker v1.1.1 github.com/lightningnetwork/lnd/tlv v1.3.2 - github.com/lightningnetwork/lnd/tor v1.1.6 + github.com/lightningnetwork/lnd/tor v1.1.7 github.com/ory/dockertest/v3 v3.10.0 github.com/stretchr/testify v1.11.1 github.com/urfave/cli-docs/v3 v3.1.1-0.20251020101624-bec07369b4f6 @@ -232,7 +232,7 @@ replace go.augendre.info/arangolint => github.com/Crocmagnon/arangolint v0.4.0 replace go.augendre.info/fatcontext => github.com/Crocmagnon/fatcontext v0.9.0 -go 1.25.12 +go 1.25.13 // This sqldb revision contains lnd's pgx v5 migration, which removes the // vulnerable legacy pgx v4/pgproto3 dependency chain. Remove this replacement diff --git a/go.sum b/go.sum index 06ea110a9..418087406 100644 --- a/go.sum +++ b/go.sum @@ -667,8 +667,8 @@ github.com/btcsuite/btclog v1.0.0/go.mod h1:w7xnGOhwT3lmrS4H3b/D1XAXxvh+tbhUm8xe 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 v0.16.19 h1:F52y5luPecfjSDajteVm8qYR6H8vsZ40Ot+Mim8e3JA= +github.com/btcsuite/btcwallet v0.16.19/go.mod h1:u4908XXsJNEl8t8uYz01dEMZqGg6cMN4WCumcuHmbUE= 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= @@ -1066,14 +1066,14 @@ github.com/lightninglabs/neutrino/cache v1.1.3 h1:rgnabC41W+XaPuBTQrdeFjFCCAVKh1 github.com/lightninglabs/neutrino/cache v1.1.3/go.mod h1:qxkJb+pUxR5p84jl5uIGFCR4dGdFkhNUwMSxw3EUWls= github.com/lightninglabs/protobuf-go-hex-display v1.34.2-hex-display h1:w7FM5LH9Z6CpKxl13mS48idsu6F+cEZf0lkyiV+Dq9g= github.com/lightninglabs/protobuf-go-hex-display v1.34.2-hex-display/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= -github.com/lightninglabs/taproot-assets v0.8.1 h1:E0xbHcQ/B+KmMZz6o3nqiYSMcDs2Vu0aWd+FuomDFYg= -github.com/lightninglabs/taproot-assets v0.8.1/go.mod h1:iq4ZybixussUx6NUaMYyo20uXMptibhbVLM3y/0ihIc= -github.com/lightninglabs/taproot-assets/taprpc v1.2.0 h1:CDiGyo19DTUyJcZTdhp5d6AQBz94N+mpGQNO0kEcnPk= -github.com/lightninglabs/taproot-assets/taprpc v1.2.0/go.mod h1:RkBWxHKN8JpPtoa/yBK5qZW5svz5pR9GAOT2rUP7oOI= +github.com/lightninglabs/taproot-assets v0.8.3 h1:X2Hroccy7fFKxxAADVB4QpwfA9UVFtLgD/JayWs4iro= +github.com/lightninglabs/taproot-assets v0.8.3/go.mod h1:qb76QDcVd6uwCR+tqjqiV4XeSiV1HhkvjeMeZFExZic= +github.com/lightninglabs/taproot-assets/taprpc v1.3.3 h1:KwscIMQ7Nyy8SleDiUUTWPCgixpgrN9nunM+QwM/KJQ= +github.com/lightninglabs/taproot-assets/taprpc v1.3.3/go.mod h1:0dBS6jLkddm8EvpJSpJjPUMWr294/YRoM/IAzdfo3pw= 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 v0.21.3-beta h1:Tp1YdwnP0daq/wenwObkaCqe0hckIRnxibN2QKoUv9Y= +github.com/lightningnetwork/lnd v0.21.3-beta/go.mod h1:cUmbodV1/27JGrM/aKib8mXfz8bFxT9iGm0WJi647ds= 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= @@ -1094,8 +1094,8 @@ github.com/lightningnetwork/lnd/ticker v1.1.1 h1:J/b6N2hibFtC7JLV77ULQp++QLtCwT6 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/lightningnetwork/lnd/tor v1.1.7 h1:BfY1KQGz3LVaeaAGI4XYGYCwDQR1ADFD1P/uXsS2dQc= +github.com/lightningnetwork/lnd/tor v1.1.7/go.mod h1:DANQ6QCQBiR+CqrM+mKudgkMy6CR/RS4ALDbjb2W4FU= 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= diff --git a/looprpc/go.mod b/looprpc/go.mod index db04b88d3..85e3d72ed 100644 --- a/looprpc/go.mod +++ b/looprpc/go.mod @@ -1,11 +1,11 @@ module github.com/lightninglabs/loop/looprpc -go 1.25.12 +go 1.25.13 require ( github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 github.com/lightninglabs/loop/swapserverrpc v1.0.14 - github.com/lightningnetwork/lnd v0.21.0-beta + github.com/lightningnetwork/lnd v0.21.3-beta google.golang.org/grpc v1.83.1 google.golang.org/protobuf v1.36.11 gopkg.in/macaroon-bakery.v2 v2.3.0 @@ -28,7 +28,7 @@ require ( github.com/btcsuite/btcd/v2transport v1.0.1 // indirect github.com/btcsuite/btclog v1.0.0 // indirect github.com/btcsuite/btclog/v2 v2.0.1-0.20250728225537-6090e87c6c5b // indirect - github.com/btcsuite/btcwallet v0.16.18 // indirect + github.com/btcsuite/btcwallet v0.16.19 // 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 @@ -98,7 +98,7 @@ require ( 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/lightningnetwork/lnd/tor v1.1.7 // indirect github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect diff --git a/looprpc/go.sum b/looprpc/go.sum index 399ace352..b03f03f7d 100644 --- a/looprpc/go.sum +++ b/looprpc/go.sum @@ -52,8 +52,8 @@ github.com/btcsuite/btclog v1.0.0/go.mod h1:w7xnGOhwT3lmrS4H3b/D1XAXxvh+tbhUm8xe 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 v0.16.19 h1:F52y5luPecfjSDajteVm8qYR6H8vsZ40Ot+Mim8e3JA= +github.com/btcsuite/btcwallet v0.16.19/go.mod h1:u4908XXsJNEl8t8uYz01dEMZqGg6cMN4WCumcuHmbUE= 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= @@ -289,8 +289,8 @@ github.com/lightninglabs/protobuf-go-hex-display v1.34.2-hex-display h1:w7FM5LH9 github.com/lightninglabs/protobuf-go-hex-display v1.34.2-hex-display/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= 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 v0.21.3-beta h1:Tp1YdwnP0daq/wenwObkaCqe0hckIRnxibN2QKoUv9Y= +github.com/lightningnetwork/lnd v0.21.3-beta/go.mod h1:cUmbodV1/27JGrM/aKib8mXfz8bFxT9iGm0WJi647ds= 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/clock v1.1.1 h1:OfR3/zcJd2RhH0RU+zX/77c0ZiOnIMsDIBjgjWdZgA0= @@ -309,8 +309,8 @@ github.com/lightningnetwork/lnd/ticker v1.1.1 h1:J/b6N2hibFtC7JLV77ULQp++QLtCwT6 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/lightningnetwork/lnd/tor v1.1.7 h1:BfY1KQGz3LVaeaAGI4XYGYCwDQR1ADFD1P/uXsS2dQc= +github.com/lightningnetwork/lnd/tor v1.1.7/go.mod h1:DANQ6QCQBiR+CqrM+mKudgkMy6CR/RS4ALDbjb2W4FU= 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=