From 05db2c35df5bc0c6e2ef1e70820c0bd663df79de Mon Sep 17 00:00:00 2001 From: ffranr Date: Tue, 26 Mar 2024 18:27:15 +0000 Subject: [PATCH 001/109] lntest: add test node name to tmp directory name In this commit we add the LND node name to the temporary directory's name. This change makes it easier to identify a particular test node's temporary directory. This commit also replaces the depreciated `ioutil.TempDir` function call with `os.MkdirTemp`. --- lntest/node/harness_node.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lntest/node/harness_node.go b/lntest/node/harness_node.go index fb0eea014..d784f06fc 100644 --- a/lntest/node/harness_node.go +++ b/lntest/node/harness_node.go @@ -97,7 +97,12 @@ type HarnessNode struct { func NewHarnessNode(t *testing.T, cfg *BaseNodeConfig) (*HarnessNode, error) { if cfg.BaseDir == "" { var err error - cfg.BaseDir, err = ioutil.TempDir("", "lndtest-node") + + // Create a temporary directory for the node's data and logs. + // Use dash suffix as a separator between base name and random + // suffix. + dirBaseName := fmt.Sprintf("lndtest-node-%s-", cfg.Name) + cfg.BaseDir, err = os.MkdirTemp("", dirBaseName) if err != nil { return nil, err } From 8afb978c816ad082b4aa159196099b47cef567b5 Mon Sep 17 00:00:00 2001 From: hidewrong Date: Wed, 17 Apr 2024 11:19:31 +0800 Subject: [PATCH 002/109] chore: fix struct names Signed-off-by: hidewrong --- autopilot/choice_test.go | 2 +- contractcourt/nursery_store.go | 2 +- input/input.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/autopilot/choice_test.go b/autopilot/choice_test.go index bde48b0da..c08d87a35 100644 --- a/autopilot/choice_test.go +++ b/autopilot/choice_test.go @@ -21,7 +21,7 @@ func TestWeightedChoiceEmptyMap(t *testing.T) { } } -// singeNonZero is a type used to generate float64 slices with one non-zero +// singleNonZero is a type used to generate float64 slices with one non-zero // element. type singleNonZero []float64 diff --git a/contractcourt/nursery_store.go b/contractcourt/nursery_store.go index 3dc3416f7..b06371f2d 100644 --- a/contractcourt/nursery_store.go +++ b/contractcourt/nursery_store.go @@ -75,7 +75,7 @@ import ( // graduated height and finalized txes. This also prevents people downgrading // and surprising the downgraded nursery with missing data. -// NurseryStore abstracts the persistent storage layer for the utxo nursery. +// NurseryStorer abstracts the persistent storage layer for the utxo nursery. // Concretely, it stores commitment and htlc outputs until any time-bounded // constraints have fully matured. The store exposes methods for enumerating its // contents, and persisting state transitions detected by the utxo nursery. diff --git a/input/input.go b/input/input.go index fe7971eed..211d0d053 100644 --- a/input/input.go +++ b/input/input.go @@ -329,7 +329,7 @@ func (h *HtlcSucceedInput) CraftInputScript(signer Signer, txn *wire.MsgTx, }, nil } -// HtlcsSecondLevelAnchorInput is an input type used to spend HTLC outputs +// HtlcSecondLevelAnchorInput is an input type used to spend HTLC outputs // using a re-signed second level transaction, either via the timeout or success // paths. type HtlcSecondLevelAnchorInput struct { From 8a5160e1de6568699d2244fc63162b05febf380c Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Thu, 26 Jan 2023 11:35:43 +0100 Subject: [PATCH 003/109] multi: add test coverage for integration tests --- .github/workflows/main.yml | 8 +++++++- .gitignore | 1 + Makefile | 4 +++- make/testing_flags.mk | 10 +++++++++- scripts/itest_part.sh | 2 ++ 5 files changed, 22 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 429b09171..720d2a27e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -274,7 +274,13 @@ jobs: run: ./scripts/install_bitcoind.sh $BITCOIN_VERSION - name: run ${{ matrix.name }} - run: make itest-parallel ${{ matrix.args }} + run: make itest-parallel ${{ matrix.args }} cover=1 + + - name: Send coverage + uses: shogo82148/actions-goveralls@v1 + with: + path-to-profile: coverage.txt + parallel: true - name: Zip log files on failure if: ${{ failure() }} diff --git a/.gitignore b/.gitignore index 16d33c142..a44a7b8f5 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,7 @@ itest/.minerlogs itest/lnd-itest itest/btcd-itest itest/.logs-* +itest/cover cmd/cmd *.key diff --git a/Makefile b/Makefile index 41fabbfcc..3c42cd6cf 100644 --- a/Makefile +++ b/Makefile @@ -110,7 +110,7 @@ build: build-itest: @$(call print, "Building itest btcd and lnd.") CGO_ENABLED=0 $(GOBUILD) -tags="integration" -o itest/btcd-itest$(EXEC_SUFFIX) $(DEV_LDFLAGS) $(BTCD_PKG) - CGO_ENABLED=0 $(GOBUILD) -tags="$(ITEST_TAGS)" -o itest/lnd-itest$(EXEC_SUFFIX) $(DEV_LDFLAGS) $(PKG)/cmd/lnd + CGO_ENABLED=0 $(GOBUILD) -tags="$(ITEST_TAGS)" $(ITEST_COVERAGE) -o itest/lnd-itest$(EXEC_SUFFIX) $(DEV_LDFLAGS) $(PKG)/cmd/lnd @$(call print, "Building itest binary for ${backend} backend.") CGO_ENABLED=0 $(GOTEST) -v ./itest -tags="$(DEV_TAGS) $(RPC_TAGS) integration $(backend)" -c -o itest/itest.test$(EXEC_SUFFIX) @@ -197,6 +197,7 @@ itest-only: db-instance @$(call print, "Running integration tests with ${backend} backend.") rm -rf itest/*.log itest/.logs-*; date EXEC_SUFFIX=$(EXEC_SUFFIX) scripts/itest_part.sh 0 1 $(TEST_FLAGS) $(ITEST_FLAGS) + $(COLLECT_ITEST_COVERAGE) #? itest: Build and run integration tests itest: build-itest itest-only @@ -209,6 +210,7 @@ itest-parallel: build-itest db-instance @$(call print, "Running tests") rm -rf itest/*.log itest/.logs-*; date EXEC_SUFFIX=$(EXEC_SUFFIX) scripts/itest_parallel.sh $(ITEST_PARALLELISM) $(NUM_ITEST_TRANCHES) $(TEST_FLAGS) $(ITEST_FLAGS) + $(COLLECT_ITEST_COVERAGE) #? itest-clean: Kill all running itest processes itest-clean: diff --git a/make/testing_flags.mk b/make/testing_flags.mk index 3fecb073a..b2db6861c 100644 --- a/make/testing_flags.mk +++ b/make/testing_flags.mk @@ -2,7 +2,9 @@ DEV_TAGS = dev RPC_TAGS = autopilotrpc chainrpc invoicesrpc neutrinorpc peersrpc routerrpc signrpc verrpc walletrpc watchtowerrpc wtclientrpc LOG_TAGS = TEST_FLAGS = -ITEST_FLAGS = +ITEST_FLAGS = +ITEST_COVERAGE = +COLLECT_ITEST_COVERAGE = EXEC_SUFFIX = COVER_PKG = $$(go list -deps -tags="$(DEV_TAGS)" ./... | grep '$(PKG)' | grep -v lnrpc) NUM_ITEST_TRANCHES = 4 @@ -77,6 +79,12 @@ ifneq ($(tags),) DEV_TAGS += ${tags} endif +# Enable integration test coverage (requires Go >= 1.20.0). +ifneq ($(cover),) +ITEST_COVERAGE = -cover +COLLECT_ITEST_COVERAGE = go tool covdata textfmt -i=itest/cover -o coverage.txt +endif + # Define the log tags that will be applied only when running unit tests. If none # are provided, we default to "nolog" which will be silent. ifneq ($(log),) diff --git a/scripts/itest_part.sh b/scripts/itest_part.sh index 312e13a01..bdf4ecdf5 100755 --- a/scripts/itest_part.sh +++ b/scripts/itest_part.sh @@ -16,6 +16,8 @@ shift EXEC="$WORKDIR"/itest.test"$EXEC_SUFFIX" LND_EXEC="$WORKDIR"/lnd-itest"$EXEC_SUFFIX" BTCD_EXEC="$WORKDIR"/btcd-itest"$EXEC_SUFFIX" +export GOCOVERDIR="$WORKDIR/cover" +mkdir -p "$GOCOVERDIR" echo $EXEC -test.v "$@" -logoutput -logdir=.logs-tranche$TRANCHE -lndexec=$LND_EXEC -btcdexec=$BTCD_EXEC -splittranches=$NUM_TRANCHES -runtranche=$TRANCHE # Exit code 255 causes the parallel jobs to abort, so if one part fails the From 7468eb341651d91dcba28241be574af1e0bb043d Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Thu, 21 Mar 2024 15:38:48 +0100 Subject: [PATCH 004/109] GitHub: only run cover on some itests, send completion We only want to run the coverage on some select tests, since we don't want to make tests with slow backends even slower. And because we use "parallel: true" when uploading the coverage results, those will only be assembled once we send "parallel-finished: true" using the goveralls action. So we do that with a new "finish" job. --- .github/workflows/main.yml | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 720d2a27e..5443f6ee3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -241,13 +241,13 @@ jobs: matrix: include: - name: btcd - args: backend=btcd + args: backend=btcd cover=1 - name: bitcoind - args: backend=bitcoind + args: backend=bitcoind cover=1 - name: bitcoind-notxindex args: backend="bitcoind notxindex" - name: bitcoind-rpcpolling - args: backend="bitcoind rpcpolling" + args: backend="bitcoind rpcpolling" cover=1 - name: bitcoind-etcd args: backend=bitcoind dbbackend=etcd - name: bitcoind-postgres @@ -259,7 +259,7 @@ jobs: - name: bitcoind-sqlite-nativesql args: backend=bitcoind dbbackend=sqlite nativesql=true - name: neutrino - args: backend=neutrino + args: backend=neutrino cover=1 steps: - name: git checkout uses: actions/checkout@v3 @@ -274,9 +274,10 @@ jobs: run: ./scripts/install_bitcoind.sh $BITCOIN_VERSION - name: run ${{ matrix.name }} - run: make itest-parallel ${{ matrix.args }} cover=1 + run: make itest-parallel ${{ matrix.args }} - name: Send coverage + if: ${{ contains(matrix.args, 'cover=1') }} uses: shogo82148/actions-goveralls@v1 with: path-to-profile: coverage.txt @@ -407,3 +408,13 @@ jobs: - name: release notes check run: scripts/check-release-notes.sh + + # Notify about the completion of all coverage collecting jobs. + finish: + if: ${{ always() }} + needs: [unit-test, ubuntu-integration-test] + runs-on: ubuntu-latest + steps: + - uses: shogo82148/actions-goveralls@v1 + with: + parallel-finished: true From 39b7f1c4f4bff9b2b6977cdec283d7978fc49adc Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 25 Mar 2024 14:09:09 +0100 Subject: [PATCH 005/109] GitHub: give tag to each cover job --- .github/workflows/main.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5443f6ee3..6d23cf8d9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -225,6 +225,7 @@ jobs: if: matrix.unit_type == 'btcd unit-cover' with: path-to-profile: coverage.txt + flag-name: 'unit' parallel: true @@ -281,6 +282,7 @@ jobs: uses: shogo82148/actions-goveralls@v1 with: path-to-profile: coverage.txt + flag-name: 'itest-${{ matrix.name }}' parallel: true - name: Zip log files on failure From 2a88cf8eef738fdbce6d49fee0e3d664b7cad5c5 Mon Sep 17 00:00:00 2001 From: ziggie Date: Sat, 30 Mar 2024 16:52:01 +0000 Subject: [PATCH 006/109] mod: update btcwallet version. --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b8a658edd..54827142b 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/btcsuite/btcd/btcutil/psbt v1.1.8 github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f - github.com/btcsuite/btcwallet v0.16.10-0.20240410030101-6fe19a472a62 + github.com/btcsuite/btcwallet v0.16.10-0.20240404104514-b2f31f9045fb github.com/btcsuite/btcwallet/wallet/txauthor v1.3.4 github.com/btcsuite/btcwallet/wallet/txrules v1.2.1 github.com/btcsuite/btcwallet/walletdb v1.4.2 diff --git a/go.sum b/go.sum index c2f3fdb80..e5e56d2c1 100644 --- a/go.sum +++ b/go.sum @@ -92,8 +92,8 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtyd github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcwallet v0.16.10-0.20240410030101-6fe19a472a62 h1:MtcTVTcDbGdTJhfDc7LLikojyl0PYtSRNLwoRaLVbWI= -github.com/btcsuite/btcwallet v0.16.10-0.20240410030101-6fe19a472a62/go.mod h1:2C3Q/MhYAKmk7F+Tey6LfKtKRTdQsrCf8AAAzzDPmH4= +github.com/btcsuite/btcwallet v0.16.10-0.20240404104514-b2f31f9045fb h1:qoIOlBPRZWtfpcbQlNFf67Wz8ZlXo+mxQc9Pnbm/iqU= +github.com/btcsuite/btcwallet v0.16.10-0.20240404104514-b2f31f9045fb/go.mod h1:2C3Q/MhYAKmk7F+Tey6LfKtKRTdQsrCf8AAAzzDPmH4= github.com/btcsuite/btcwallet/wallet/txauthor v1.3.4 h1:poyHFf7+5+RdxNp5r2T6IBRD7RyraUsYARYbp/7t4D8= github.com/btcsuite/btcwallet/wallet/txauthor v1.3.4/go.mod h1:GETGDQuyq+VFfH1S/+/7slLM/9aNa4l7P4ejX6dJfb0= github.com/btcsuite/btcwallet/wallet/txrules v1.2.1 h1:UZo7YRzdHbwhK7Rhv3PO9bXgTxiOH45edK5qdsdiatk= From 62a52b4d7c372ec8a221c18bc5de729d41a26b4d Mon Sep 17 00:00:00 2001 From: ziggie Date: Sat, 30 Mar 2024 16:55:25 +0000 Subject: [PATCH 007/109] multi: Utxo restriction single funding case. Restrict the utxo selection when opening a single internal wallet funded backed channel. --- funding/manager.go | 30 ++++++++++++++++++--- lnwallet/chanfunding/wallet_assembler.go | 3 ++- lnwallet/test/test_interface.go | 4 ++- lnwallet/wallet.go | 34 +++++++++++++++++++++--- server.go | 5 ++-- sweep/sweeper.go | 23 ++++++++++++++++ 6 files changed, 87 insertions(+), 12 deletions(-) diff --git a/funding/manager.go b/funding/manager.go index e110269a7..b012de48d 100644 --- a/funding/manager.go +++ b/funding/manager.go @@ -537,6 +537,12 @@ type Config struct { // AliasManager is an implementation of the aliasHandler interface that // abstracts away the handling of many alias functions. AliasManager aliasHandler + + // IsSweeperOutpoint queries the sweeper store for successfully + // published sweeps. This is useful to decide for the internal wallet + // backed funding flow to not use utxos still being swept by the sweeper + // subsystem. + IsSweeperOutpoint func(wire.OutPoint) bool } // Manager acts as an orchestrator/bridge between the wallet's @@ -4600,10 +4606,26 @@ func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) { MinConfs: msg.MinConfs, CommitType: commitType, ChanFunder: msg.ChanFunder, - ZeroConf: zeroConf, - OptionScidAlias: scid, - ScidAliasFeature: scidFeatureVal, - Memo: msg.Memo, + // Unconfirmed Utxos which are marked by the sweeper subsystem + // are excluded from the coin selection because they are not + // final and can be RBFed by the sweeper subsystem. + AllowUtxoForFunding: func(u lnwallet.Utxo) bool { + // Utxos with at least 1 confirmation are safe to use + // for channel openings because they don't bare the risk + // of being replaced (BIP 125 RBF). + if u.Confirmations > 0 { + return true + } + + // Query the sweeper storage to make sure we don't use + // an unconfirmed utxo still in use by the sweeper + // subsystem. + return !f.cfg.IsSweeperOutpoint(u.OutPoint) + }, + ZeroConf: zeroConf, + OptionScidAlias: scid, + ScidAliasFeature: scidFeatureVal, + Memo: msg.Memo, } reservation, err := f.cfg.Wallet.InitChannelReservation(req) diff --git a/lnwallet/chanfunding/wallet_assembler.go b/lnwallet/chanfunding/wallet_assembler.go index d4ee080bc..4f2aa759b 100644 --- a/lnwallet/chanfunding/wallet_assembler.go +++ b/lnwallet/chanfunding/wallet_assembler.go @@ -334,7 +334,8 @@ func (w *WalletAssembler) ProvisionChannel(r *Request) (Intent, error) { } for _, coin := range manuallySelectedCoins { if _, ok := unspent[coin.OutPoint]; !ok { - return fmt.Errorf("outpoint already spent: %v", + return fmt.Errorf("outpoint already spent or "+ + "locked by another subsystem: %v", coin.OutPoint) } } diff --git a/lnwallet/test/test_interface.go b/lnwallet/test/test_interface.go index 401c46683..12b3aafc9 100644 --- a/lnwallet/test/test_interface.go +++ b/lnwallet/test/test_interface.go @@ -2963,7 +2963,9 @@ func testSingleFunderExternalFundingTx(miner *rpctest.Harness, // we'll create a new chanfunding.Assembler hacked by Alice's wallet. aliceChanFunder := chanfunding.NewWalletAssembler( chanfunding.WalletConfig{ - CoinSource: lnwallet.NewCoinSource(alice), + CoinSource: lnwallet.NewCoinSource( + alice, nil, + ), CoinSelectLocker: alice, CoinLeaser: alice, Signer: alice.Cfg.Signer, diff --git a/lnwallet/wallet.go b/lnwallet/wallet.go index 7786791f9..b99b6eed2 100644 --- a/lnwallet/wallet.go +++ b/lnwallet/wallet.go @@ -184,6 +184,15 @@ type InitFundingReserveMsg struct { // used. ChanFunder chanfunding.Assembler + // AllowUtxoForFunding enables the channel funding workflow to restrict + // the selection of utxos when selecting the inputs for the channel + // opening. This does ONLY apply for the internal wallet backed channel + // opening case. + // + // NOTE: This is very useful when opening channels with unconfirmed + // inputs to make sure stable non-replaceable inputs are used. + AllowUtxoForFunding func(Utxo) bool + // ZeroConf is a boolean that is true if a zero-conf channel was // negotiated. ZeroConf bool @@ -849,7 +858,9 @@ func (l *LightningWallet) handleFundingReserveRequest(req *InitFundingReserveMsg // P2WPKH dust limit and to avoid threading through two // different dust limits. cfg := chanfunding.WalletConfig{ - CoinSource: &CoinSource{l}, + CoinSource: NewCoinSource( + l, req.AllowUtxoForFunding, + ), CoinSelectLocker: l, CoinLeaser: l, Signer: l.Cfg.Signer, @@ -2525,12 +2536,16 @@ func (l *LightningWallet) CancelRebroadcast(txid chainhash.Hash) { // CoinSource is a wrapper around the wallet that implements the // chanfunding.CoinSource interface. type CoinSource struct { - wallet *LightningWallet + wallet *LightningWallet + allowUtxo func(Utxo) bool } // NewCoinSource creates a new instance of the CoinSource wrapper struct. -func NewCoinSource(w *LightningWallet) *CoinSource { - return &CoinSource{wallet: w} +func NewCoinSource(w *LightningWallet, allowUtxo func(Utxo) bool) *CoinSource { + return &CoinSource{ + wallet: w, + allowUtxo: allowUtxo, + } } // ListCoins returns all UTXOs from the source that have between @@ -2546,7 +2561,18 @@ func (c *CoinSource) ListCoins(minConfs int32, } var coins []wallet.Coin + for _, utxo := range utxos { + // If there is a filter function supplied all utxos not adhering + // to these conditions will be discared. + if c.allowUtxo != nil && !c.allowUtxo(*utxo) { + walletLog.Infof("Cannot use unconfirmed "+ + "utxo=%v because it is unstable and could be "+ + "replaced", utxo.OutPoint) + + continue + } + coins = append(coins, wallet.Coin{ TxOut: wire.TxOut{ Value: int64(utxo.Value), diff --git a/server.go b/server.go index e2c0b831a..2979880a2 100644 --- a/server.go +++ b/server.go @@ -1489,8 +1489,9 @@ func newServer(cfg *Config, listenAddrs []net.Addr, EnableUpfrontShutdown: cfg.EnableUpfrontShutdown, MaxAnchorsCommitFeeRate: chainfee.SatPerKVByte( s.cfg.MaxCommitFeeRateAnchors * 1000).FeePerKWeight(), - DeleteAliasEdge: deleteAliasEdge, - AliasManager: s.aliasMgr, + DeleteAliasEdge: deleteAliasEdge, + AliasManager: s.aliasMgr, + IsSweeperOutpoint: s.sweeper.IsSweeperOutpoint, }) if err != nil { return nil, err diff --git a/sweep/sweeper.go b/sweep/sweeper.go index 2754485ea..e8e7d77a4 100644 --- a/sweep/sweeper.go +++ b/sweep/sweeper.go @@ -1735,3 +1735,26 @@ func (s *UtxoSweeper) handleBumpEvent(r *BumpResult) error { return nil } + +// IsSweeperOutpoint determines whether the outpoint was created by the sweeper. +// +// NOTE: It is enough to check the txid because the sweeper will create +// outpoints which solely belong to the internal LND wallet. +func (s *UtxoSweeper) IsSweeperOutpoint(op wire.OutPoint) bool { + found, err := s.cfg.Store.IsOurTx(op.Hash) + // In case there is an error fetching the transaction details from the + // sweeper store we assume the outpoint is still used by the sweeper + // (worst case scenario). + // + // TODO(ziggie): Ensure that confirmed outpoints are deleted from the + // bucket. + if err != nil && !errors.Is(err, errNoTxHashesBucket) { + log.Errorf("failed to fetch info for outpoint(%v:%d) "+ + "with: %v, we assume it is still in use by the sweeper", + op.Hash, op.Index, err) + + return true + } + + return found +} From ab7634b276c04ef87ce1c31cecd80d64d8bc2179 Mon Sep 17 00:00:00 2001 From: ziggie Date: Sat, 30 Mar 2024 17:03:09 +0000 Subject: [PATCH 008/109] multi: Add utxo restriction for batchchannel openings. Add utxo restrictions for psbt internal wallet funded lightning channels. This also includes batchopening channels backed by the internal wallet. --- lnrpc/walletrpc/walletkit_server.go | 67 +++++++++++++++++++++++++++-- lntest/mock/walletcontroller.go | 3 +- lnwallet/btcwallet/psbt.go | 10 ++++- lnwallet/interface.go | 3 +- lnwallet/mock.go | 3 +- 5 files changed, 79 insertions(+), 7 deletions(-) diff --git a/lnrpc/walletrpc/walletkit_server.go b/lnrpc/walletrpc/walletkit_server.go index b8fcbc776..6a1b8d116 100644 --- a/lnrpc/walletrpc/walletkit_server.go +++ b/lnrpc/walletrpc/walletkit_server.go @@ -1551,21 +1551,82 @@ func (w *WalletKit) fundPsbtInternalWallet(account string, return err } + // filterFn makes sure utxos which are unconfirmed and + // still used by the sweeper are not used. + filterFn := func(u *lnwallet.Utxo) bool { + // Confirmed utxos are always allowed. + if u.Confirmations > 0 { + return true + } + + // Unconfirmed utxos in use by the sweeper are + // not stable to use because they can be + // replaced. + if w.cfg.Sweeper.IsSweeperOutpoint(u.OutPoint) { + log.Warnf("Cannot use unconfirmed "+ + "utxo=%v because it is "+ + "unstable and could be "+ + "replaced", u.OutPoint) + + return false + } + + return true + } + + eligible := fn.Filter(filterFn, utxos) + // Validate all inputs against our known list of UTXOs // now. - err = verifyInputsUnspent(packet.UnsignedTx.TxIn, utxos) + err = verifyInputsUnspent( + packet.UnsignedTx.TxIn, eligible, + ) if err != nil { return err } } + // currentHeight is needed to determine whether the internal + // wallet utxo is still unconfirmed. + _, currentHeight, err := w.cfg.Chain.GetBestBlock() + if err != nil { + return fmt.Errorf("unable to retrieve current "+ + "height: %v", err) + } + + // restrictUnstableUtxos is a filter function which disallows + // the usage of unconfirmed outputs published (still in use) by + // the sweeper. + restrictUnstableUtxos := func(utxo wtxmgr.Credit) bool { + // Wallet utxos which are unmined have a height + // of -1. + if utxo.Height != -1 && utxo.Height <= currentHeight { + // Confirmed utxos are always allowed. + return true + } + + // Utxos used by the sweeper are not used for + // channel openings. + allowed := !w.cfg.Sweeper.IsSweeperOutpoint( + utxo.OutPoint, + ) + if !allowed { + log.Warnf("Cannot use unconfirmed "+ + "utxo=%v because it is "+ + "unstable and could be "+ + "replaced", utxo.OutPoint) + } + + return allowed + } + // We made sure the input from the user is as sane as possible. // We can now ask the wallet to fund the TX. This will not yet // lock any coins but might still change the wallet DB by // generating a new change address. changeIndex, err := w.cfg.Wallet.FundPsbt( - packet, minConfs, feeSatPerKW, account, - keyScope, strategy, + packet, minConfs, feeSatPerKW, account, keyScope, + strategy, restrictUnstableUtxos, ) if err != nil { return fmt.Errorf("wallet couldn't fund PSBT: %w", err) diff --git a/lntest/mock/walletcontroller.go b/lntest/mock/walletcontroller.go index 21d78add3..52aecb382 100644 --- a/lntest/mock/walletcontroller.go +++ b/lntest/mock/walletcontroller.go @@ -208,7 +208,8 @@ func (w *WalletController) ListLeasedOutputs() ([]*base.ListLeasedOutputResult, // FundPsbt currently does nothing. func (w *WalletController) FundPsbt(*psbt.Packet, int32, chainfee.SatPerKWeight, - string, *waddrmgr.KeyScope, base.CoinSelectionStrategy) (int32, error) { + string, *waddrmgr.KeyScope, base.CoinSelectionStrategy, + func(utxo wtxmgr.Credit) bool) (int32, error) { return 0, nil } diff --git a/lnwallet/btcwallet/psbt.go b/lnwallet/btcwallet/psbt.go index 0fdf76c38..ec88cd92f 100644 --- a/lnwallet/btcwallet/psbt.go +++ b/lnwallet/btcwallet/psbt.go @@ -15,6 +15,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcwallet/waddrmgr" "github.com/btcsuite/btcwallet/wallet" + "github.com/btcsuite/btcwallet/wtxmgr" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lnwallet" @@ -60,6 +61,9 @@ var ( // imported public keys. For custom account, no key scope should be provided // as the coin selection key scope will always be used to generate the change // address. +// The function argument `allowUtxo` specifies a filter function for utxos +// during coin selection. It should return true for utxos that can be used and +// false for those that should be excluded. // // NOTE: If the packet doesn't contain any inputs, coin selection is performed // automatically. The account parameter must be non-empty as it determines which @@ -74,7 +78,8 @@ var ( func (b *BtcWallet) FundPsbt(packet *psbt.Packet, minConfs int32, feeRate chainfee.SatPerKWeight, accountName string, changeScope *waddrmgr.KeyScope, - strategy wallet.CoinSelectionStrategy) (int32, error) { + strategy wallet.CoinSelectionStrategy, + allowUtxo func(wtxmgr.Credit) bool) (int32, error) { // The fee rate is passed in using units of sat/kw, so we'll convert // this to sat/KB as the CreateSimpleTx method requires this unit. @@ -130,6 +135,9 @@ func (b *BtcWallet) FundPsbt(packet *psbt.Packet, minConfs int32, if changeScope != nil { opts = append(opts, wallet.WithCustomChangeScope(changeScope)) } + if allowUtxo != nil { + opts = append(opts, wallet.WithUtxoFilter(allowUtxo)) + } // Let the wallet handle coin selection and/or fee estimation based on // the partial TX information in the packet. diff --git a/lnwallet/interface.go b/lnwallet/interface.go index 59e6f5aab..a48e92560 100644 --- a/lnwallet/interface.go +++ b/lnwallet/interface.go @@ -468,7 +468,8 @@ type WalletController interface { FundPsbt(packet *psbt.Packet, minConfs int32, feeRate chainfee.SatPerKWeight, account string, changeScope *waddrmgr.KeyScope, - strategy base.CoinSelectionStrategy) (int32, error) + strategy base.CoinSelectionStrategy, + allowUtxo func(wtxmgr.Credit) bool) (int32, error) // SignPsbt expects a partial transaction with all inputs and outputs // fully declared and tries to sign all unsigned inputs that have all diff --git a/lnwallet/mock.go b/lnwallet/mock.go index 0146df57e..1873de79a 100644 --- a/lnwallet/mock.go +++ b/lnwallet/mock.go @@ -217,7 +217,8 @@ func (w *mockWalletController) ListLeasedOutputs() ( // FundPsbt currently does nothing. func (w *mockWalletController) FundPsbt(*psbt.Packet, int32, chainfee.SatPerKWeight, string, *waddrmgr.KeyScope, - base.CoinSelectionStrategy) (int32, error) { + base.CoinSelectionStrategy, func(utxo wtxmgr.Credit) bool) (int32, + error) { return 0, nil } From b954ee4c7222919d1256c036b882a27ba27ce807 Mon Sep 17 00:00:00 2001 From: ziggie Date: Tue, 2 Apr 2024 19:28:54 +0100 Subject: [PATCH 009/109] rpcserver: allow unconf. inputs for psbt shim. Allow unconfirmed inputs to be used when funding a channel via the psbt channel opening flow. We do now check for unstable utxos. --- lnrpc/walletrpc/walletkit_server.go | 4 ++-- rpcserver.go | 13 ++++++------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/lnrpc/walletrpc/walletkit_server.go b/lnrpc/walletrpc/walletkit_server.go index 6a1b8d116..d3f5131b0 100644 --- a/lnrpc/walletrpc/walletkit_server.go +++ b/lnrpc/walletrpc/walletkit_server.go @@ -1574,12 +1574,12 @@ func (w *WalletKit) fundPsbtInternalWallet(account string, return true } - eligible := fn.Filter(filterFn, utxos) + eligibleUtxos := fn.Filter(filterFn, utxos) // Validate all inputs against our known list of UTXOs // now. err = verifyInputsUnspent( - packet.UnsignedTx.TxIn, eligible, + packet.UnsignedTx.TxIn, eligibleUtxos, ) if err != nil { return err diff --git a/rpcserver.go b/rpcserver.go index 7f2ca16da..810ac2630 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1890,7 +1890,7 @@ func newFundingShimAssembler(chanPointShim *lnrpc.ChanPointShim, initiator bool, // newFundingShimAssembler returns a new fully populated // chanfunding.PsbtAssembler using a FundingShim obtained from an RPC caller. -func newPsbtAssembler(req *lnrpc.OpenChannelRequest, normalizedMinConfs int32, +func newPsbtAssembler(req *lnrpc.OpenChannelRequest, psbtShim *lnrpc.PsbtShim, netParams *chaincfg.Params) ( chanfunding.Assembler, error) { @@ -1904,11 +1904,6 @@ func newPsbtAssembler(req *lnrpc.OpenChannelRequest, normalizedMinConfs int32, if len(psbtShim.PendingChanId) != 32 { return nil, fmt.Errorf("pending chan ID not set") } - if normalizedMinConfs != 1 { - return nil, fmt.Errorf("setting non-default values for " + - "minimum confirmation is not supported for PSBT " + - "funding") - } if req.SatPerByte != 0 || req.SatPerVbyte != 0 || req.TargetConf != 0 { // nolint:staticcheck return nil, fmt.Errorf("specifying fee estimation parameters " + "is not supported for PSBT funding") @@ -2351,8 +2346,12 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest, // chanfunding.PsbtAssembler to construct the funding // transaction. copy(req.PendingChanID[:], psbtShim.PendingChanId) + + // NOTE: For the PSBT case we do also allow unconfirmed + // utxos to fund the psbt transaction because we make + // sure we only use stable utxos. req.ChanFunder, err = newPsbtAssembler( - in, req.MinConfs, psbtShim, + in, psbtShim, &r.server.cc.Wallet.Cfg.NetParams, ) if err != nil { From 351e9a68dd95a4ce25f4b09863ef8918d009b12f Mon Sep 17 00:00:00 2001 From: ziggie Date: Tue, 2 Apr 2024 19:32:50 +0100 Subject: [PATCH 010/109] multi: Add tests to psbt and normal open channel flow. Itests were added to the normal channel funding flow and the psbt funding flow using unstable (unconfirmed sweeper inputs). --- funding/manager_test.go | 5 + itest/list_on_test.go | 8 + ...lnd_channel_funding_utxo_selection_test.go | 3 +- itest/lnd_funding_test.go | 209 ++++++++++++ itest/lnd_psbt_test.go | 318 ++++++++++++++++++ lntest/harness.go | 1 + lntest/rpc/wallet_kit.go | 10 + lnwallet/test/test_interface.go | 7 +- 8 files changed, 559 insertions(+), 2 deletions(-) diff --git a/funding/manager_test.go b/funding/manager_test.go index db61c3000..69e23eeb8 100644 --- a/funding/manager_test.go +++ b/funding/manager_test.go @@ -556,6 +556,11 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey, return nil, nil }, AliasManager: aliasMgr, + // For unit tests we default to false meaning that no funds + // originated from the sweeper. + IsSweeperOutpoint: func(wire.OutPoint) bool { + return false + }, } for _, op := range options { diff --git a/itest/list_on_test.go b/itest/list_on_test.go index b4f586fa2..4696fc80e 100644 --- a/itest/list_on_test.go +++ b/itest/list_on_test.go @@ -117,6 +117,14 @@ var allTestCases = []*lntest.TestCase{ Name: "batch channel funding", TestFunc: testBatchChanFunding, }, + { + Name: "open channel with unstable utxos", + TestFunc: testChannelFundingWithUnstableUtxos, + }, + { + Name: "open psbt channel with unstable utxos", + TestFunc: testPsbtChanFundingWithUnstableUtxos, + }, { Name: "update channel policy", TestFunc: testUpdateChannelPolicy, diff --git a/itest/lnd_channel_funding_utxo_selection_test.go b/itest/lnd_channel_funding_utxo_selection_test.go index 4ba4a557b..8504a17cb 100644 --- a/itest/lnd_channel_funding_utxo_selection_test.go +++ b/itest/lnd_channel_funding_utxo_selection_test.go @@ -330,7 +330,8 @@ func runUtxoSelectionTestCase(ht *lntest.HarnessTest, alice, // When re-selecting a spent output for funding another channel we // expect the respective error message. if tc.reuseUtxo { - expectedErrStr := fmt.Sprintf("outpoint already spent: %s:%d", + expectedErrStr := fmt.Sprintf("outpoint already spent or "+ + "locked by another subsystem: %s:%d", selectedOutpoints[0].TxidStr, selectedOutpoints[0].OutputIndex) expectedErr := fmt.Errorf(expectedErrStr) diff --git a/itest/lnd_funding_test.go b/itest/lnd_funding_test.go index 97613429e..38ca71d92 100644 --- a/itest/lnd_funding_test.go +++ b/itest/lnd_funding_test.go @@ -12,6 +12,7 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/chainreg" + "github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/funding" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/labels" @@ -1250,3 +1251,211 @@ func deriveFundingShim(ht *lntest.HarnessTest, carol, dave *node.HarnessNode, return fundingShim, chanPoint } + +// testChannelFundingWithUnstableUtxos tests channel openings with restricted +// utxo selection. Internal wallet utxos might be restricted due to another +// subsystems still using it therefore it would be unsecure to use them for +// channel openings. This test focuses on unconfirmed utxos which are still +// being used by the sweeper subsystem hence should only be used when confirmed. +func testChannelFundingWithUnstableUtxos(ht *lntest.HarnessTest) { + // Select funding amt below wumbo size because we later use fundMax to + // open a channel with the total balance. + fundingAmt := btcutil.Amount(3_000_000) + + // We use STATIC_REMOTE_KEY channels because anchor sweeps would + // interfere and create additional utxos. + // Although its the current default we explicitly signal it. + cType := lnrpc.CommitmentType_STATIC_REMOTE_KEY + + // First, we'll create two new nodes that we'll use to open channel + // between for this test. + carol := ht.NewNode("carol", nil) + // We'll attempt at max 2 pending channels, so Dave will need to accept + // two pending ones. + dave := ht.NewNode("dave", []string{ + "--maxpendingchannels=2", + }) + ht.EnsureConnected(carol, dave) + + // Fund Carol's wallet with a confirmed utxo. + ht.FundCoins(fundingAmt, carol) + + // Now spend the coins to create an unconfirmed transaction. This is + // necessary to test also the neutrino behaviour. For neutrino nodes + // only unconfirmed transactions originating from this node will be + // recognized as unconfirmed. + req := &lnrpc.NewAddressRequest{Type: AddrTypeTaprootPubkey} + resp := carol.RPC.NewAddress(req) + + sendCoinsResp := carol.RPC.SendCoins(&lnrpc.SendCoinsRequest{ + Addr: resp.Address, + SendAll: true, + SatPerVbyte: 1, + }) + + walletUtxo := ht.AssertNumUTXOsUnconfirmed(carol, 1)[0] + require.EqualValues(ht, sendCoinsResp.Txid, walletUtxo.Outpoint.TxidStr) + + // We will attempt to open 2 channels at a time. + chanSize := btcutil.Amount(walletUtxo.AmountSat / 3) + + // Open a channel to dave with an unconfirmed utxo. Although this utxo + // is unconfirmed it can be used to open a channel because it did not + // originated from the sweeper subsystem. + update := ht.OpenChannelAssertPending(carol, dave, + lntest.OpenChannelParams{ + Amt: chanSize, + SpendUnconfirmed: true, + CommitmentType: cType, + }) + chanPoint1 := lntest.ChanPointFromPendingUpdate(update) + + // Verify that both nodes know about the channel. + ht.AssertNumPendingOpenChannels(carol, 1) + ht.AssertNumPendingOpenChannels(dave, 1) + + // We open another channel on the fly, funds are unconfirmed but because + // the tx was not created by the sweeper we can use it and open another + // channel. This is a common use case when opening zeroconf channels, + // so unconfirmed utxos originated from prior channel opening are safe + // to use because channel opening should not be RBFed, at least not for + // now. + update = ht.OpenChannelAssertPending(carol, dave, + lntest.OpenChannelParams{ + Amt: chanSize, + SpendUnconfirmed: true, + CommitmentType: cType, + }) + + chanPoint2 := lntest.ChanPointFromPendingUpdate(update) + + ht.AssertNumPendingOpenChannels(carol, 2) + ht.AssertNumPendingOpenChannels(dave, 2) + + // We expect the initial funding tx to confirm and also the two + // unconfirmed channel openings. + ht.MineBlocksAndAssertNumTxes(1, 3) + + // Now we create an unconfirmed utxo which originated from the sweeper + // subsystem and hence is not safe to use for channel openings. We do + // that by dave force-closing the channel. Which let's carol sweep its + // to_remote output which is not encumbered by any relative locktime. + ht.CloseChannelAssertPending(dave, chanPoint2, true) + // Mine the force close commitment transaction. + ht.MineBlocksAndAssertNumTxes(1, 1) + + // Mine one block to trigger the sweep transaction. + ht.MineEmptyBlocks(1) + + // We need to wait for carol initiating the sweep of the to_remote + // output of chanPoint2. + utxos := ht.AssertNumUTXOsUnconfirmed(carol, 1) + + // We filter for the unconfirmed utxo and try to open a channel with + // that utxo. + utxoOpt := fn.Find(func(u *lnrpc.Utxo) bool { + return u.Confirmations == 0 + }, utxos) + fundingUtxo := utxoOpt.UnwrapOrFail(ht.T) + + // Now try to open the channel with this utxo and expect an error. + expectedErr := fmt.Errorf("outpoint already spent or "+ + "locked by another subsystem: %s:%d", + fundingUtxo.Outpoint.TxidStr, + fundingUtxo.Outpoint.OutputIndex) + + ht.OpenChannelAssertErr(carol, dave, + lntest.OpenChannelParams{ + FundMax: true, + SpendUnconfirmed: true, + Outpoints: []*lnrpc.OutPoint{ + fundingUtxo.Outpoint, + }, + }, expectedErr) + + // The channel opening failed because the utxo was unconfirmed and + // originated from the sweeper subsystem. Now we confirm the + // to_remote sweep and expect the channel opening to work. + ht.MineBlocksAndAssertNumTxes(1, 1) + + // Try opening the channel with the same utxo (now confirmed) again. + update = ht.OpenChannelAssertPending(carol, dave, + lntest.OpenChannelParams{ + FundMax: true, + SpendUnconfirmed: true, + Outpoints: []*lnrpc.OutPoint{ + fundingUtxo.Outpoint, + }, + }) + + chanPoint3 := lntest.ChanPointFromPendingUpdate(update) + ht.AssertNumPendingOpenChannels(carol, 1) + ht.AssertNumPendingOpenChannels(dave, 1) + + // We expect chanPoint3 to confirm. + ht.MineBlocksAndAssertNumTxes(1, 1) + + // Force Close the channel and test the opening flow without preselected + // utxos. + // Before we tested the channel funding with a selected coin, now we + // want to make sure that our internal coin selection also adheres to + // the restictions of unstable utxos. + // We create the unconfirmed sweeper originating utxo just like before + // by force-closing a channel from dave's side. + ht.CloseChannelAssertPending(dave, chanPoint3, true) + ht.MineBlocksAndAssertNumTxes(1, 1) + + // Mine one block to trigger the sweep transaction. + ht.MineEmptyBlocks(1) + + // Wait for the to_remote sweep tx to show up in carol's wallet. + ht.AssertNumUTXOsUnconfirmed(carol, 1) + + // Calculate the maximum amount our wallet has for the channel funding + // so that we will use all utxos. + carolBalance := carol.RPC.WalletBalance() + + // Now calculate the fee for the channel opening transaction. We don't + // have to keep a channel reserve because we are using STATIC_REMOTE_KEY + // channels. + // NOTE: The TotalBalance includes the unconfirmed balance as well. + chanSize = btcutil.Amount(carolBalance.TotalBalance) - + fundingFee(2, false) + + // We are trying to open a channel with the maximum amount and expect it + // to fail because one of the utxos cannot be used because it is + // unstable. + expectedErr = fmt.Errorf("not enough witness outputs to create " + + "funding transaction") + + ht.OpenChannelAssertErr(carol, dave, + lntest.OpenChannelParams{ + Amt: chanSize, + SpendUnconfirmed: true, + CommitmentType: cType, + }, expectedErr) + + // Confirm the to_remote sweep utxo. + ht.MineBlocksAndAssertNumTxes(1, 1) + + ht.AssertNumUTXOsConfirmed(carol, 2) + + // Now after the sweep utxo is confirmed it is stable and can be used + // for channel openings again. + update = ht.OpenChannelAssertPending(carol, dave, + lntest.OpenChannelParams{ + Amt: chanSize, + SpendUnconfirmed: true, + CommitmentType: cType, + }) + chanPoint4 := lntest.ChanPointFromPendingUpdate(update) + + // Verify that both nodes know about the channel. + ht.AssertNumPendingOpenChannels(carol, 1) + ht.AssertNumPendingOpenChannels(dave, 1) + + ht.MineBlocksAndAssertNumTxes(1, 1) + + ht.CloseChannel(carol, chanPoint1) + ht.CloseChannel(carol, chanPoint4) +} diff --git a/itest/lnd_psbt_test.go b/itest/lnd_psbt_test.go index a3b5f757b..a6f15fd35 100644 --- a/itest/lnd_psbt_test.go +++ b/itest/lnd_psbt_test.go @@ -1592,3 +1592,321 @@ func testPsbtChanFundingFailFlow(ht *lntest.HarnessTest) { // funding workflow with an internal error. ht.ReceiveOpenChannelError(chanUpdates, chanfunding.ErrRemoteCanceled) } + +// testPsbtChanFundingWithUnstableUtxos tests that channel openings with +// unstable utxos, in this case in particular unconfirmed utxos still in use by +// the sweeper subsystem, are not considered when opening a channel. They bear +// the risk of being RBFed and are therefore not safe to open a channel with. +func testPsbtChanFundingWithUnstableUtxos(ht *lntest.HarnessTest) { + fundingAmt := btcutil.Amount(2_000_000) + + // First, we'll create two new nodes that we'll use to open channel + // between for this test. + carol := ht.NewNode("carol", nil) + dave := ht.NewNode("dave", nil) + ht.EnsureConnected(carol, dave) + + // Fund Carol's wallet with a confirmed utxo. + ht.FundCoins(fundingAmt, carol) + + ht.AssertNumUTXOs(carol, 1) + + // Now spend the coins to create an unconfirmed transaction. This is + // necessary to test also the neutrino behaviour. For neutrino nodes + // only unconfirmed transactions originating from this node will be + // recognized as unconfirmed. + req := &lnrpc.NewAddressRequest{Type: AddrTypeTaprootPubkey} + resp := carol.RPC.NewAddress(req) + + sendCoinsResp := carol.RPC.SendCoins(&lnrpc.SendCoinsRequest{ + Addr: resp.Address, + SendAll: true, + SatPerVbyte: 1, + }) + + walletUtxo := ht.AssertNumUTXOsUnconfirmed(carol, 1)[0] + require.EqualValues(ht, sendCoinsResp.Txid, walletUtxo.Outpoint.TxidStr) + + chanSize := btcutil.Amount(walletUtxo.AmountSat / 2) + + // We use STATIC_REMOTE_KEY channels to easily generate sweeps without + // anchor sweeps interfering. + cType := lnrpc.CommitmentType_STATIC_REMOTE_KEY + + // We open a normal channel so that we can force-close it and produce + // a sweeper originating utxo. + update := ht.OpenChannelAssertPending(carol, dave, + lntest.OpenChannelParams{ + Amt: chanSize, + SpendUnconfirmed: true, + }) + channelPoint := lntest.ChanPointFromPendingUpdate(update) + ht.MineBlocksAndAssertNumTxes(1, 2) + + // Now force close the channel by dave to generate a utxo which is + // swept by the sweeper. We have STATIC_REMOTE_KEY Channel Types. + ht.CloseChannelAssertPending(dave, channelPoint, true) + ht.MineBlocksAndAssertNumTxes(1, 1) + + // Mine one block to trigger the sweep transaction. + ht.MineEmptyBlocks(1) + + // We wait for the to_remote sweep tx. + ht.AssertNumUTXOsUnconfirmed(carol, 1) + + // We need the maximum funding amount to ensure we are opening the next + // channel with all available utxos. + carolBalance := carol.RPC.WalletBalance() + + // The max chan size needs to account for the fee opening the channel + // itself. + // NOTE: We need to always account for a change here, because their is + // an inaccurarcy in the backend code. + chanSize = btcutil.Amount(carolBalance.TotalBalance) - + fundingFee(2, true) + + // Now open a channel of this amount via a psbt workflow. + // At this point, we can begin our PSBT channel funding workflow. We'll + // start by generating a pending channel ID externally that will be used + // to track this new funding type. + pendingChanID := ht.Random32Bytes() + + // Now that we have the pending channel ID, Carol will open the channel + // by specifying a PSBT shim. We expect it to fail because we try to + // fund a channel with the maximum amount of our wallet, which also + // includes an unstable utxo originating from the sweeper. + chanUpdates, tempPsbt := ht.OpenChannelPsbt( + carol, dave, lntest.OpenChannelParams{ + Amt: chanSize, + FundingShim: &lnrpc.FundingShim{ + Shim: &lnrpc.FundingShim_PsbtShim{ + PsbtShim: &lnrpc.PsbtShim{ + PendingChanId: pendingChanID, + }, + }, + }, + CommitmentType: cType, + SpendUnconfirmed: true, + }, + ) + + fundReq := &walletrpc.FundPsbtRequest{ + Template: &walletrpc.FundPsbtRequest_Psbt{ + Psbt: tempPsbt, + }, + Fees: &walletrpc.FundPsbtRequest_SatPerVbyte{ + SatPerVbyte: 50, + }, + MinConfs: 0, + SpendUnconfirmed: true, + } + carol.RPC.FundPsbtAssertErr(fundReq) + + // We confirm the sweep transaction and make sure we see it as confirmed + // from the perspective of the underlying wallet. + ht.MineBlocksAndAssertNumTxes(1, 1) + + // We expect 2 confirmed utxos, the change of the prior successful + // channel opening and the confirmed to_remote output. + ht.AssertNumUTXOsConfirmed(carol, 2) + + // We fund the psbt request again and now all utxo are stable and can + // finally be used to fund the channel. + fundResp := carol.RPC.FundPsbt(fundReq) + + // We verify the psbt before finalizing it. + carol.RPC.FundingStateStep(&lnrpc.FundingTransitionMsg{ + Trigger: &lnrpc.FundingTransitionMsg_PsbtVerify{ + PsbtVerify: &lnrpc.FundingPsbtVerify{ + PendingChanId: pendingChanID, + FundedPsbt: fundResp.FundedPsbt, + }, + }, + }) + + // Now we'll ask Carol's wallet to sign the PSBT so we can finish the + // funding flow. + finalizeReq := &walletrpc.FinalizePsbtRequest{ + FundedPsbt: fundResp.FundedPsbt, + } + finalizeRes := carol.RPC.FinalizePsbt(finalizeReq) + + // We've signed our PSBT now, let's pass it to the intent again. + carol.RPC.FundingStateStep(&lnrpc.FundingTransitionMsg{ + Trigger: &lnrpc.FundingTransitionMsg_PsbtFinalize{ + PsbtFinalize: &lnrpc.FundingPsbtFinalize{ + PendingChanId: pendingChanID, + SignedPsbt: finalizeRes.SignedPsbt, + }, + }, + }) + + // Consume the "channel pending" update. This waits until the funding + // transaction was fully compiled. + updateResp := ht.ReceiveOpenChannelUpdate(chanUpdates) + upd, ok := updateResp.Update.(*lnrpc.OpenStatusUpdate_ChanPending) + require.True(ht, ok) + channelPoint2 := &lnrpc.ChannelPoint{ + FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{ + FundingTxidBytes: upd.ChanPending.Txid, + }, + OutputIndex: upd.ChanPending.OutputIndex, + } + + var finalTx wire.MsgTx + err := finalTx.Deserialize(bytes.NewReader(finalizeRes.RawFinalTx)) + require.NoError(ht, err) + + txHash := finalTx.TxHash() + block := ht.MineBlocksAndAssertNumTxes(1, 1)[0] + ht.Miner.AssertTxInBlock(block, &txHash) + + // Now we do the same but instead use preselected utxos to verify that + // these utxos respects the utxo restrictions on sweeper unconfirmed + // inputs as well. + + // Now force close the channel by dave to generate a utxo which is + // swept by the sweeper. We have STATIC_REMOTE_KEY Channel Types. + ht.CloseChannelAssertPending(dave, channelPoint2, true) + ht.MineBlocksAndAssertNumTxes(1, 1) + + // Mine one block to trigger the sweep transaction. + ht.MineEmptyBlocks(1) + + // We wait for the to_remote sweep tx of channelPoint2. + utxos := ht.AssertNumUTXOsUnconfirmed(carol, 1) + + // We need the maximum funding amount to ensure we are opening the next + // channel with all available utxos. + carolBalance = carol.RPC.WalletBalance() + + // The max chan size needs to account for the fee opening the channel + // itself. + // NOTE: We need to always account for a change here, because their is + // an inaccurarcy in the backend code calculating the fee of a 1 input + // one output transaction, it always account for a channge in that case + // as well. + chanSize = btcutil.Amount(carolBalance.TotalBalance) - + fundingFee(2, true) + + // Now open a channel of this amount via a psbt workflow. + // At this point, we can begin our PSBT channel funding workflow. We'll + // start by generating a pending channel ID externally that will be used + // to track this new funding type. + pendingChanID = ht.Random32Bytes() + + // Now that we have the pending channel ID, Carol will open the channel + // by specifying a PSBT shim. We expect it to fail because we try to + // fund a channel with the maximum amount of our wallet, which also + // includes an unstable utxo originating from the sweeper. + chanUpdates, tempPsbt = ht.OpenChannelPsbt( + carol, dave, lntest.OpenChannelParams{ + Amt: chanSize, + FundingShim: &lnrpc.FundingShim{ + Shim: &lnrpc.FundingShim_PsbtShim{ + PsbtShim: &lnrpc.PsbtShim{ + PendingChanId: pendingChanID, + }, + }, + }, + CommitmentType: cType, + SpendUnconfirmed: true, + }, + ) + // Add selected utxos to the funding intent. + decodedPsbt, err := psbt.NewFromRawBytes( + bytes.NewReader(tempPsbt), false, + ) + require.NoError(ht, err) + + for _, input := range utxos { + txHash, err := chainhash.NewHashFromStr(input.Outpoint.TxidStr) + require.NoError(ht, err) + decodedPsbt.UnsignedTx.TxIn = append( + decodedPsbt.UnsignedTx.TxIn, &wire.TxIn{ + PreviousOutPoint: wire.OutPoint{ + Hash: *txHash, + Index: input.Outpoint.OutputIndex, + }, + }) + + // The inputs we are using to fund the transaction are known to + // the internal wallet that's why we just append an empty input + // element so that the parsing of the psbt package succeeds. + decodedPsbt.Inputs = append(decodedPsbt.Inputs, psbt.PInput{}) + } + + var psbtBytes bytes.Buffer + err = decodedPsbt.Serialize(&psbtBytes) + require.NoError(ht, err) + + fundReq = &walletrpc.FundPsbtRequest{ + Template: &walletrpc.FundPsbtRequest_Psbt{ + Psbt: psbtBytes.Bytes(), + }, + Fees: &walletrpc.FundPsbtRequest_SatPerVbyte{ + SatPerVbyte: 50, + }, + MinConfs: 0, + SpendUnconfirmed: true, + } + carol.RPC.FundPsbtAssertErr(fundReq) + + ht.MineBlocksAndAssertNumTxes(1, 1) + + // We expect 2 confirmed utxos, the change of the last successful + // channel opening and the confirmed to_remote output of channelPoint2. + ht.AssertNumUTXOsConfirmed(carol, 2) + + // After the confirmation of the sweep to_remote output the funding + // will now proceed. + fundResp = carol.RPC.FundPsbt(fundReq) + + // We verify the funded psbt. + carol.RPC.FundingStateStep(&lnrpc.FundingTransitionMsg{ + Trigger: &lnrpc.FundingTransitionMsg_PsbtVerify{ + PsbtVerify: &lnrpc.FundingPsbtVerify{ + PendingChanId: pendingChanID, + FundedPsbt: fundResp.FundedPsbt, + }, + }, + }) + + // Now we'll ask Carol's wallet to sign the PSBT so we can finish the + // funding flow. + finalizeReq = &walletrpc.FinalizePsbtRequest{ + FundedPsbt: fundResp.FundedPsbt, + } + finalizeRes = carol.RPC.FinalizePsbt(finalizeReq) + + // We've signed our PSBT now, let's pass it to the intent again. + carol.RPC.FundingStateStep(&lnrpc.FundingTransitionMsg{ + Trigger: &lnrpc.FundingTransitionMsg_PsbtFinalize{ + PsbtFinalize: &lnrpc.FundingPsbtFinalize{ + PendingChanId: pendingChanID, + SignedPsbt: finalizeRes.SignedPsbt, + }, + }, + }) + + // Consume the "channel pending" update. This waits until the funding + // transaction was fully compiled. + updateResp = ht.ReceiveOpenChannelUpdate(chanUpdates) + upd, ok = updateResp.Update.(*lnrpc.OpenStatusUpdate_ChanPending) + require.True(ht, ok) + channelPoint3 := &lnrpc.ChannelPoint{ + FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{ + FundingTxidBytes: upd.ChanPending.Txid, + }, + OutputIndex: upd.ChanPending.OutputIndex, + } + + err = finalTx.Deserialize(bytes.NewReader(finalizeRes.RawFinalTx)) + require.NoError(ht, err) + + txHash = finalTx.TxHash() + block = ht.MineBlocksAndAssertNumTxes(1, 1)[0] + ht.Miner.AssertTxInBlock(block, &txHash) + + ht.CloseChannel(carol, channelPoint3) +} diff --git a/lntest/harness.go b/lntest/harness.go index c291e7cf3..5c2bef488 100644 --- a/lntest/harness.go +++ b/lntest/harness.go @@ -1205,6 +1205,7 @@ func (h *HarnessTest) OpenChannelAssertErr(srcNode, destNode *node.HarnessNode, // Receive an error to be sent from the stream. _, err := h.receiveOpenChannelUpdate(respStream) + require.NotNil(h, err, "expected channel opening to fail") // Use string comparison here as we haven't codified all the RPC errors // yet. diff --git a/lntest/rpc/wallet_kit.go b/lntest/rpc/wallet_kit.go index 79ccdcbdf..967679d66 100644 --- a/lntest/rpc/wallet_kit.go +++ b/lntest/rpc/wallet_kit.go @@ -68,6 +68,16 @@ func (h *HarnessRPC) FundPsbt( return resp } +// FundPsbtAssertErr makes a RPC call to the node's FundPsbt and asserts an +// error is returned. +func (h *HarnessRPC) FundPsbtAssertErr(req *walletrpc.FundPsbtRequest) { + ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout) + defer cancel() + + _, err := h.WalletKit.FundPsbt(ctxt, req) + require.Error(h, err, "expected error returned") +} + // FinalizePsbt makes a RPC call to node's FinalizePsbt and asserts. func (h *HarnessRPC) FinalizePsbt( req *walletrpc.FinalizePsbtRequest) *walletrpc.FinalizePsbtResponse { diff --git a/lnwallet/test/test_interface.go b/lnwallet/test/test_interface.go index 12b3aafc9..dd1db5f20 100644 --- a/lnwallet/test/test_interface.go +++ b/lnwallet/test/test_interface.go @@ -2947,6 +2947,11 @@ func waitForWalletSync(r *rpctest.Harness, w *lnwallet.LightningWallet) error { func testSingleFunderExternalFundingTx(miner *rpctest.Harness, alice, bob *lnwallet.LightningWallet, t *testing.T) { + // Define a filter function without any restrictions. + allowUtxo := func(lnwallet.Utxo) bool { + return true + } + // First, we'll obtain multi-sig keys from both Alice and Bob which // simulates them exchanging keys on a higher level. aliceFundingKey, err := alice.DeriveNextKey(keychain.KeyFamilyMultiSig) @@ -2964,7 +2969,7 @@ func testSingleFunderExternalFundingTx(miner *rpctest.Harness, aliceChanFunder := chanfunding.NewWalletAssembler( chanfunding.WalletConfig{ CoinSource: lnwallet.NewCoinSource( - alice, nil, + alice, allowUtxo, ), CoinSelectLocker: alice, CoinLeaser: alice, From 58e12884dc99b00b233ddeec3195ebc0cc470d57 Mon Sep 17 00:00:00 2001 From: ziggie Date: Sat, 30 Mar 2024 17:05:09 +0000 Subject: [PATCH 011/109] docs: add release-notes. --- docs/release-notes/release-notes-0.18.0.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/release-notes/release-notes-0.18.0.md b/docs/release-notes/release-notes-0.18.0.md index 955905354..f59ae179b 100644 --- a/docs/release-notes/release-notes-0.18.0.md +++ b/docs/release-notes/release-notes-0.18.0.md @@ -118,6 +118,14 @@ * [Fixed a bug in `btcd` that caused an incompatibility with `bitcoind v27.0`](https://github.com/lightningnetwork/lnd/pull/8573). + +* [Fixed](https://github.com/lightningnetwork/lnd/pull/8609) a function call + where arguments were swapped. + +* [Fixed](https://github.com/lightningnetwork/lnd/pull/8545) utxo selection + for the internal channel funding flow (Single and Batch Funding Flow). Now + utxos which are unconfirmed and originated from the sweeper subsystem are not + selected because they bear the risk of being replaced (BIP 125 RBF). # New Features ## Functional Enhancements From 64740e18cb9320fe6c49a9a7ea08b66a728eb465 Mon Sep 17 00:00:00 2001 From: zhiqiangxu <652732310@qq.com> Date: Wed, 27 Mar 2024 14:40:02 +0800 Subject: [PATCH 012/109] itest: fix ascii --- itest/lnd_mpp_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/itest/lnd_mpp_test.go b/itest/lnd_mpp_test.go index 960626500..bf2679846 100644 --- a/itest/lnd_mpp_test.go +++ b/itest/lnd_mpp_test.go @@ -248,8 +248,8 @@ type mppOpenChannelRequest struct { // openChannels is a helper to open channels that sets up a network topology // with three different paths Alice <-> Bob as following, // -// _ Eve _ -// / \ +// _ Eve _ +// / \ // Alice -- Carol ---- Bob // \ / // \__ Dave ____/ From 64601a9bbeefe004c821573d6398e507a73d98ca Mon Sep 17 00:00:00 2001 From: ziggie Date: Wed, 24 Apr 2024 16:49:14 +0100 Subject: [PATCH 013/109] wallet lncli: fix bumpfee parsing bug. --- cmd/lncli/walletrpc_active.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/cmd/lncli/walletrpc_active.go b/cmd/lncli/walletrpc_active.go index e9e5cc575..a79fc0065 100644 --- a/cmd/lncli/walletrpc_active.go +++ b/cmd/lncli/walletrpc_active.go @@ -272,10 +272,24 @@ func bumpFee(ctx *cli.Context) error { client, cleanUp := getWalletClient(ctx) defer cleanUp() + // Parse immediate flag (force flag was deprecated). + immediate := false + switch { + case ctx.IsSet("immediate") && ctx.IsSet("force"): + return fmt.Errorf("cannot set immediate and force flag at " + + "the same time") + + case ctx.Bool("immediate"): + immediate = true + + case ctx.Bool("force"): + immediate = true + } + resp, err := client.BumpFee(ctxc, &walletrpc.BumpFeeRequest{ Outpoint: protoOutPoint, TargetConf: uint32(ctx.Uint64("conf_target")), - Immediate: ctx.Bool("force"), + Immediate: immediate, Budget: ctx.Uint64("budget"), }) if err != nil { From 0ea45efe28b69315616edacc4a1faede908432f3 Mon Sep 17 00:00:00 2001 From: ziggie Date: Wed, 24 Apr 2024 16:51:34 +0100 Subject: [PATCH 014/109] docs: add release-notes. --- docs/release-notes/release-notes-0.18.0.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/release-notes/release-notes-0.18.0.md b/docs/release-notes/release-notes-0.18.0.md index f59ae179b..2add279b4 100644 --- a/docs/release-notes/release-notes-0.18.0.md +++ b/docs/release-notes/release-notes-0.18.0.md @@ -127,6 +127,9 @@ utxos which are unconfirmed and originated from the sweeper subsystem are not selected because they bear the risk of being replaced (BIP 125 RBF). +* [Fixed](https://github.com/lightningnetwork/lnd/pull/8685) lncli "bumpfee" + parsing of the immediate/force flag. + # New Features ## Functional Enhancements From 4f48cc69fb18c9eadd6109e5309db10f425a3cdb Mon Sep 17 00:00:00 2001 From: Mohamed Awnallah Date: Mon, 22 Apr 2024 01:48:58 +0200 Subject: [PATCH 015/109] lnrpc: add `all_payments` opt to DeleteAllPayments --- lnrpc/lightning.pb.go | 1876 +++++++++++++++++----------------- lnrpc/lightning.proto | 4 + lnrpc/lightning.swagger.json | 7 + 3 files changed, 955 insertions(+), 932 deletions(-) diff --git a/lnrpc/lightning.pb.go b/lnrpc/lightning.pb.go index 46badbe84..b2bc8034c 100644 --- a/lnrpc/lightning.pb.go +++ b/lnrpc/lightning.pb.go @@ -13895,6 +13895,9 @@ type DeleteAllPaymentsRequest struct { FailedPaymentsOnly bool `protobuf:"varint,1,opt,name=failed_payments_only,json=failedPaymentsOnly,proto3" json:"failed_payments_only,omitempty"` // Only delete failed HTLCs from payments, not the payment itself. FailedHtlcsOnly bool `protobuf:"varint,2,opt,name=failed_htlcs_only,json=failedHtlcsOnly,proto3" json:"failed_htlcs_only,omitempty"` + // Delete all payments. NOTE: Using this option requires careful + // consideration as it is a destructive operation. + AllPayments bool `protobuf:"varint,3,opt,name=all_payments,json=allPayments,proto3" json:"all_payments,omitempty"` } func (x *DeleteAllPaymentsRequest) Reset() { @@ -13943,6 +13946,13 @@ func (x *DeleteAllPaymentsRequest) GetFailedHtlcsOnly() bool { return false } +func (x *DeleteAllPaymentsRequest) GetAllPayments() bool { + if x != nil { + return x.AllPayments + } + return false +} + type DeletePaymentResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -20083,948 +20093,950 @@ var file_lightning_proto_rawDesc = []byte{ 0x28, 0x0c, 0x52, 0x0b, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x2a, 0x0a, 0x11, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x5f, 0x68, 0x74, 0x6c, 0x63, 0x73, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x66, 0x61, 0x69, 0x6c, - 0x65, 0x64, 0x48, 0x74, 0x6c, 0x63, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x78, 0x0a, 0x18, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x14, 0x66, 0x61, 0x69, 0x6c, 0x65, - 0x64, 0x5f, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x50, 0x61, 0x79, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x66, 0x61, 0x69, - 0x6c, 0x65, 0x64, 0x5f, 0x68, 0x74, 0x6c, 0x63, 0x73, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x48, 0x74, 0x6c, 0x63, - 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x17, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, - 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, - 0x0a, 0x19, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xbf, 0x01, 0x0a, 0x15, - 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0d, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, - 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6c, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x69, 0x6e, - 0x74, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, - 0x39, 0x0a, 0x19, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x75, 0x6e, 0x64, 0x69, - 0x6e, 0x67, 0x5f, 0x73, 0x68, 0x69, 0x6d, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x16, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x46, 0x75, 0x6e, 0x64, 0x69, - 0x6e, 0x67, 0x53, 0x68, 0x69, 0x6d, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x31, 0x0a, 0x16, 0x69, 0x5f, - 0x6b, 0x6e, 0x6f, 0x77, 0x5f, 0x77, 0x68, 0x61, 0x74, 0x5f, 0x69, 0x5f, 0x61, 0x6d, 0x5f, 0x64, - 0x6f, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x69, 0x4b, 0x6e, 0x6f, - 0x77, 0x57, 0x68, 0x61, 0x74, 0x49, 0x41, 0x6d, 0x44, 0x6f, 0x69, 0x6e, 0x67, 0x22, 0x18, 0x0a, - 0x16, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x46, 0x0a, 0x11, 0x44, 0x65, 0x62, 0x75, 0x67, - 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, - 0x73, 0x68, 0x6f, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x73, 0x68, 0x6f, 0x77, - 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x53, 0x70, 0x65, 0x63, 0x22, - 0x35, 0x0a, 0x12, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x75, 0x62, 0x5f, 0x73, 0x79, 0x73, - 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x75, 0x62, 0x53, - 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x22, 0x27, 0x0a, 0x0c, 0x50, 0x61, 0x79, 0x52, 0x65, 0x71, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x5f, 0x72, 0x65, - 0x71, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x61, 0x79, 0x52, 0x65, 0x71, 0x22, - 0xb0, 0x04, 0x0a, 0x06, 0x50, 0x61, 0x79, 0x52, 0x65, 0x71, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, - 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, - 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, - 0x21, 0x0a, 0x0c, 0x6e, 0x75, 0x6d, 0x5f, 0x73, 0x61, 0x74, 0x6f, 0x73, 0x68, 0x69, 0x73, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x6e, 0x75, 0x6d, 0x53, 0x61, 0x74, 0x6f, 0x73, 0x68, - 0x69, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x12, 0x16, 0x0a, 0x06, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x06, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x48, 0x61, 0x73, 0x68, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, - 0x6b, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x66, 0x61, - 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, - 0x74, 0x76, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0a, 0x63, 0x6c, 0x74, 0x76, 0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x12, 0x31, 0x0a, 0x0b, 0x72, - 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x68, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x10, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x48, 0x69, - 0x6e, 0x74, 0x52, 0x0a, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x48, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x21, - 0x0a, 0x0c, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x0b, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x41, 0x64, 0x64, - 0x72, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x75, 0x6d, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x0c, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x07, 0x6e, 0x75, 0x6d, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x37, 0x0a, 0x08, - 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, 0x79, 0x52, 0x65, 0x71, 0x2e, 0x46, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x66, 0x65, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x73, 0x1a, 0x4b, 0x0a, 0x0d, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x24, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x22, 0x59, 0x0a, 0x07, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x73, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, - 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x22, 0x12, 0x0a, - 0x10, 0x46, 0x65, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x22, 0x95, 0x02, 0x0a, 0x10, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x46, 0x65, 0x65, - 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1b, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x30, 0x01, 0x52, 0x06, 0x63, 0x68, 0x61, - 0x6e, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x6e, - 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x62, 0x61, 0x73, 0x65, - 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0b, 0x62, 0x61, 0x73, 0x65, 0x46, 0x65, 0x65, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x1e, 0x0a, 0x0b, - 0x66, 0x65, 0x65, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x6d, 0x69, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x09, 0x66, 0x65, 0x65, 0x50, 0x65, 0x72, 0x4d, 0x69, 0x6c, 0x12, 0x19, 0x0a, 0x08, - 0x66, 0x65, 0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x07, - 0x66, 0x65, 0x65, 0x52, 0x61, 0x74, 0x65, 0x12, 0x31, 0x0a, 0x15, 0x69, 0x6e, 0x62, 0x6f, 0x75, - 0x6e, 0x64, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x6d, 0x73, 0x61, 0x74, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x42, - 0x61, 0x73, 0x65, 0x46, 0x65, 0x65, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x2d, 0x0a, 0x13, 0x69, 0x6e, - 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x6d, 0x69, - 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, - 0x46, 0x65, 0x65, 0x50, 0x65, 0x72, 0x4d, 0x69, 0x6c, 0x22, 0xb5, 0x01, 0x0a, 0x11, 0x46, 0x65, - 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x3a, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x65, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, - 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x46, 0x65, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x0b, - 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x46, 0x65, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x64, - 0x61, 0x79, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x09, 0x64, 0x61, 0x79, 0x46, 0x65, 0x65, 0x53, 0x75, 0x6d, 0x12, 0x20, 0x0a, 0x0c, 0x77, - 0x65, 0x65, 0x6b, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x0a, 0x77, 0x65, 0x65, 0x6b, 0x46, 0x65, 0x65, 0x53, 0x75, 0x6d, 0x12, 0x22, 0x0a, - 0x0d, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x46, 0x65, 0x65, 0x53, 0x75, - 0x6d, 0x22, 0xda, 0x03, 0x0a, 0x13, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x06, 0x67, 0x6c, 0x6f, - 0x62, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x06, 0x67, 0x6c, 0x6f, - 0x62, 0x61, 0x6c, 0x12, 0x34, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x09, - 0x63, 0x68, 0x61, 0x6e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x62, 0x61, 0x73, - 0x65, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x0b, 0x62, 0x61, 0x73, 0x65, 0x46, 0x65, 0x65, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x19, 0x0a, - 0x08, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, - 0x07, 0x66, 0x65, 0x65, 0x52, 0x61, 0x74, 0x65, 0x12, 0x20, 0x0a, 0x0c, 0x66, 0x65, 0x65, 0x5f, - 0x72, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x70, 0x6d, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, - 0x66, 0x65, 0x65, 0x52, 0x61, 0x74, 0x65, 0x50, 0x70, 0x6d, 0x12, 0x26, 0x0a, 0x0f, 0x74, 0x69, - 0x6d, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x74, 0x69, 0x6d, 0x65, 0x4c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6c, - 0x74, 0x61, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x68, 0x74, 0x6c, 0x63, 0x5f, 0x6d, - 0x73, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x48, 0x74, - 0x6c, 0x63, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x69, 0x6e, 0x5f, 0x68, 0x74, - 0x6c, 0x63, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, - 0x69, 0x6e, 0x48, 0x74, 0x6c, 0x63, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x35, 0x0a, 0x17, 0x6d, 0x69, - 0x6e, 0x5f, 0x68, 0x74, 0x6c, 0x63, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x5f, 0x73, 0x70, 0x65, 0x63, - 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x6d, 0x69, 0x6e, - 0x48, 0x74, 0x6c, 0x63, 0x4d, 0x73, 0x61, 0x74, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, - 0x64, 0x12, 0x31, 0x0a, 0x15, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x62, 0x61, 0x73, - 0x65, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x12, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x61, 0x73, 0x65, 0x46, 0x65, 0x65, - 0x4d, 0x73, 0x61, 0x74, 0x12, 0x2f, 0x0a, 0x14, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, - 0x66, 0x65, 0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x70, 0x6d, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x11, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x65, 0x65, 0x52, 0x61, - 0x74, 0x65, 0x50, 0x70, 0x6d, 0x42, 0x07, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x22, 0x8c, - 0x01, 0x0a, 0x0c, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, - 0x2b, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x0f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, - 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x06, - 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x6c, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, 0x61, 0x69, 0x6c, 0x75, - 0x72, 0x65, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x75, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x52, 0x0a, - 0x14, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x0e, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x5f, - 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x52, 0x0d, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x73, 0x22, 0xc9, 0x01, 0x0a, 0x18, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, - 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, - 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x19, 0x0a, - 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x07, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x64, 0x65, - 0x78, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x6e, - 0x75, 0x6d, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6e, 0x75, 0x6d, 0x4d, 0x61, 0x78, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x5f, - 0x6c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x70, 0x65, - 0x65, 0x72, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x22, 0x85, 0x03, - 0x0a, 0x0f, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x12, 0x20, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x18, 0x01, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x12, 0x20, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x5f, 0x69, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x30, 0x01, 0x52, 0x08, 0x63, 0x68, 0x61, - 0x6e, 0x49, 0x64, 0x49, 0x6e, 0x12, 0x22, 0x0a, 0x0b, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x69, 0x64, - 0x5f, 0x6f, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x30, 0x01, 0x52, 0x09, - 0x63, 0x68, 0x61, 0x6e, 0x49, 0x64, 0x4f, 0x75, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x6d, 0x74, - 0x5f, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x61, 0x6d, 0x74, 0x49, 0x6e, - 0x12, 0x17, 0x0a, 0x07, 0x61, 0x6d, 0x74, 0x5f, 0x6f, 0x75, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x06, 0x61, 0x6d, 0x74, 0x4f, 0x75, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x65, 0x65, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x66, 0x65, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x66, - 0x65, 0x65, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x66, - 0x65, 0x65, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x1e, 0x0a, 0x0b, 0x61, 0x6d, 0x74, 0x5f, 0x69, 0x6e, - 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x61, 0x6d, 0x74, - 0x49, 0x6e, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x20, 0x0a, 0x0c, 0x61, 0x6d, 0x74, 0x5f, 0x6f, 0x75, - 0x74, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x61, 0x6d, - 0x74, 0x4f, 0x75, 0x74, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x6e, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, - 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4e, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x70, - 0x65, 0x65, 0x72, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x5f, 0x69, 0x6e, 0x18, 0x0c, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x70, 0x65, 0x65, 0x72, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x49, 0x6e, 0x12, - 0x24, 0x0a, 0x0e, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x5f, 0x6f, 0x75, - 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x65, 0x65, 0x72, 0x41, 0x6c, 0x69, - 0x61, 0x73, 0x4f, 0x75, 0x74, 0x22, 0x8c, 0x01, 0x0a, 0x19, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, - 0x64, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x11, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, - 0x67, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, - 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x10, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, - 0x6e, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, - 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x49, - 0x6e, 0x64, 0x65, 0x78, 0x22, 0x50, 0x0a, 0x1a, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x68, - 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x32, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, - 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x09, 0x63, 0x68, 0x61, - 0x6e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x22, 0x64, 0x0a, 0x0d, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, - 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x32, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x5f, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6c, 0x6e, + 0x65, 0x64, 0x48, 0x74, 0x6c, 0x63, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x9b, 0x01, 0x0a, 0x18, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x14, 0x66, 0x61, 0x69, 0x6c, + 0x65, 0x64, 0x5f, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x50, 0x61, + 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x66, 0x61, + 0x69, 0x6c, 0x65, 0x64, 0x5f, 0x68, 0x74, 0x6c, 0x63, 0x73, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x48, 0x74, 0x6c, + 0x63, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x6c, 0x6c, 0x5f, 0x70, 0x61, + 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x61, 0x6c, + 0x6c, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x17, 0x0a, 0x15, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x1b, 0x0a, 0x19, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x50, + 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0xbf, 0x01, 0x0a, 0x15, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, + 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0d, 0x63, 0x68, 0x61, + 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, + 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, + 0x69, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x19, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x66, + 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x68, 0x69, 0x6d, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x46, + 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x68, 0x69, 0x6d, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x31, + 0x0a, 0x16, 0x69, 0x5f, 0x6b, 0x6e, 0x6f, 0x77, 0x5f, 0x77, 0x68, 0x61, 0x74, 0x5f, 0x69, 0x5f, + 0x61, 0x6d, 0x5f, 0x64, 0x6f, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, + 0x69, 0x4b, 0x6e, 0x6f, 0x77, 0x57, 0x68, 0x61, 0x74, 0x49, 0x41, 0x6d, 0x44, 0x6f, 0x69, 0x6e, + 0x67, 0x22, 0x18, 0x0a, 0x16, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, + 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x46, 0x0a, 0x11, 0x44, + 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x12, 0x0a, 0x04, 0x73, 0x68, 0x6f, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, + 0x73, 0x68, 0x6f, 0x77, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x5f, 0x73, 0x70, + 0x65, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x53, + 0x70, 0x65, 0x63, 0x22, 0x35, 0x0a, 0x12, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, + 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x75, 0x62, + 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x73, 0x75, 0x62, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x22, 0x27, 0x0a, 0x0c, 0x50, 0x61, + 0x79, 0x52, 0x65, 0x71, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x61, + 0x79, 0x5f, 0x72, 0x65, 0x71, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x61, 0x79, + 0x52, 0x65, 0x71, 0x22, 0xb0, 0x04, 0x0a, 0x06, 0x50, 0x61, 0x79, 0x52, 0x65, 0x71, 0x12, 0x20, + 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73, 0x68, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, + 0x61, 0x73, 0x68, 0x12, 0x21, 0x0a, 0x0c, 0x6e, 0x75, 0x6d, 0x5f, 0x73, 0x61, 0x74, 0x6f, 0x73, + 0x68, 0x69, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x6e, 0x75, 0x6d, 0x53, 0x61, + 0x74, 0x6f, 0x73, 0x68, 0x69, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x12, 0x20, 0x0a, 0x0b, + 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, + 0x0a, 0x10, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x61, + 0x73, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x61, 0x73, 0x68, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x61, 0x6c, + 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0c, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x12, 0x1f, + 0x0a, 0x0b, 0x63, 0x6c, 0x74, 0x76, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x18, 0x09, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, 0x6c, 0x74, 0x76, 0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x12, + 0x31, 0x0a, 0x0b, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x68, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x0a, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x6f, 0x75, + 0x74, 0x65, 0x48, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x48, 0x69, 0x6e, + 0x74, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x64, + 0x64, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, + 0x74, 0x41, 0x64, 0x64, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x75, 0x6d, 0x5f, 0x6d, 0x73, 0x61, + 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6e, 0x75, 0x6d, 0x4d, 0x73, 0x61, 0x74, + 0x12, 0x37, 0x0a, 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x0d, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, 0x79, 0x52, 0x65, + 0x71, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x08, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x1a, 0x4b, 0x0a, 0x0d, 0x46, 0x65, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x24, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x59, 0x0a, 0x07, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x73, 0x5f, 0x72, 0x65, 0x71, 0x75, + 0x69, 0x72, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x6b, 0x6e, 0x6f, + 0x77, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x4b, 0x6e, 0x6f, 0x77, + 0x6e, 0x22, 0x12, 0x0a, 0x10, 0x46, 0x65, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x95, 0x02, 0x0a, 0x10, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, + 0x6c, 0x46, 0x65, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1b, 0x0a, 0x07, 0x63, 0x68, + 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x30, 0x01, 0x52, + 0x06, 0x63, 0x68, 0x61, 0x6e, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x68, 0x61, 0x6e, 0x6e, + 0x65, 0x6c, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, + 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x22, 0x0a, 0x0d, + 0x62, 0x61, 0x73, 0x65, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0b, 0x62, 0x61, 0x73, 0x65, 0x46, 0x65, 0x65, 0x4d, 0x73, 0x61, 0x74, + 0x12, 0x1e, 0x0a, 0x0b, 0x66, 0x65, 0x65, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x6d, 0x69, 0x6c, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x66, 0x65, 0x65, 0x50, 0x65, 0x72, 0x4d, 0x69, 0x6c, + 0x12, 0x19, 0x0a, 0x08, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x01, 0x52, 0x07, 0x66, 0x65, 0x65, 0x52, 0x61, 0x74, 0x65, 0x12, 0x31, 0x0a, 0x15, 0x69, + 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x66, 0x65, 0x65, 0x5f, + 0x6d, 0x73, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x69, 0x6e, 0x62, 0x6f, + 0x75, 0x6e, 0x64, 0x42, 0x61, 0x73, 0x65, 0x46, 0x65, 0x65, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x2d, + 0x0a, 0x13, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x70, 0x65, + 0x72, 0x5f, 0x6d, 0x69, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x69, 0x6e, 0x62, + 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x65, 0x65, 0x50, 0x65, 0x72, 0x4d, 0x69, 0x6c, 0x22, 0xb5, 0x01, + 0x0a, 0x11, 0x46, 0x65, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x66, + 0x65, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6c, 0x6e, 0x72, 0x70, + 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x46, 0x65, 0x65, 0x52, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x52, 0x0b, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x46, 0x65, 0x65, 0x73, 0x12, + 0x1e, 0x0a, 0x0b, 0x64, 0x61, 0x79, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x64, 0x61, 0x79, 0x46, 0x65, 0x65, 0x53, 0x75, 0x6d, 0x12, + 0x20, 0x0a, 0x0c, 0x77, 0x65, 0x65, 0x6b, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x77, 0x65, 0x65, 0x6b, 0x46, 0x65, 0x65, 0x53, 0x75, + 0x6d, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x73, + 0x75, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x46, + 0x65, 0x65, 0x53, 0x75, 0x6d, 0x22, 0xda, 0x03, 0x0a, 0x13, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, + 0x06, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, + 0x06, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x12, 0x34, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x5f, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x69, 0x6e, 0x74, - 0x52, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, - 0x68, 0x61, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x22, 0x73, 0x0a, 0x0f, - 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, - 0x34, 0x0a, 0x0b, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, - 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x50, - 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x5f, 0x63, - 0x68, 0x61, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, - 0x70, 0x22, 0x19, 0x0a, 0x17, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x45, - 0x78, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x9f, 0x01, 0x0a, - 0x12, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, 0x6e, 0x61, 0x70, 0x73, - 0x68, 0x6f, 0x74, 0x12, 0x45, 0x0a, 0x13, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x5f, 0x63, 0x68, + 0x48, 0x00, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x22, 0x0a, + 0x0d, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x62, 0x61, 0x73, 0x65, 0x46, 0x65, 0x65, 0x4d, 0x73, 0x61, + 0x74, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x01, 0x52, 0x07, 0x66, 0x65, 0x65, 0x52, 0x61, 0x74, 0x65, 0x12, 0x20, 0x0a, 0x0c, + 0x66, 0x65, 0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x70, 0x6d, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x0a, 0x66, 0x65, 0x65, 0x52, 0x61, 0x74, 0x65, 0x50, 0x70, 0x6d, 0x12, 0x26, + 0x0a, 0x0f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x64, 0x65, 0x6c, 0x74, + 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x74, 0x69, 0x6d, 0x65, 0x4c, 0x6f, 0x63, + 0x6b, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x68, 0x74, + 0x6c, 0x63, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, + 0x61, 0x78, 0x48, 0x74, 0x6c, 0x63, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x69, + 0x6e, 0x5f, 0x68, 0x74, 0x6c, 0x63, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x0b, 0x6d, 0x69, 0x6e, 0x48, 0x74, 0x6c, 0x63, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x35, + 0x0a, 0x17, 0x6d, 0x69, 0x6e, 0x5f, 0x68, 0x74, 0x6c, 0x63, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x5f, + 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x14, 0x6d, 0x69, 0x6e, 0x48, 0x74, 0x6c, 0x63, 0x4d, 0x73, 0x61, 0x74, 0x53, 0x70, 0x65, 0x63, + 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x31, 0x0a, 0x15, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, + 0x5f, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x61, 0x73, + 0x65, 0x46, 0x65, 0x65, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x2f, 0x0a, 0x14, 0x69, 0x6e, 0x62, 0x6f, + 0x75, 0x6e, 0x64, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x70, 0x6d, + 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x46, + 0x65, 0x65, 0x52, 0x61, 0x74, 0x65, 0x50, 0x70, 0x6d, 0x42, 0x07, 0x0a, 0x05, 0x73, 0x63, 0x6f, + 0x70, 0x65, 0x22, 0x8c, 0x01, 0x0a, 0x0c, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x12, 0x2b, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x75, + 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x12, 0x2c, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x14, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, + 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x21, + 0x0a, 0x0c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x72, 0x72, 0x6f, + 0x72, 0x22, 0x52, 0x0a, 0x14, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x0e, 0x66, 0x61, 0x69, + 0x6c, 0x65, 0x64, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x73, 0x22, 0xc9, 0x01, 0x0a, 0x18, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, + 0x64, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, + 0x65, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, + 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x0b, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, + 0x24, 0x0a, 0x0e, 0x6e, 0x75, 0x6d, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6e, 0x75, 0x6d, 0x4d, 0x61, 0x78, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x61, 0x6c, + 0x69, 0x61, 0x73, 0x5f, 0x6c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0f, 0x70, 0x65, 0x65, 0x72, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, + 0x70, 0x22, 0x85, 0x03, 0x0a, 0x0f, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x20, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x18, 0x01, 0x52, 0x09, 0x74, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x20, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x5f, + 0x69, 0x64, 0x5f, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x30, 0x01, 0x52, + 0x08, 0x63, 0x68, 0x61, 0x6e, 0x49, 0x64, 0x49, 0x6e, 0x12, 0x22, 0x0a, 0x0b, 0x63, 0x68, 0x61, + 0x6e, 0x5f, 0x69, 0x64, 0x5f, 0x6f, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, + 0x30, 0x01, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x49, 0x64, 0x4f, 0x75, 0x74, 0x12, 0x15, 0x0a, + 0x06, 0x61, 0x6d, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x61, + 0x6d, 0x74, 0x49, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x61, 0x6d, 0x74, 0x5f, 0x6f, 0x75, 0x74, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x74, 0x4f, 0x75, 0x74, 0x12, 0x10, 0x0a, + 0x03, 0x66, 0x65, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x66, 0x65, 0x65, 0x12, + 0x19, 0x0a, 0x08, 0x66, 0x65, 0x65, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x07, 0x66, 0x65, 0x65, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x1e, 0x0a, 0x0b, 0x61, 0x6d, + 0x74, 0x5f, 0x69, 0x6e, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x09, 0x61, 0x6d, 0x74, 0x49, 0x6e, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x20, 0x0a, 0x0c, 0x61, 0x6d, + 0x74, 0x5f, 0x6f, 0x75, 0x74, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x0a, 0x61, 0x6d, 0x74, 0x4f, 0x75, 0x74, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x21, 0x0a, 0x0c, + 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x6e, 0x73, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4e, 0x73, 0x12, + 0x22, 0x0a, 0x0d, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x5f, 0x69, 0x6e, + 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x65, 0x65, 0x72, 0x41, 0x6c, 0x69, 0x61, + 0x73, 0x49, 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x61, 0x6c, 0x69, 0x61, + 0x73, 0x5f, 0x6f, 0x75, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x65, 0x65, + 0x72, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4f, 0x75, 0x74, 0x22, 0x8c, 0x01, 0x0a, 0x19, 0x46, 0x6f, + 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x11, 0x66, 0x6f, 0x72, 0x77, 0x61, + 0x72, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, 0x77, 0x61, + 0x72, 0x64, 0x69, 0x6e, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x10, 0x66, 0x6f, 0x72, 0x77, + 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, + 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, + 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x4f, 0x66, 0x66, + 0x73, 0x65, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x50, 0x0a, 0x1a, 0x45, 0x78, 0x70, 0x6f, + 0x72, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x32, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6c, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, + 0x09, 0x63, 0x68, 0x61, 0x6e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x22, 0x64, 0x0a, 0x0d, 0x43, 0x68, + 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x32, 0x0a, 0x0a, 0x63, + 0x68, 0x61, 0x6e, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, + 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, + 0x1f, 0x0a, 0x0b, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, + 0x22, 0x73, 0x0a, 0x0f, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, + 0x6b, 0x75, 0x70, 0x12, 0x34, 0x0a, 0x0b, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, + 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x63, + 0x68, 0x61, 0x6e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x75, 0x6c, + 0x74, 0x69, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x43, 0x68, 0x61, 0x6e, 0x42, + 0x61, 0x63, 0x6b, 0x75, 0x70, 0x22, 0x19, 0x0a, 0x17, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, + 0x6b, 0x75, 0x70, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x22, 0x9f, 0x01, 0x0a, 0x12, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, + 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x45, 0x0a, 0x13, 0x73, 0x69, 0x6e, 0x67, 0x6c, + 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, + 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x52, 0x11, 0x73, 0x69, 0x6e, + 0x67, 0x6c, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12, 0x42, + 0x0a, 0x11, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x62, 0x61, 0x63, + 0x6b, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, + 0x63, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, + 0x70, 0x52, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, + 0x75, 0x70, 0x22, 0x49, 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, + 0x6b, 0x75, 0x70, 0x73, 0x12, 0x37, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x62, 0x61, 0x63, + 0x6b, 0x75, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6c, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, + 0x52, 0x0b, 0x63, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x22, 0x8e, 0x01, + 0x0a, 0x18, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, + 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, - 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x52, 0x11, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x43, - 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12, 0x42, 0x0a, 0x11, 0x6d, 0x75, - 0x6c, 0x74, 0x69, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x75, - 0x6c, 0x74, 0x69, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x0f, 0x6d, - 0x75, 0x6c, 0x74, 0x69, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x22, 0x49, - 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, - 0x12, 0x37, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, - 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x0b, 0x63, 0x68, - 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x22, 0x8e, 0x01, 0x0a, 0x18, 0x52, 0x65, - 0x73, 0x74, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x62, - 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6c, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, - 0x75, 0x70, 0x73, 0x48, 0x00, 0x52, 0x0b, 0x63, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, - 0x70, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x5f, 0x63, 0x68, 0x61, 0x6e, - 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, - 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, - 0x42, 0x08, 0x0a, 0x06, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x22, 0x17, 0x0a, 0x15, 0x52, 0x65, - 0x73, 0x74, 0x6f, 0x72, 0x65, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x0a, 0x19, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, - 0x63, 0x6b, 0x75, 0x70, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x22, 0x1a, 0x0a, 0x18, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, - 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x44, 0x0a, 0x12, - 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x22, 0xb0, 0x01, 0x0a, 0x13, 0x42, 0x61, 0x6b, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, - 0x6f, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3b, 0x0a, 0x0b, 0x70, 0x65, - 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, - 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, - 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x72, 0x6f, 0x6f, 0x74, 0x5f, - 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x72, 0x6f, - 0x6f, 0x74, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x12, 0x3c, 0x0a, 0x1a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, - 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x61, 0x6c, 0x6c, - 0x6f, 0x77, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x32, 0x0a, 0x14, 0x42, 0x61, 0x6b, 0x65, 0x4d, 0x61, 0x63, - 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, - 0x08, 0x6d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x6d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x22, 0x18, 0x0a, 0x16, 0x4c, 0x69, 0x73, - 0x74, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x22, 0x3b, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x61, 0x72, - 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, - 0x0a, 0x0c, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x04, 0x52, 0x0a, 0x72, 0x6f, 0x6f, 0x74, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x73, - 0x22, 0x39, 0x0a, 0x17, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, - 0x6f, 0x6e, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x0b, 0x72, - 0x6f, 0x6f, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x22, 0x34, 0x0a, 0x18, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x64, 0x22, 0x55, 0x0a, 0x16, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x50, 0x65, 0x72, - 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x3b, 0x0a, 0x0b, 0x70, - 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, - 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x70, 0x65, 0x72, - 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x18, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, - 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x22, 0xe4, 0x01, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, 0x69, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x64, - 0x0a, 0x12, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, - 0x64, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x11, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x63, 0x0a, 0x16, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x50, 0x65, - 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x12, 0x33, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, - 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xcc, 0x08, 0x0a, 0x07, 0x46, 0x61, - 0x69, 0x6c, 0x75, 0x72, 0x65, 0x12, 0x2e, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x61, 0x69, 0x6c, - 0x75, 0x72, 0x65, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x52, - 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x3b, 0x0a, 0x0e, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, - 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x52, 0x0d, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x68, 0x74, 0x6c, 0x63, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x68, 0x74, 0x6c, 0x63, 0x4d, 0x73, 0x61, 0x74, 0x12, - 0x22, 0x0a, 0x0d, 0x6f, 0x6e, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x68, 0x61, 0x5f, 0x32, 0x35, 0x36, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x6f, 0x6e, 0x69, 0x6f, 0x6e, 0x53, 0x68, 0x61, - 0x32, 0x35, 0x36, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x74, 0x76, 0x5f, 0x65, 0x78, 0x70, 0x69, - 0x72, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x63, 0x6c, 0x74, 0x76, 0x45, 0x78, - 0x70, 0x69, 0x72, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x66, 0x61, - 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, - 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x16, 0x0a, 0x06, - 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x68, 0x65, - 0x69, 0x67, 0x68, 0x74, 0x22, 0x8b, 0x06, 0x0a, 0x0b, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, - 0x43, 0x6f, 0x64, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x53, 0x45, 0x52, 0x56, 0x45, 0x44, - 0x10, 0x00, 0x12, 0x28, 0x0a, 0x24, 0x49, 0x4e, 0x43, 0x4f, 0x52, 0x52, 0x45, 0x43, 0x54, 0x5f, - 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x50, 0x41, 0x59, 0x4d, 0x45, - 0x4e, 0x54, 0x5f, 0x44, 0x45, 0x54, 0x41, 0x49, 0x4c, 0x53, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, - 0x49, 0x4e, 0x43, 0x4f, 0x52, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x50, 0x41, 0x59, 0x4d, 0x45, 0x4e, - 0x54, 0x5f, 0x41, 0x4d, 0x4f, 0x55, 0x4e, 0x54, 0x10, 0x02, 0x12, 0x1f, 0x0a, 0x1b, 0x46, 0x49, - 0x4e, 0x41, 0x4c, 0x5f, 0x49, 0x4e, 0x43, 0x4f, 0x52, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x43, 0x4c, - 0x54, 0x56, 0x5f, 0x45, 0x58, 0x50, 0x49, 0x52, 0x59, 0x10, 0x03, 0x12, 0x1f, 0x0a, 0x1b, 0x46, - 0x49, 0x4e, 0x41, 0x4c, 0x5f, 0x49, 0x4e, 0x43, 0x4f, 0x52, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x48, - 0x54, 0x4c, 0x43, 0x5f, 0x41, 0x4d, 0x4f, 0x55, 0x4e, 0x54, 0x10, 0x04, 0x12, 0x19, 0x0a, 0x15, - 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x5f, 0x45, 0x58, 0x50, 0x49, 0x52, 0x59, 0x5f, 0x54, 0x4f, 0x4f, - 0x5f, 0x53, 0x4f, 0x4f, 0x4e, 0x10, 0x05, 0x12, 0x11, 0x0a, 0x0d, 0x49, 0x4e, 0x56, 0x41, 0x4c, - 0x49, 0x44, 0x5f, 0x52, 0x45, 0x41, 0x4c, 0x4d, 0x10, 0x06, 0x12, 0x13, 0x0a, 0x0f, 0x45, 0x58, - 0x50, 0x49, 0x52, 0x59, 0x5f, 0x54, 0x4f, 0x4f, 0x5f, 0x53, 0x4f, 0x4f, 0x4e, 0x10, 0x07, 0x12, - 0x19, 0x0a, 0x15, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x4f, 0x4e, 0x49, 0x4f, 0x4e, - 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x10, 0x08, 0x12, 0x16, 0x0a, 0x12, 0x49, 0x4e, - 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x4f, 0x4e, 0x49, 0x4f, 0x4e, 0x5f, 0x48, 0x4d, 0x41, 0x43, - 0x10, 0x09, 0x12, 0x15, 0x0a, 0x11, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x4f, 0x4e, - 0x49, 0x4f, 0x4e, 0x5f, 0x4b, 0x45, 0x59, 0x10, 0x0a, 0x12, 0x18, 0x0a, 0x14, 0x41, 0x4d, 0x4f, - 0x55, 0x4e, 0x54, 0x5f, 0x42, 0x45, 0x4c, 0x4f, 0x57, 0x5f, 0x4d, 0x49, 0x4e, 0x49, 0x4d, 0x55, - 0x4d, 0x10, 0x0b, 0x12, 0x14, 0x0a, 0x10, 0x46, 0x45, 0x45, 0x5f, 0x49, 0x4e, 0x53, 0x55, 0x46, - 0x46, 0x49, 0x43, 0x49, 0x45, 0x4e, 0x54, 0x10, 0x0c, 0x12, 0x19, 0x0a, 0x15, 0x49, 0x4e, 0x43, - 0x4f, 0x52, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x43, 0x4c, 0x54, 0x56, 0x5f, 0x45, 0x58, 0x50, 0x49, - 0x52, 0x59, 0x10, 0x0d, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x5f, - 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x0e, 0x12, 0x1d, 0x0a, 0x19, 0x54, 0x45, - 0x4d, 0x50, 0x4f, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x5f, - 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, 0x0f, 0x12, 0x21, 0x0a, 0x1d, 0x52, 0x45, 0x51, - 0x55, 0x49, 0x52, 0x45, 0x44, 0x5f, 0x4e, 0x4f, 0x44, 0x45, 0x5f, 0x46, 0x45, 0x41, 0x54, 0x55, - 0x52, 0x45, 0x5f, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4e, 0x47, 0x10, 0x10, 0x12, 0x24, 0x0a, 0x20, - 0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, 0x44, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, - 0x5f, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4e, 0x47, - 0x10, 0x11, 0x12, 0x15, 0x0a, 0x11, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x4e, 0x45, - 0x58, 0x54, 0x5f, 0x50, 0x45, 0x45, 0x52, 0x10, 0x12, 0x12, 0x1a, 0x0a, 0x16, 0x54, 0x45, 0x4d, - 0x50, 0x4f, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x4e, 0x4f, 0x44, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, - 0x55, 0x52, 0x45, 0x10, 0x13, 0x12, 0x1a, 0x0a, 0x16, 0x50, 0x45, 0x52, 0x4d, 0x41, 0x4e, 0x45, - 0x4e, 0x54, 0x5f, 0x4e, 0x4f, 0x44, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, - 0x14, 0x12, 0x1d, 0x0a, 0x19, 0x50, 0x45, 0x52, 0x4d, 0x41, 0x4e, 0x45, 0x4e, 0x54, 0x5f, 0x43, - 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, 0x15, - 0x12, 0x12, 0x0a, 0x0e, 0x45, 0x58, 0x50, 0x49, 0x52, 0x59, 0x5f, 0x54, 0x4f, 0x4f, 0x5f, 0x46, - 0x41, 0x52, 0x10, 0x16, 0x12, 0x0f, 0x0a, 0x0b, 0x4d, 0x50, 0x50, 0x5f, 0x54, 0x49, 0x4d, 0x45, - 0x4f, 0x55, 0x54, 0x10, 0x17, 0x12, 0x19, 0x0a, 0x15, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, - 0x5f, 0x4f, 0x4e, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x41, 0x59, 0x4c, 0x4f, 0x41, 0x44, 0x10, 0x18, - 0x12, 0x1a, 0x0a, 0x16, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x4f, 0x4e, 0x49, 0x4f, - 0x4e, 0x5f, 0x42, 0x4c, 0x49, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x19, 0x12, 0x15, 0x0a, 0x10, - 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, - 0x10, 0xe5, 0x07, 0x12, 0x14, 0x0a, 0x0f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x46, - 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, 0xe6, 0x07, 0x12, 0x17, 0x0a, 0x12, 0x55, 0x4e, 0x52, - 0x45, 0x41, 0x44, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, - 0xe7, 0x07, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0xb3, 0x03, 0x0a, 0x0d, 0x43, 0x68, 0x61, - 0x6e, 0x6e, 0x65, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1b, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x5f, - 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x30, 0x01, 0x52, 0x06, 0x63, 0x68, - 0x61, 0x6e, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x6c, - 0x61, 0x67, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x68, 0x61, 0x6e, 0x6e, - 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, - 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x26, 0x0a, 0x0f, - 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x74, 0x69, 0x6d, 0x65, 0x4c, 0x6f, 0x63, 0x6b, 0x44, - 0x65, 0x6c, 0x74, 0x61, 0x12, 0x2a, 0x0a, 0x11, 0x68, 0x74, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, - 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x0f, 0x68, 0x74, 0x6c, 0x63, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x4d, 0x73, 0x61, 0x74, - 0x12, 0x19, 0x0a, 0x08, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x66, 0x65, 0x65, 0x18, 0x08, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x07, 0x62, 0x61, 0x73, 0x65, 0x46, 0x65, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x66, - 0x65, 0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x66, - 0x65, 0x65, 0x52, 0x61, 0x74, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x68, 0x74, 0x6c, 0x63, 0x5f, 0x6d, - 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x0f, 0x68, 0x74, 0x6c, 0x63, 0x4d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x4d, 0x73, - 0x61, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x6f, 0x70, 0x61, 0x71, - 0x75, 0x65, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x65, - 0x78, 0x74, 0x72, 0x61, 0x4f, 0x70, 0x61, 0x71, 0x75, 0x65, 0x44, 0x61, 0x74, 0x61, 0x22, 0x5d, - 0x0a, 0x0a, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, - 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x6e, 0x6f, 0x6e, - 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x49, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x49, 0x64, - 0x12, 0x1b, 0x0a, 0x03, 0x6f, 0x70, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x70, 0x52, 0x03, 0x6f, 0x70, 0x73, 0x22, 0x36, 0x0a, - 0x02, 0x4f, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x8e, 0x01, 0x0a, 0x13, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4d, - 0x61, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, - 0x08, 0x6d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x08, 0x6d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x12, 0x3b, 0x0a, 0x0b, 0x70, 0x65, 0x72, - 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x50, - 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x66, 0x75, 0x6c, 0x6c, 0x4d, 0x65, - 0x74, 0x68, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x66, 0x75, 0x6c, 0x6c, - 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x22, 0x2c, 0x0a, 0x14, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4d, - 0x61, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x22, 0xf4, 0x02, 0x0a, 0x14, 0x52, 0x50, 0x43, 0x4d, 0x69, 0x64, 0x64, - 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, - 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, - 0x72, 0x61, 0x77, 0x5f, 0x6d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x0b, 0x72, 0x61, 0x77, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x12, - 0x36, 0x0a, 0x17, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x63, 0x61, 0x76, 0x65, 0x61, 0x74, - 0x5f, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x15, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, 0x43, 0x6f, - 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, 0x0b, 0x73, 0x74, 0x72, 0x65, 0x61, - 0x6d, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6c, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x41, 0x75, 0x74, 0x68, 0x48, - 0x00, 0x52, 0x0a, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x41, 0x75, 0x74, 0x68, 0x12, 0x2d, 0x0a, - 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x50, 0x43, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x48, 0x00, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x08, - 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x50, 0x43, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x48, 0x00, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, - 0x0c, 0x72, 0x65, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0b, 0x72, 0x65, 0x67, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, - 0x74, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x6d, 0x73, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x42, 0x10, 0x0a, 0x0e, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x34, 0x0a, 0x0a, 0x53, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x41, 0x75, 0x74, 0x68, 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 0x5f, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x46, 0x75, 0x6c, 0x6c, 0x55, 0x72, - 0x69, 0x22, 0xab, 0x01, 0x0a, 0x0a, 0x52, 0x50, 0x43, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x66, 0x75, 0x6c, 0x6c, 0x5f, - 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6d, 0x65, 0x74, 0x68, 0x6f, - 0x64, 0x46, 0x75, 0x6c, 0x6c, 0x55, 0x72, 0x69, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x65, - 0x61, 0x6d, 0x5f, 0x72, 0x70, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x74, - 0x72, 0x65, 0x61, 0x6d, 0x52, 0x70, 0x63, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, - 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, - 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, - 0x69, 0x7a, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, - 0xc0, 0x01, 0x0a, 0x15, 0x52, 0x50, 0x43, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x0a, 0x72, 0x65, 0x66, - 0x5f, 0x6d, 0x73, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x72, - 0x65, 0x66, 0x4d, 0x73, 0x67, 0x49, 0x64, 0x12, 0x3b, 0x0a, 0x08, 0x72, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x08, 0x72, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x65, 0x72, 0x12, 0x36, 0x0a, 0x08, 0x66, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, - 0x48, 0x00, 0x52, 0x08, 0x66, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x42, 0x14, 0x0a, 0x12, - 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x22, 0xa6, 0x01, 0x0a, 0x16, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, - 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, - 0x0f, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, - 0x72, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3d, 0x0a, 0x1b, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, - 0x5f, 0x6d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x5f, 0x63, 0x61, 0x76, 0x65, 0x61, 0x74, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x18, 0x63, 0x75, 0x73, - 0x74, 0x6f, 0x6d, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x43, 0x61, 0x76, 0x65, 0x61, - 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6f, 0x6e, - 0x6c, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x72, - 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x22, 0x8b, 0x01, 0x0a, 0x11, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, - 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65, 0x70, 0x6c, 0x61, - 0x63, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x0f, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x35, 0x0a, 0x16, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, - 0x74, 0x5f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x15, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x53, - 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x2a, 0xcb, 0x02, 0x0a, 0x10, 0x4f, 0x75, - 0x74, 0x70, 0x75, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, - 0x0a, 0x17, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x55, - 0x42, 0x4b, 0x45, 0x59, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x53, - 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x43, 0x52, 0x49, 0x50, - 0x54, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x01, 0x12, 0x26, 0x0a, 0x22, 0x53, 0x43, 0x52, 0x49, - 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x57, 0x49, 0x54, 0x4e, 0x45, 0x53, 0x53, 0x5f, - 0x56, 0x30, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, 0x59, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x02, - 0x12, 0x26, 0x0a, 0x22, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x57, 0x49, 0x54, 0x4e, 0x45, 0x53, 0x53, 0x5f, 0x56, 0x30, 0x5f, 0x53, 0x43, 0x52, 0x49, 0x50, - 0x54, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x43, 0x52, 0x49, - 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, 0x59, 0x10, 0x04, - 0x12, 0x18, 0x0a, 0x14, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x53, 0x49, 0x47, 0x10, 0x05, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x43, - 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e, 0x55, 0x4c, 0x4c, 0x44, 0x41, - 0x54, 0x41, 0x10, 0x06, 0x12, 0x1c, 0x0a, 0x18, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x4e, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x4e, 0x44, 0x41, 0x52, 0x44, - 0x10, 0x07, 0x12, 0x1f, 0x0a, 0x1b, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, - 0x45, 0x5f, 0x57, 0x49, 0x54, 0x4e, 0x45, 0x53, 0x53, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, - 0x4e, 0x10, 0x08, 0x12, 0x22, 0x0a, 0x1e, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, 0x59, - 0x50, 0x45, 0x5f, 0x57, 0x49, 0x54, 0x4e, 0x45, 0x53, 0x53, 0x5f, 0x56, 0x31, 0x5f, 0x54, 0x41, - 0x50, 0x52, 0x4f, 0x4f, 0x54, 0x10, 0x09, 0x2a, 0x62, 0x0a, 0x15, 0x43, 0x6f, 0x69, 0x6e, 0x53, - 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, - 0x12, 0x1e, 0x0a, 0x1a, 0x53, 0x54, 0x52, 0x41, 0x54, 0x45, 0x47, 0x59, 0x5f, 0x55, 0x53, 0x45, - 0x5f, 0x47, 0x4c, 0x4f, 0x42, 0x41, 0x4c, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x00, - 0x12, 0x14, 0x0a, 0x10, 0x53, 0x54, 0x52, 0x41, 0x54, 0x45, 0x47, 0x59, 0x5f, 0x4c, 0x41, 0x52, - 0x47, 0x45, 0x53, 0x54, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x54, 0x52, 0x41, 0x54, 0x45, - 0x47, 0x59, 0x5f, 0x52, 0x41, 0x4e, 0x44, 0x4f, 0x4d, 0x10, 0x02, 0x2a, 0xac, 0x01, 0x0a, 0x0b, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x57, - 0x49, 0x54, 0x4e, 0x45, 0x53, 0x53, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, 0x59, 0x5f, 0x48, 0x41, - 0x53, 0x48, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x4e, 0x45, 0x53, 0x54, 0x45, 0x44, 0x5f, 0x50, - 0x55, 0x42, 0x4b, 0x45, 0x59, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x01, 0x12, 0x1e, 0x0a, 0x1a, - 0x55, 0x4e, 0x55, 0x53, 0x45, 0x44, 0x5f, 0x57, 0x49, 0x54, 0x4e, 0x45, 0x53, 0x53, 0x5f, 0x50, - 0x55, 0x42, 0x4b, 0x45, 0x59, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x02, 0x12, 0x1d, 0x0a, 0x19, - 0x55, 0x4e, 0x55, 0x53, 0x45, 0x44, 0x5f, 0x4e, 0x45, 0x53, 0x54, 0x45, 0x44, 0x5f, 0x50, 0x55, - 0x42, 0x4b, 0x45, 0x59, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x03, 0x12, 0x12, 0x0a, 0x0e, 0x54, - 0x41, 0x50, 0x52, 0x4f, 0x4f, 0x54, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, 0x59, 0x10, 0x04, 0x12, - 0x19, 0x0a, 0x15, 0x55, 0x4e, 0x55, 0x53, 0x45, 0x44, 0x5f, 0x54, 0x41, 0x50, 0x52, 0x4f, 0x4f, - 0x54, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, 0x59, 0x10, 0x05, 0x2a, 0x8c, 0x01, 0x0a, 0x0e, 0x43, - 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, - 0x17, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x4d, - 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x45, - 0x47, 0x41, 0x43, 0x59, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x54, 0x41, 0x54, 0x49, 0x43, - 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x5f, 0x4b, 0x45, 0x59, 0x10, 0x02, 0x12, 0x0b, 0x0a, - 0x07, 0x41, 0x4e, 0x43, 0x48, 0x4f, 0x52, 0x53, 0x10, 0x03, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x43, - 0x52, 0x49, 0x50, 0x54, 0x5f, 0x45, 0x4e, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x44, 0x5f, 0x4c, 0x45, - 0x41, 0x53, 0x45, 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x49, 0x4d, 0x50, 0x4c, 0x45, 0x5f, - 0x54, 0x41, 0x50, 0x52, 0x4f, 0x4f, 0x54, 0x10, 0x05, 0x2a, 0x61, 0x0a, 0x09, 0x49, 0x6e, 0x69, - 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x15, 0x0a, 0x11, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, - 0x54, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x13, 0x0a, - 0x0f, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x54, 0x4f, 0x52, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x4c, - 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x54, 0x4f, 0x52, 0x5f, - 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x49, 0x4e, 0x49, 0x54, - 0x49, 0x41, 0x54, 0x4f, 0x52, 0x5f, 0x42, 0x4f, 0x54, 0x48, 0x10, 0x03, 0x2a, 0x60, 0x0a, 0x0e, - 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x10, - 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, - 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x4e, 0x43, 0x48, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, - 0x49, 0x4e, 0x43, 0x4f, 0x4d, 0x49, 0x4e, 0x47, 0x5f, 0x48, 0x54, 0x4c, 0x43, 0x10, 0x02, 0x12, - 0x11, 0x0a, 0x0d, 0x4f, 0x55, 0x54, 0x47, 0x4f, 0x49, 0x4e, 0x47, 0x5f, 0x48, 0x54, 0x4c, 0x43, - 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x04, 0x2a, 0x71, - 0x0a, 0x11, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x75, 0x74, 0x63, - 0x6f, 0x6d, 0x65, 0x12, 0x13, 0x0a, 0x0f, 0x4f, 0x55, 0x54, 0x43, 0x4f, 0x4d, 0x45, 0x5f, 0x55, - 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x4c, 0x41, 0x49, - 0x4d, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x43, 0x4c, 0x41, 0x49, 0x4d, - 0x45, 0x44, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x41, 0x42, 0x41, 0x4e, 0x44, 0x4f, 0x4e, 0x45, - 0x44, 0x10, 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x46, 0x49, 0x52, 0x53, 0x54, 0x5f, 0x53, 0x54, 0x41, - 0x47, 0x45, 0x10, 0x04, 0x12, 0x0b, 0x0a, 0x07, 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, - 0x05, 0x2a, 0x39, 0x0a, 0x0e, 0x4e, 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, - 0x12, 0x1a, 0x0a, 0x16, 0x42, 0x45, 0x54, 0x57, 0x45, 0x45, 0x4e, 0x4e, 0x45, 0x53, 0x53, 0x5f, - 0x43, 0x45, 0x4e, 0x54, 0x52, 0x41, 0x4c, 0x49, 0x54, 0x59, 0x10, 0x01, 0x2a, 0x3b, 0x0a, 0x10, - 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x48, 0x54, 0x4c, 0x43, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, - 0x0a, 0x07, 0x53, 0x45, 0x54, 0x54, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x43, - 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x45, 0x44, 0x10, 0x02, 0x2a, 0xd9, 0x01, 0x0a, 0x14, 0x50, 0x61, - 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x52, 0x65, 0x61, 0x73, - 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x13, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, - 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x46, - 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x54, 0x49, - 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x46, 0x41, 0x49, 0x4c, 0x55, - 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f, 0x5f, 0x52, 0x4f, 0x55, - 0x54, 0x45, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, - 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x2c, - 0x0a, 0x28, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, - 0x5f, 0x49, 0x4e, 0x43, 0x4f, 0x52, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x50, 0x41, 0x59, 0x4d, 0x45, - 0x4e, 0x54, 0x5f, 0x44, 0x45, 0x54, 0x41, 0x49, 0x4c, 0x53, 0x10, 0x04, 0x12, 0x27, 0x0a, 0x23, - 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x49, - 0x4e, 0x53, 0x55, 0x46, 0x46, 0x49, 0x43, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x42, 0x41, 0x4c, 0x41, - 0x4e, 0x43, 0x45, 0x10, 0x05, 0x2a, 0xcf, 0x04, 0x0a, 0x0a, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x42, 0x69, 0x74, 0x12, 0x18, 0x0a, 0x14, 0x44, 0x41, 0x54, 0x41, 0x4c, 0x4f, 0x53, 0x53, - 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x45, 0x43, 0x54, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x00, 0x12, 0x18, - 0x0a, 0x14, 0x44, 0x41, 0x54, 0x41, 0x4c, 0x4f, 0x53, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x45, - 0x43, 0x54, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x49, 0x4e, 0x49, 0x54, - 0x49, 0x41, 0x4c, 0x5f, 0x52, 0x4f, 0x55, 0x49, 0x4e, 0x47, 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x10, - 0x03, 0x12, 0x1f, 0x0a, 0x1b, 0x55, 0x50, 0x46, 0x52, 0x4f, 0x4e, 0x54, 0x5f, 0x53, 0x48, 0x55, - 0x54, 0x44, 0x4f, 0x57, 0x4e, 0x5f, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x52, 0x45, 0x51, - 0x10, 0x04, 0x12, 0x1f, 0x0a, 0x1b, 0x55, 0x50, 0x46, 0x52, 0x4f, 0x4e, 0x54, 0x5f, 0x53, 0x48, - 0x55, 0x54, 0x44, 0x4f, 0x57, 0x4e, 0x5f, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x4f, 0x50, - 0x54, 0x10, 0x05, 0x12, 0x16, 0x0a, 0x12, 0x47, 0x4f, 0x53, 0x53, 0x49, 0x50, 0x5f, 0x51, 0x55, - 0x45, 0x52, 0x49, 0x45, 0x53, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x06, 0x12, 0x16, 0x0a, 0x12, 0x47, - 0x4f, 0x53, 0x53, 0x49, 0x50, 0x5f, 0x51, 0x55, 0x45, 0x52, 0x49, 0x45, 0x53, 0x5f, 0x4f, 0x50, - 0x54, 0x10, 0x07, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x4c, 0x56, 0x5f, 0x4f, 0x4e, 0x49, 0x4f, 0x4e, - 0x5f, 0x52, 0x45, 0x51, 0x10, 0x08, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x4c, 0x56, 0x5f, 0x4f, 0x4e, - 0x49, 0x4f, 0x4e, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x09, 0x12, 0x1a, 0x0a, 0x16, 0x45, 0x58, 0x54, + 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x48, 0x00, 0x52, 0x0b, 0x63, 0x68, 0x61, 0x6e, 0x42, + 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x5f, + 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x48, 0x00, 0x52, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, + 0x63, 0x6b, 0x75, 0x70, 0x42, 0x08, 0x0a, 0x06, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x22, 0x17, + 0x0a, 0x15, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x0a, 0x19, 0x43, 0x68, 0x61, 0x6e, 0x6e, + 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x1a, 0x0a, 0x18, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x68, + 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x44, 0x0a, 0x12, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x16, + 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb0, 0x01, 0x0a, 0x13, 0x42, 0x61, 0x6b, 0x65, 0x4d, + 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3b, + 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x61, 0x63, 0x61, + 0x72, 0x6f, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0b, + 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x72, + 0x6f, 0x6f, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x12, 0x3c, 0x0a, 0x1a, 0x61, + 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x70, 0x65, + 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x18, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x50, 0x65, + 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x32, 0x0a, 0x14, 0x42, 0x61, 0x6b, + 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x22, 0x18, 0x0a, + 0x16, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3b, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x4d, + 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0c, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x69, + 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x04, 0x52, 0x0a, 0x72, 0x6f, 0x6f, 0x74, 0x4b, 0x65, + 0x79, 0x49, 0x64, 0x73, 0x22, 0x39, 0x0a, 0x17, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, + 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x1e, 0x0a, 0x0b, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x22, + 0x34, 0x0a, 0x18, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, + 0x6e, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x64, 0x22, 0x55, 0x0a, 0x16, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, + 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x12, + 0x3b, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x61, 0x63, + 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, + 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x18, 0x0a, 0x16, + 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xe4, 0x01, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x50, + 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x64, 0x0a, 0x12, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x70, 0x65, 0x72, + 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, 0x69, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, + 0x65, 0x74, 0x68, 0x6f, 0x64, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x50, 0x65, 0x72, + 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x63, 0x0a, 0x16, 0x4d, 0x65, 0x74, 0x68, + 0x6f, 0x64, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x33, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x61, 0x63, 0x61, + 0x72, 0x6f, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xcc, 0x08, + 0x0a, 0x07, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x12, 0x2e, 0x0a, 0x04, 0x63, 0x6f, 0x64, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x43, + 0x6f, 0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x3b, 0x0a, 0x0e, 0x63, 0x68, 0x61, + 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x14, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, + 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x68, 0x74, 0x6c, 0x63, 0x5f, 0x6d, + 0x73, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x68, 0x74, 0x6c, 0x63, 0x4d, + 0x73, 0x61, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x6e, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x68, 0x61, + 0x5f, 0x32, 0x35, 0x36, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x6f, 0x6e, 0x69, 0x6f, + 0x6e, 0x53, 0x68, 0x61, 0x32, 0x35, 0x36, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x74, 0x76, 0x5f, + 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x63, 0x6c, + 0x74, 0x76, 0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, + 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x30, + 0x0a, 0x14, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x66, 0x61, + 0x69, 0x6c, 0x75, 0x72, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, + 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x8b, 0x06, 0x0a, 0x0b, 0x46, 0x61, 0x69, + 0x6c, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x53, 0x45, + 0x52, 0x56, 0x45, 0x44, 0x10, 0x00, 0x12, 0x28, 0x0a, 0x24, 0x49, 0x4e, 0x43, 0x4f, 0x52, 0x52, + 0x45, 0x43, 0x54, 0x5f, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x50, + 0x41, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x44, 0x45, 0x54, 0x41, 0x49, 0x4c, 0x53, 0x10, 0x01, + 0x12, 0x1c, 0x0a, 0x18, 0x49, 0x4e, 0x43, 0x4f, 0x52, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x50, 0x41, + 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x41, 0x4d, 0x4f, 0x55, 0x4e, 0x54, 0x10, 0x02, 0x12, 0x1f, + 0x0a, 0x1b, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x5f, 0x49, 0x4e, 0x43, 0x4f, 0x52, 0x52, 0x45, 0x43, + 0x54, 0x5f, 0x43, 0x4c, 0x54, 0x56, 0x5f, 0x45, 0x58, 0x50, 0x49, 0x52, 0x59, 0x10, 0x03, 0x12, + 0x1f, 0x0a, 0x1b, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x5f, 0x49, 0x4e, 0x43, 0x4f, 0x52, 0x52, 0x45, + 0x43, 0x54, 0x5f, 0x48, 0x54, 0x4c, 0x43, 0x5f, 0x41, 0x4d, 0x4f, 0x55, 0x4e, 0x54, 0x10, 0x04, + 0x12, 0x19, 0x0a, 0x15, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x5f, 0x45, 0x58, 0x50, 0x49, 0x52, 0x59, + 0x5f, 0x54, 0x4f, 0x4f, 0x5f, 0x53, 0x4f, 0x4f, 0x4e, 0x10, 0x05, 0x12, 0x11, 0x0a, 0x0d, 0x49, + 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x52, 0x45, 0x41, 0x4c, 0x4d, 0x10, 0x06, 0x12, 0x13, + 0x0a, 0x0f, 0x45, 0x58, 0x50, 0x49, 0x52, 0x59, 0x5f, 0x54, 0x4f, 0x4f, 0x5f, 0x53, 0x4f, 0x4f, + 0x4e, 0x10, 0x07, 0x12, 0x19, 0x0a, 0x15, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x4f, + 0x4e, 0x49, 0x4f, 0x4e, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x10, 0x08, 0x12, 0x16, + 0x0a, 0x12, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x4f, 0x4e, 0x49, 0x4f, 0x4e, 0x5f, + 0x48, 0x4d, 0x41, 0x43, 0x10, 0x09, 0x12, 0x15, 0x0a, 0x11, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, + 0x44, 0x5f, 0x4f, 0x4e, 0x49, 0x4f, 0x4e, 0x5f, 0x4b, 0x45, 0x59, 0x10, 0x0a, 0x12, 0x18, 0x0a, + 0x14, 0x41, 0x4d, 0x4f, 0x55, 0x4e, 0x54, 0x5f, 0x42, 0x45, 0x4c, 0x4f, 0x57, 0x5f, 0x4d, 0x49, + 0x4e, 0x49, 0x4d, 0x55, 0x4d, 0x10, 0x0b, 0x12, 0x14, 0x0a, 0x10, 0x46, 0x45, 0x45, 0x5f, 0x49, + 0x4e, 0x53, 0x55, 0x46, 0x46, 0x49, 0x43, 0x49, 0x45, 0x4e, 0x54, 0x10, 0x0c, 0x12, 0x19, 0x0a, + 0x15, 0x49, 0x4e, 0x43, 0x4f, 0x52, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x43, 0x4c, 0x54, 0x56, 0x5f, + 0x45, 0x58, 0x50, 0x49, 0x52, 0x59, 0x10, 0x0d, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x48, 0x41, 0x4e, + 0x4e, 0x45, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x0e, 0x12, 0x1d, + 0x0a, 0x19, 0x54, 0x45, 0x4d, 0x50, 0x4f, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x43, 0x48, 0x41, 0x4e, + 0x4e, 0x45, 0x4c, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, 0x0f, 0x12, 0x21, 0x0a, + 0x1d, 0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, 0x44, 0x5f, 0x4e, 0x4f, 0x44, 0x45, 0x5f, 0x46, + 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4e, 0x47, 0x10, 0x10, + 0x12, 0x24, 0x0a, 0x20, 0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, 0x44, 0x5f, 0x43, 0x48, 0x41, + 0x4e, 0x4e, 0x45, 0x4c, 0x5f, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x4d, 0x49, 0x53, + 0x53, 0x49, 0x4e, 0x47, 0x10, 0x11, 0x12, 0x15, 0x0a, 0x11, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, + 0x4e, 0x5f, 0x4e, 0x45, 0x58, 0x54, 0x5f, 0x50, 0x45, 0x45, 0x52, 0x10, 0x12, 0x12, 0x1a, 0x0a, + 0x16, 0x54, 0x45, 0x4d, 0x50, 0x4f, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x4e, 0x4f, 0x44, 0x45, 0x5f, + 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, 0x13, 0x12, 0x1a, 0x0a, 0x16, 0x50, 0x45, 0x52, + 0x4d, 0x41, 0x4e, 0x45, 0x4e, 0x54, 0x5f, 0x4e, 0x4f, 0x44, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, + 0x55, 0x52, 0x45, 0x10, 0x14, 0x12, 0x1d, 0x0a, 0x19, 0x50, 0x45, 0x52, 0x4d, 0x41, 0x4e, 0x45, + 0x4e, 0x54, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, + 0x52, 0x45, 0x10, 0x15, 0x12, 0x12, 0x0a, 0x0e, 0x45, 0x58, 0x50, 0x49, 0x52, 0x59, 0x5f, 0x54, + 0x4f, 0x4f, 0x5f, 0x46, 0x41, 0x52, 0x10, 0x16, 0x12, 0x0f, 0x0a, 0x0b, 0x4d, 0x50, 0x50, 0x5f, + 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, 0x17, 0x12, 0x19, 0x0a, 0x15, 0x49, 0x4e, 0x56, + 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x4f, 0x4e, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x41, 0x59, 0x4c, 0x4f, + 0x41, 0x44, 0x10, 0x18, 0x12, 0x1a, 0x0a, 0x16, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, + 0x4f, 0x4e, 0x49, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x49, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x19, + 0x12, 0x15, 0x0a, 0x10, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x46, 0x41, 0x49, + 0x4c, 0x55, 0x52, 0x45, 0x10, 0xe5, 0x07, 0x12, 0x14, 0x0a, 0x0f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, + 0x57, 0x4e, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, 0xe6, 0x07, 0x12, 0x17, 0x0a, + 0x12, 0x55, 0x4e, 0x52, 0x45, 0x41, 0x44, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, + 0x55, 0x52, 0x45, 0x10, 0xe7, 0x07, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0xb3, 0x03, 0x0a, + 0x0d, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x1c, + 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1d, 0x0a, 0x0a, + 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x09, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1b, 0x0a, 0x07, 0x63, + 0x68, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x30, 0x01, + 0x52, 0x06, 0x63, 0x68, 0x61, 0x6e, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x74, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x63, + 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, + 0x12, 0x26, 0x0a, 0x0f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x64, 0x65, + 0x6c, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x74, 0x69, 0x6d, 0x65, 0x4c, + 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x2a, 0x0a, 0x11, 0x68, 0x74, 0x6c, 0x63, + 0x5f, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x0f, 0x68, 0x74, 0x6c, 0x63, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, + 0x4d, 0x73, 0x61, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x66, 0x65, 0x65, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x62, 0x61, 0x73, 0x65, 0x46, 0x65, 0x65, 0x12, + 0x19, 0x0a, 0x08, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x07, 0x66, 0x65, 0x65, 0x52, 0x61, 0x74, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x68, 0x74, + 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, + 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x68, 0x74, 0x6c, 0x63, 0x4d, 0x61, 0x78, 0x69, 0x6d, + 0x75, 0x6d, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, + 0x6f, 0x70, 0x61, 0x71, 0x75, 0x65, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0c, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x0f, 0x65, 0x78, 0x74, 0x72, 0x61, 0x4f, 0x70, 0x61, 0x71, 0x75, 0x65, 0x44, 0x61, + 0x74, 0x61, 0x22, 0x5d, 0x0a, 0x0a, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x64, + 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, + 0x65, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x74, 0x6f, 0x72, 0x61, + 0x67, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x03, 0x6f, 0x70, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x09, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x70, 0x52, 0x03, 0x6f, 0x70, + 0x73, 0x22, 0x36, 0x0a, 0x02, 0x4f, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, + 0x18, 0x0a, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x8e, 0x01, 0x0a, 0x13, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x12, 0x3b, 0x0a, + 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x61, 0x63, 0x61, 0x72, + 0x6f, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x70, + 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x66, 0x75, + 0x6c, 0x6c, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x66, 0x75, 0x6c, 0x6c, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x22, 0x2c, 0x0a, 0x14, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x22, 0xf4, 0x02, 0x0a, 0x14, 0x52, 0x50, 0x43, + 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, + 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x61, 0x77, 0x5f, 0x6d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x72, 0x61, 0x77, 0x4d, 0x61, 0x63, 0x61, 0x72, + 0x6f, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x17, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x63, 0x61, + 0x76, 0x65, 0x61, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x43, 0x61, 0x76, 0x65, + 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, 0x0b, 0x73, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x11, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x41, + 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x0a, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x41, 0x75, 0x74, + 0x68, 0x12, 0x2d, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x50, 0x43, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x2f, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x50, 0x43, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x72, 0x65, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, + 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0b, 0x72, 0x65, 0x67, 0x43, 0x6f, + 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x6d, 0x73, 0x67, 0x5f, 0x69, 0x64, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x42, 0x10, 0x0a, + 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, + 0x34, 0x0a, 0x0a, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x41, 0x75, 0x74, 0x68, 0x12, 0x26, 0x0a, + 0x0f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x75, 0x72, 0x69, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x46, 0x75, + 0x6c, 0x6c, 0x55, 0x72, 0x69, 0x22, 0xab, 0x01, 0x0a, 0x0a, 0x52, 0x50, 0x43, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x66, + 0x75, 0x6c, 0x6c, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6d, + 0x65, 0x74, 0x68, 0x6f, 0x64, 0x46, 0x75, 0x6c, 0x6c, 0x55, 0x72, 0x69, 0x12, 0x1d, 0x0a, 0x0a, + 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x72, 0x70, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x09, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x70, 0x63, 0x12, 0x1b, 0x0a, 0x09, 0x74, + 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x69, + 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x73, 0x65, + 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x45, 0x72, + 0x72, 0x6f, 0x72, 0x22, 0xc0, 0x01, 0x0a, 0x15, 0x52, 0x50, 0x43, 0x4d, 0x69, 0x64, 0x64, 0x6c, + 0x65, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, + 0x0a, 0x72, 0x65, 0x66, 0x5f, 0x6d, 0x73, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x08, 0x72, 0x65, 0x66, 0x4d, 0x73, 0x67, 0x49, 0x64, 0x12, 0x3b, 0x0a, 0x08, 0x72, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, + 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x08, + 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x36, 0x0a, 0x08, 0x66, 0x65, 0x65, 0x64, + 0x62, 0x61, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6c, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x46, 0x65, 0x65, 0x64, + 0x62, 0x61, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x08, 0x66, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, + 0x42, 0x14, 0x0a, 0x12, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x5f, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xa6, 0x01, 0x0a, 0x16, 0x4d, 0x69, 0x64, 0x64, 0x6c, + 0x65, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x5f, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6d, 0x69, 0x64, 0x64, + 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3d, 0x0a, 0x1b, 0x63, 0x75, + 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x5f, 0x63, 0x61, + 0x76, 0x65, 0x61, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x18, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x43, + 0x61, 0x76, 0x65, 0x61, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x65, 0x61, + 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0c, 0x72, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x22, + 0x8b, 0x01, 0x0a, 0x11, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x46, 0x65, 0x65, + 0x64, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x29, 0x0a, 0x10, 0x72, + 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x16, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x15, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, + 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x2a, 0xcb, 0x02, + 0x0a, 0x10, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, 0x59, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x00, 0x12, + 0x1b, 0x0a, 0x17, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, + 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x01, 0x12, 0x26, 0x0a, 0x22, + 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x57, 0x49, 0x54, 0x4e, + 0x45, 0x53, 0x53, 0x5f, 0x56, 0x30, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, 0x59, 0x5f, 0x48, 0x41, + 0x53, 0x48, 0x10, 0x02, 0x12, 0x26, 0x0a, 0x22, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x57, 0x49, 0x54, 0x4e, 0x45, 0x53, 0x53, 0x5f, 0x56, 0x30, 0x5f, 0x53, + 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, + 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x55, 0x42, 0x4b, + 0x45, 0x59, 0x10, 0x04, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x53, 0x49, 0x47, 0x10, 0x05, 0x12, 0x18, + 0x0a, 0x14, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e, 0x55, + 0x4c, 0x4c, 0x44, 0x41, 0x54, 0x41, 0x10, 0x06, 0x12, 0x1c, 0x0a, 0x18, 0x53, 0x43, 0x52, 0x49, + 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x4e, + 0x44, 0x41, 0x52, 0x44, 0x10, 0x07, 0x12, 0x1f, 0x0a, 0x1b, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x57, 0x49, 0x54, 0x4e, 0x45, 0x53, 0x53, 0x5f, 0x55, 0x4e, + 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x08, 0x12, 0x22, 0x0a, 0x1e, 0x53, 0x43, 0x52, 0x49, 0x50, + 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x57, 0x49, 0x54, 0x4e, 0x45, 0x53, 0x53, 0x5f, 0x56, + 0x31, 0x5f, 0x54, 0x41, 0x50, 0x52, 0x4f, 0x4f, 0x54, 0x10, 0x09, 0x2a, 0x62, 0x0a, 0x15, 0x43, + 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, + 0x74, 0x65, 0x67, 0x79, 0x12, 0x1e, 0x0a, 0x1a, 0x53, 0x54, 0x52, 0x41, 0x54, 0x45, 0x47, 0x59, + 0x5f, 0x55, 0x53, 0x45, 0x5f, 0x47, 0x4c, 0x4f, 0x42, 0x41, 0x4c, 0x5f, 0x43, 0x4f, 0x4e, 0x46, + 0x49, 0x47, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x54, 0x52, 0x41, 0x54, 0x45, 0x47, 0x59, + 0x5f, 0x4c, 0x41, 0x52, 0x47, 0x45, 0x53, 0x54, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x54, + 0x52, 0x41, 0x54, 0x45, 0x47, 0x59, 0x5f, 0x52, 0x41, 0x4e, 0x44, 0x4f, 0x4d, 0x10, 0x02, 0x2a, + 0xac, 0x01, 0x0a, 0x0b, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x17, 0x0a, 0x13, 0x57, 0x49, 0x54, 0x4e, 0x45, 0x53, 0x53, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, + 0x59, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x4e, 0x45, 0x53, 0x54, + 0x45, 0x44, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, 0x59, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x01, + 0x12, 0x1e, 0x0a, 0x1a, 0x55, 0x4e, 0x55, 0x53, 0x45, 0x44, 0x5f, 0x57, 0x49, 0x54, 0x4e, 0x45, + 0x53, 0x53, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, 0x59, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x02, + 0x12, 0x1d, 0x0a, 0x19, 0x55, 0x4e, 0x55, 0x53, 0x45, 0x44, 0x5f, 0x4e, 0x45, 0x53, 0x54, 0x45, + 0x44, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, 0x59, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x03, 0x12, + 0x12, 0x0a, 0x0e, 0x54, 0x41, 0x50, 0x52, 0x4f, 0x4f, 0x54, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, + 0x59, 0x10, 0x04, 0x12, 0x19, 0x0a, 0x15, 0x55, 0x4e, 0x55, 0x53, 0x45, 0x44, 0x5f, 0x54, 0x41, + 0x50, 0x52, 0x4f, 0x4f, 0x54, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, 0x59, 0x10, 0x05, 0x2a, 0x8c, + 0x01, 0x0a, 0x0e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x43, 0x4f, 0x4d, + 0x4d, 0x49, 0x54, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x10, 0x00, 0x12, 0x0a, + 0x0a, 0x06, 0x4c, 0x45, 0x47, 0x41, 0x43, 0x59, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x54, + 0x41, 0x54, 0x49, 0x43, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x5f, 0x4b, 0x45, 0x59, 0x10, + 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x4e, 0x43, 0x48, 0x4f, 0x52, 0x53, 0x10, 0x03, 0x12, 0x19, + 0x0a, 0x15, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x45, 0x4e, 0x46, 0x4f, 0x52, 0x43, 0x45, + 0x44, 0x5f, 0x4c, 0x45, 0x41, 0x53, 0x45, 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x49, 0x4d, + 0x50, 0x4c, 0x45, 0x5f, 0x54, 0x41, 0x50, 0x52, 0x4f, 0x4f, 0x54, 0x10, 0x05, 0x2a, 0x61, 0x0a, + 0x09, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x15, 0x0a, 0x11, 0x49, 0x4e, + 0x49, 0x54, 0x49, 0x41, 0x54, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, + 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x54, 0x4f, 0x52, 0x5f, 0x4c, + 0x4f, 0x43, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, + 0x54, 0x4f, 0x52, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, + 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x54, 0x4f, 0x52, 0x5f, 0x42, 0x4f, 0x54, 0x48, 0x10, 0x03, + 0x2a, 0x60, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, + 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x4e, 0x43, 0x48, 0x4f, 0x52, 0x10, 0x01, + 0x12, 0x11, 0x0a, 0x0d, 0x49, 0x4e, 0x43, 0x4f, 0x4d, 0x49, 0x4e, 0x47, 0x5f, 0x48, 0x54, 0x4c, + 0x43, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x4f, 0x55, 0x54, 0x47, 0x4f, 0x49, 0x4e, 0x47, 0x5f, + 0x48, 0x54, 0x4c, 0x43, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, + 0x10, 0x04, 0x2a, 0x71, 0x0a, 0x11, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x4f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x12, 0x13, 0x0a, 0x0f, 0x4f, 0x55, 0x54, 0x43, 0x4f, + 0x4d, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, + 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x43, + 0x4c, 0x41, 0x49, 0x4d, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x41, 0x42, 0x41, 0x4e, + 0x44, 0x4f, 0x4e, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x46, 0x49, 0x52, 0x53, 0x54, + 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x10, 0x04, 0x12, 0x0b, 0x0a, 0x07, 0x54, 0x49, 0x4d, 0x45, + 0x4f, 0x55, 0x54, 0x10, 0x05, 0x2a, 0x39, 0x0a, 0x0e, 0x4e, 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, + 0x72, 0x69, 0x63, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, + 0x57, 0x4e, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x42, 0x45, 0x54, 0x57, 0x45, 0x45, 0x4e, 0x4e, + 0x45, 0x53, 0x53, 0x5f, 0x43, 0x45, 0x4e, 0x54, 0x52, 0x41, 0x4c, 0x49, 0x54, 0x59, 0x10, 0x01, + 0x2a, 0x3b, 0x0a, 0x10, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x48, 0x54, 0x4c, 0x43, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x45, 0x54, 0x54, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, + 0x0c, 0x0a, 0x08, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x45, 0x44, 0x10, 0x02, 0x2a, 0xd9, 0x01, + 0x0a, 0x14, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, + 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x13, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, + 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, + 0x1a, 0x0a, 0x16, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, + 0x4e, 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x46, + 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f, + 0x5f, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x46, 0x41, 0x49, 0x4c, + 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, + 0x10, 0x03, 0x12, 0x2c, 0x0a, 0x28, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, + 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x49, 0x4e, 0x43, 0x4f, 0x52, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x50, + 0x41, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x44, 0x45, 0x54, 0x41, 0x49, 0x4c, 0x53, 0x10, 0x04, + 0x12, 0x27, 0x0a, 0x23, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, + 0x4f, 0x4e, 0x5f, 0x49, 0x4e, 0x53, 0x55, 0x46, 0x46, 0x49, 0x43, 0x49, 0x45, 0x4e, 0x54, 0x5f, + 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x05, 0x2a, 0xcf, 0x04, 0x0a, 0x0a, 0x46, 0x65, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x42, 0x69, 0x74, 0x12, 0x18, 0x0a, 0x14, 0x44, 0x41, 0x54, 0x41, + 0x4c, 0x4f, 0x53, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x45, 0x43, 0x54, 0x5f, 0x52, 0x45, 0x51, + 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x44, 0x41, 0x54, 0x41, 0x4c, 0x4f, 0x53, 0x53, 0x5f, 0x50, + 0x52, 0x4f, 0x54, 0x45, 0x43, 0x54, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, + 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x4c, 0x5f, 0x52, 0x4f, 0x55, 0x49, 0x4e, 0x47, 0x5f, 0x53, + 0x59, 0x4e, 0x43, 0x10, 0x03, 0x12, 0x1f, 0x0a, 0x1b, 0x55, 0x50, 0x46, 0x52, 0x4f, 0x4e, 0x54, + 0x5f, 0x53, 0x48, 0x55, 0x54, 0x44, 0x4f, 0x57, 0x4e, 0x5f, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, + 0x5f, 0x52, 0x45, 0x51, 0x10, 0x04, 0x12, 0x1f, 0x0a, 0x1b, 0x55, 0x50, 0x46, 0x52, 0x4f, 0x4e, + 0x54, 0x5f, 0x53, 0x48, 0x55, 0x54, 0x44, 0x4f, 0x57, 0x4e, 0x5f, 0x53, 0x43, 0x52, 0x49, 0x50, + 0x54, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x05, 0x12, 0x16, 0x0a, 0x12, 0x47, 0x4f, 0x53, 0x53, 0x49, + 0x50, 0x5f, 0x51, 0x55, 0x45, 0x52, 0x49, 0x45, 0x53, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x06, 0x12, + 0x16, 0x0a, 0x12, 0x47, 0x4f, 0x53, 0x53, 0x49, 0x50, 0x5f, 0x51, 0x55, 0x45, 0x52, 0x49, 0x45, + 0x53, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x07, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x4c, 0x56, 0x5f, 0x4f, + 0x4e, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x08, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x4c, + 0x56, 0x5f, 0x4f, 0x4e, 0x49, 0x4f, 0x4e, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x09, 0x12, 0x1a, 0x0a, + 0x16, 0x45, 0x58, 0x54, 0x5f, 0x47, 0x4f, 0x53, 0x53, 0x49, 0x50, 0x5f, 0x51, 0x55, 0x45, 0x52, + 0x49, 0x45, 0x53, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x0a, 0x12, 0x1a, 0x0a, 0x16, 0x45, 0x58, 0x54, 0x5f, 0x47, 0x4f, 0x53, 0x53, 0x49, 0x50, 0x5f, 0x51, 0x55, 0x45, 0x52, 0x49, 0x45, 0x53, 0x5f, - 0x52, 0x45, 0x51, 0x10, 0x0a, 0x12, 0x1a, 0x0a, 0x16, 0x45, 0x58, 0x54, 0x5f, 0x47, 0x4f, 0x53, - 0x53, 0x49, 0x50, 0x5f, 0x51, 0x55, 0x45, 0x52, 0x49, 0x45, 0x53, 0x5f, 0x4f, 0x50, 0x54, 0x10, - 0x0b, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x54, 0x41, 0x54, 0x49, 0x43, 0x5f, 0x52, 0x45, 0x4d, 0x4f, - 0x54, 0x45, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x0c, 0x12, 0x19, 0x0a, 0x15, - 0x53, 0x54, 0x41, 0x54, 0x49, 0x43, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x5f, 0x4b, 0x45, - 0x59, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x0d, 0x12, 0x14, 0x0a, 0x10, 0x50, 0x41, 0x59, 0x4d, 0x45, - 0x4e, 0x54, 0x5f, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x0e, 0x12, 0x14, 0x0a, - 0x10, 0x50, 0x41, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x4f, 0x50, - 0x54, 0x10, 0x0f, 0x12, 0x0b, 0x0a, 0x07, 0x4d, 0x50, 0x50, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x10, - 0x12, 0x0b, 0x0a, 0x07, 0x4d, 0x50, 0x50, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x11, 0x12, 0x16, 0x0a, - 0x12, 0x57, 0x55, 0x4d, 0x42, 0x4f, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x53, 0x5f, - 0x52, 0x45, 0x51, 0x10, 0x12, 0x12, 0x16, 0x0a, 0x12, 0x57, 0x55, 0x4d, 0x42, 0x4f, 0x5f, 0x43, - 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x53, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x13, 0x12, 0x0f, 0x0a, - 0x0b, 0x41, 0x4e, 0x43, 0x48, 0x4f, 0x52, 0x53, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x14, 0x12, 0x0f, - 0x0a, 0x0b, 0x41, 0x4e, 0x43, 0x48, 0x4f, 0x52, 0x53, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x15, 0x12, - 0x1d, 0x0a, 0x19, 0x41, 0x4e, 0x43, 0x48, 0x4f, 0x52, 0x53, 0x5f, 0x5a, 0x45, 0x52, 0x4f, 0x5f, - 0x46, 0x45, 0x45, 0x5f, 0x48, 0x54, 0x4c, 0x43, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x16, 0x12, 0x1d, - 0x0a, 0x19, 0x41, 0x4e, 0x43, 0x48, 0x4f, 0x52, 0x53, 0x5f, 0x5a, 0x45, 0x52, 0x4f, 0x5f, 0x46, - 0x45, 0x45, 0x5f, 0x48, 0x54, 0x4c, 0x43, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x17, 0x12, 0x0b, 0x0a, - 0x07, 0x41, 0x4d, 0x50, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x1e, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x4d, - 0x50, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x1f, 0x2a, 0xac, 0x01, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x55, 0x50, 0x44, - 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, - 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, - 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, - 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, - 0x55, 0x52, 0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x02, 0x12, - 0x1f, 0x0a, 0x1b, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, - 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x45, 0x52, 0x52, 0x10, 0x03, - 0x12, 0x24, 0x0a, 0x20, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, - 0x52, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x50, 0x41, 0x52, 0x41, 0x4d, - 0x45, 0x54, 0x45, 0x52, 0x10, 0x04, 0x32, 0xb9, 0x27, 0x0a, 0x09, 0x4c, 0x69, 0x67, 0x68, 0x74, - 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x4a, 0x0a, 0x0d, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x42, 0x61, - 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x61, - 0x6c, 0x6c, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x61, 0x6c, 0x6c, 0x65, - 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x4d, 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, - 0x63, 0x65, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, - 0x65, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, - 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x4b, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x44, 0x0a, 0x0b, - 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x12, 0x19, 0x2e, 0x6c, 0x6e, - 0x72, 0x70, 0x63, 0x2e, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x45, - 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x09, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x12, - 0x17, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x69, 0x6e, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x6e, - 0x74, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, - 0x73, 0x70, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x6e, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x15, 0x53, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x62, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x30, 0x01, 0x12, 0x3b, 0x0a, 0x08, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x61, - 0x6e, 0x79, 0x12, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x4d, - 0x61, 0x6e, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x61, 0x6e, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0a, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x12, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, - 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, - 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x0d, - 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, - 0x0a, 0x0e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, - 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, - 0x09, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x12, 0x17, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, - 0x13, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x50, 0x65, 0x65, 0x72, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x65, 0x65, - 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x1a, 0x10, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x38, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, - 0x6f, 0x12, 0x15, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, - 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x47, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x44, 0x65, 0x62, 0x75, 0x67, 0x49, 0x6e, 0x66, 0x6f, - 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x62, 0x75, - 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x62, 0x75, 0x67, 0x49, 0x6e, 0x66, - 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0f, 0x47, 0x65, 0x74, - 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x2e, 0x6c, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, - 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6c, 0x6e, - 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x49, - 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0f, 0x50, - 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x12, 0x1d, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x68, - 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x61, - 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, - 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x12, 0x1a, 0x2e, + 0x4f, 0x50, 0x54, 0x10, 0x0b, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x54, 0x41, 0x54, 0x49, 0x43, 0x5f, + 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x0c, + 0x12, 0x19, 0x0a, 0x15, 0x53, 0x54, 0x41, 0x54, 0x49, 0x43, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x54, + 0x45, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x0d, 0x12, 0x14, 0x0a, 0x10, 0x50, + 0x41, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x52, 0x45, 0x51, 0x10, + 0x0e, 0x12, 0x14, 0x0a, 0x10, 0x50, 0x41, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x41, 0x44, 0x44, + 0x52, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x0f, 0x12, 0x0b, 0x0a, 0x07, 0x4d, 0x50, 0x50, 0x5f, 0x52, + 0x45, 0x51, 0x10, 0x10, 0x12, 0x0b, 0x0a, 0x07, 0x4d, 0x50, 0x50, 0x5f, 0x4f, 0x50, 0x54, 0x10, + 0x11, 0x12, 0x16, 0x0a, 0x12, 0x57, 0x55, 0x4d, 0x42, 0x4f, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x4e, + 0x45, 0x4c, 0x53, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x12, 0x12, 0x16, 0x0a, 0x12, 0x57, 0x55, 0x4d, + 0x42, 0x4f, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x53, 0x5f, 0x4f, 0x50, 0x54, 0x10, + 0x13, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x4e, 0x43, 0x48, 0x4f, 0x52, 0x53, 0x5f, 0x52, 0x45, 0x51, + 0x10, 0x14, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x4e, 0x43, 0x48, 0x4f, 0x52, 0x53, 0x5f, 0x4f, 0x50, + 0x54, 0x10, 0x15, 0x12, 0x1d, 0x0a, 0x19, 0x41, 0x4e, 0x43, 0x48, 0x4f, 0x52, 0x53, 0x5f, 0x5a, + 0x45, 0x52, 0x4f, 0x5f, 0x46, 0x45, 0x45, 0x5f, 0x48, 0x54, 0x4c, 0x43, 0x5f, 0x52, 0x45, 0x51, + 0x10, 0x16, 0x12, 0x1d, 0x0a, 0x19, 0x41, 0x4e, 0x43, 0x48, 0x4f, 0x52, 0x53, 0x5f, 0x5a, 0x45, + 0x52, 0x4f, 0x5f, 0x46, 0x45, 0x45, 0x5f, 0x48, 0x54, 0x4c, 0x43, 0x5f, 0x4f, 0x50, 0x54, 0x10, + 0x17, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x4d, 0x50, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x1e, 0x12, 0x0b, + 0x0a, 0x07, 0x41, 0x4d, 0x50, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x1f, 0x2a, 0xac, 0x01, 0x0a, 0x0d, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x12, 0x1a, 0x0a, + 0x16, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, + 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x55, 0x50, 0x44, + 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x50, 0x45, 0x4e, 0x44, + 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, + 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, + 0x44, 0x10, 0x02, 0x12, 0x1f, 0x0a, 0x1b, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, + 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x45, + 0x52, 0x52, 0x10, 0x03, 0x12, 0x24, 0x0a, 0x20, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, + 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x50, + 0x41, 0x52, 0x41, 0x4d, 0x45, 0x54, 0x45, 0x52, 0x10, 0x04, 0x32, 0xb9, 0x27, 0x0a, 0x09, 0x4c, + 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x4a, 0x0a, 0x0d, 0x57, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, + 0x63, 0x2e, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x57, + 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, + 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, + 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, + 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, + 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, + 0x12, 0x44, 0x0a, 0x0b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x12, + 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, + 0x46, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x09, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x6f, + 0x69, 0x6e, 0x73, 0x12, 0x17, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, + 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, + 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, + 0x73, 0x70, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, 0x73, + 0x70, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x15, + 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, + 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x30, 0x01, 0x12, 0x3b, 0x0a, 0x08, 0x53, 0x65, + 0x6e, 0x64, 0x4d, 0x61, 0x6e, 0x79, 0x12, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, + 0x65, 0x6e, 0x64, 0x4d, 0x61, 0x6e, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x61, 0x6e, 0x79, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0a, 0x4e, 0x65, 0x77, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, + 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x53, 0x69, + 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, + 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, + 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x4a, 0x0a, 0x0d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x12, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x12, 0x19, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x50, 0x65, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x69, 0x73, + 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x3e, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x12, 0x17, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x47, 0x0a, 0x13, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x50, 0x65, + 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, + 0x2e, 0x50, 0x65, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x10, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, + 0x65, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x38, 0x0a, 0x07, 0x47, 0x65, + 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x15, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, + 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x6c, + 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x44, 0x65, 0x62, 0x75, 0x67, + 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, + 0x44, 0x65, 0x62, 0x75, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x62, 0x75, + 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, + 0x0f, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, + 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x6f, + 0x76, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x50, 0x0a, 0x0f, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, + 0x6c, 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, + 0x6e, 0x67, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, + 0x67, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x47, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, + 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, + 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, - 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, - 0x69, 0x62, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, - 0x12, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, - 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x30, 0x01, 0x12, 0x4d, - 0x0a, 0x0e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, - 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x43, - 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x43, 0x68, 0x61, - 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, - 0x0f, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x53, 0x79, 0x6e, 0x63, - 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, - 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, - 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x69, 0x6e, 0x74, - 0x12, 0x43, 0x0a, 0x0b, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, - 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, - 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x30, 0x01, 0x12, 0x53, 0x0a, 0x10, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, - 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, - 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, - 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x10, 0x46, 0x75, - 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x74, 0x65, 0x70, 0x12, 0x1b, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x67, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, - 0x72, 0x70, 0x63, 0x2e, 0x46, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x53, 0x74, 0x65, 0x70, 0x52, 0x65, 0x73, 0x70, 0x12, 0x50, 0x0a, 0x0f, 0x43, 0x68, 0x61, 0x6e, - 0x6e, 0x65, 0x6c, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, - 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x41, 0x63, 0x63, 0x65, 0x70, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x46, 0x0a, 0x0c, 0x43, 0x6c, - 0x6f, 0x73, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, - 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x30, 0x01, 0x12, 0x4d, 0x0a, 0x0e, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x43, 0x68, 0x61, - 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x62, 0x61, - 0x6e, 0x64, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x62, 0x61, 0x6e, 0x64, - 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x3f, 0x0a, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, - 0x12, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x88, 0x02, 0x01, 0x28, 0x01, - 0x30, 0x01, 0x12, 0x3a, 0x0a, 0x0f, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, - 0x74, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, - 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, - 0x0a, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x19, 0x2e, + 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x16, 0x53, 0x75, + 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, + 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, + 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x30, 0x01, 0x12, 0x4d, 0x0a, 0x0e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x43, 0x68, 0x61, 0x6e, + 0x6e, 0x65, 0x6c, 0x73, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, + 0x73, 0x65, 0x64, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, + 0x64, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x41, 0x0a, 0x0f, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, + 0x53, 0x79, 0x6e, 0x63, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x70, 0x65, + 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, + 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x43, 0x0a, 0x0b, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, + 0x6e, 0x65, 0x6c, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x70, 0x65, 0x6e, + 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x30, 0x01, 0x12, 0x53, 0x0a, 0x10, 0x42, 0x61, 0x74, + 0x63, 0x68, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1e, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x6e, 0x43, + 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x6e, 0x43, + 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, + 0x0a, 0x10, 0x46, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x74, + 0x65, 0x70, 0x12, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x75, 0x6e, 0x64, 0x69, + 0x6e, 0x67, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x67, 0x1a, + 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x53, 0x74, 0x65, 0x70, 0x52, 0x65, 0x73, 0x70, 0x12, 0x50, 0x0a, 0x0f, + 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x12, + 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x41, + 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x1b, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x41, 0x63, 0x63, + 0x65, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x46, + 0x0a, 0x0c, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1a, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x43, 0x68, 0x61, 0x6e, + 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x30, 0x01, 0x12, 0x4d, 0x0a, 0x0e, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, + 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, + 0x2e, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x41, + 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x61, 0x79, + 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, + 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, + 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x88, + 0x02, 0x01, 0x28, 0x01, 0x30, 0x01, 0x12, 0x3a, 0x0a, 0x0f, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x61, + 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, + 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, + 0x65, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, + 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, + 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x03, 0x88, 0x02, 0x01, 0x28, 0x01, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0f, 0x53, 0x65, + 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x88, - 0x02, 0x01, 0x28, 0x01, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0f, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x41, 0x64, 0x64, - 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x0e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x41, 0x64, 0x64, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, - 0x65, 0x73, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, - 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x0d, 0x4c, 0x6f, 0x6f, - 0x6b, 0x75, 0x70, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x12, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x0e, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x41, - 0x0a, 0x11, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, - 0x63, 0x65, 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, - 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, - 0x0e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x30, - 0x01, 0x12, 0x32, 0x0a, 0x0c, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x50, 0x61, 0x79, 0x52, 0x65, - 0x71, 0x12, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, 0x79, 0x52, 0x65, 0x71, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x1a, 0x0d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, - 0x61, 0x79, 0x52, 0x65, 0x71, 0x12, 0x47, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x79, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, - 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, - 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, - 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, - 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6c, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, - 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x11, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, - 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, - 0x6c, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, - 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x40, 0x0a, 0x0d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x47, 0x72, - 0x61, 0x70, 0x68, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, - 0x6e, 0x65, 0x6c, 0x47, 0x72, 0x61, 0x70, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x47, - 0x72, 0x61, 0x70, 0x68, 0x12, 0x47, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x4d, - 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, - 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4d, 0x65, - 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, - 0x0b, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x6c, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, - 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x64, 0x67, 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4e, - 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x0f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, - 0x12, 0x44, 0x0a, 0x0b, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, - 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x6f, 0x75, - 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, - 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x74, 0x77, - 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x35, 0x0a, 0x0a, 0x53, 0x74, 0x6f, 0x70, 0x44, - 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x12, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, - 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, - 0x0a, 0x15, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, - 0x65, 0x6c, 0x47, 0x72, 0x61, 0x70, 0x68, 0x12, 0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x47, 0x72, 0x61, 0x70, 0x68, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x53, 0x75, 0x62, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0a, 0x44, 0x65, 0x62, 0x75, 0x67, - 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, - 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, - 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x09, 0x46, 0x65, - 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x17, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x46, 0x65, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x65, 0x65, 0x52, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x13, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x11, 0x46, 0x6f, - 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, - 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, - 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, - 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x13, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x68, 0x61, 0x6e, - 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x21, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, - 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x6c, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, - 0x75, 0x70, 0x12, 0x54, 0x0a, 0x17, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x41, 0x6c, 0x6c, 0x43, - 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12, 0x1e, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, - 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, - 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x4e, 0x0a, 0x10, 0x56, 0x65, 0x72, 0x69, - 0x66, 0x79, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x19, 0x2e, 0x6c, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, - 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x1a, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, + 0x0a, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x0e, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, + 0x76, 0x6f, 0x69, 0x63, 0x65, 0x73, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, + 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, + 0x0d, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x12, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x61, + 0x73, 0x68, 0x1a, 0x0e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x69, + 0x63, 0x65, 0x12, 0x41, 0x0a, 0x11, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x49, + 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x1a, 0x0e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, + 0x69, 0x63, 0x65, 0x30, 0x01, 0x12, 0x32, 0x0a, 0x0c, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x50, + 0x61, 0x79, 0x52, 0x65, 0x71, 0x12, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, + 0x79, 0x52, 0x65, 0x71, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x1a, 0x0d, 0x2e, 0x6c, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x50, 0x61, 0x79, 0x52, 0x65, 0x71, 0x12, 0x47, 0x0a, 0x0c, 0x4c, 0x69, 0x73, + 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, + 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, + 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, + 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, + 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x12, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x0d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x62, 0x65, 0x47, 0x72, 0x61, 0x70, 0x68, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x47, 0x72, 0x61, 0x70, 0x68, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, + 0x6e, 0x65, 0x6c, 0x47, 0x72, 0x61, 0x70, 0x68, 0x12, 0x47, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4e, + 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, + 0x64, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x39, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x49, 0x6e, 0x66, 0x6f, + 0x12, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x49, 0x6e, 0x66, + 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, + 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x64, 0x67, 0x65, 0x12, 0x36, 0x0a, 0x0b, + 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, + 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x44, 0x0a, 0x0b, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x6f, 0x75, + 0x74, 0x65, 0x73, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x6f, 0x75, 0x74, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x0e, 0x47, 0x65, + 0x74, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x2e, 0x6c, + 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x35, 0x0a, 0x0a, 0x53, + 0x74, 0x6f, 0x70, 0x44, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x12, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, + 0x63, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x57, 0x0a, 0x15, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43, + 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x47, 0x72, 0x61, 0x70, 0x68, 0x12, 0x20, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, + 0x79, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x1a, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x54, 0x6f, 0x70, 0x6f, 0x6c, + 0x6f, 0x67, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0a, 0x44, + 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, + 0x63, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x62, 0x75, + 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, + 0x0a, 0x09, 0x46, 0x65, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x17, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x46, 0x65, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x65, 0x65, + 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, + 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, + 0x0a, 0x11, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, + 0x6f, 0x72, 0x79, 0x12, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, 0x77, + 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, + 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x13, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, + 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x21, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x68, 0x61, 0x6e, + 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x14, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, + 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x54, 0x0a, 0x17, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, + 0x41, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, + 0x73, 0x12, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, + 0x63, 0x6b, 0x75, 0x70, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, + 0x63, 0x6b, 0x75, 0x70, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x4e, 0x0a, 0x10, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x74, - 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, - 0x73, 0x12, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, - 0x65, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x6f, - 0x72, 0x65, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x58, 0x0a, 0x17, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43, 0x68, 0x61, - 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12, 0x20, 0x2e, 0x6c, 0x6e, - 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, - 0x70, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x19, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, - 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x30, 0x01, 0x12, 0x47, 0x0a, 0x0c, 0x42, 0x61, - 0x6b, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, + 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, + 0x6b, 0x75, 0x70, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x1a, 0x1f, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, + 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x15, + 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, + 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, + 0x73, 0x74, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, + 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x17, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, + 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12, + 0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, + 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, + 0x63, 0x6b, 0x75, 0x70, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x30, 0x01, 0x12, 0x47, + 0x0a, 0x0c, 0x42, 0x61, 0x6b, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x12, 0x1a, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x6b, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, + 0x6f, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x6b, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x42, - 0x61, 0x6b, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x61, 0x72, - 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, - 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x12, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, - 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, - 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0f, 0x4c, 0x69, - 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1d, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6c, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x18, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x50, 0x65, 0x72, - 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x56, 0x0a, 0x15, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x50, 0x43, - 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x52, 0x50, 0x43, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x52, 0x50, 0x43, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x56, 0x0a, 0x11, 0x53, 0x65, 0x6e, - 0x64, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1f, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x75, 0x73, 0x74, 0x6f, - 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x75, 0x73, 0x74, - 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x58, 0x0a, 0x17, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43, 0x75, - 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x25, 0x2e, 0x6c, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43, 0x75, - 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75, 0x73, 0x74, - 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x30, 0x01, 0x12, 0x44, 0x0a, 0x0b, 0x4c, - 0x69, 0x73, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x5f, 0x0a, 0x14, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x48, 0x74, 0x6c, 0x63, 0x52, - 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x48, 0x74, 0x6c, 0x63, 0x52, 0x65, 0x73, 0x6f, - 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x4d, + 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, + 0x44, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, + 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x10, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x12, 0x1e, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x61, + 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x61, + 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, + 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, + 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, + 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x53, 0x0a, 0x18, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, + 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1a, 0x2e, 0x6c, + 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x50, 0x65, 0x72, + 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, + 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x15, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, + 0x72, 0x52, 0x50, 0x43, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x12, 0x1c, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x50, 0x43, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, + 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x1b, 0x2e, 0x6c, + 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x50, 0x43, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, + 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x56, 0x0a, + 0x11, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x12, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x43, + 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, + 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x17, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, + 0x62, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, + 0x12, 0x25, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, + 0x62, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x30, 0x01, 0x12, + 0x44, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x12, 0x19, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, + 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x14, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x48, + 0x74, 0x6c, 0x63, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x48, 0x74, 0x6c, 0x63, - 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x2f, 0x6c, 0x6e, 0x64, 0x2f, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x23, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, + 0x48, 0x74, 0x6c, 0x63, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x6e, 0x65, + 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x6c, 0x6e, 0x64, 0x2f, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/lnrpc/lightning.proto b/lnrpc/lightning.proto index 7a343b491..162dc35f9 100644 --- a/lnrpc/lightning.proto +++ b/lnrpc/lightning.proto @@ -4231,6 +4231,10 @@ message DeleteAllPaymentsRequest { Only delete failed HTLCs from payments, not the payment itself. */ bool failed_htlcs_only = 2; + + // Delete all payments. NOTE: Using this option requires careful + // consideration as it is a destructive operation. + bool all_payments = 3; } message DeletePaymentResponse { diff --git a/lnrpc/lightning.swagger.json b/lnrpc/lightning.swagger.json index 3c1b2a810..c0ea92d82 100644 --- a/lnrpc/lightning.swagger.json +++ b/lnrpc/lightning.swagger.json @@ -2268,6 +2268,13 @@ "in": "query", "required": false, "type": "boolean" + }, + { + "name": "all_payments", + "description": "Delete all payments. NOTE: Using this option requires careful\nconsideration as it is a destructive operation.", + "in": "query", + "required": false, + "type": "boolean" } ], "tags": [ From 5c3015b223bf12af886dfe965ff742bd33745a7c Mon Sep 17 00:00:00 2001 From: Mohamed Awnallah Date: Sun, 21 Apr 2024 22:43:12 +0200 Subject: [PATCH 016/109] rpcserver: validate `DeleteAllPayments` options --- rpcserver.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/rpcserver.go b/rpcserver.go index 810ac2630..fad2cc307 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -6763,6 +6763,27 @@ func (r *rpcServer) DeleteAllPayments(ctx context.Context, req *lnrpc.DeleteAllPaymentsRequest) ( *lnrpc.DeleteAllPaymentsResponse, error) { + switch { + // Since this is a destructive operation, at least one of the options + // must be set to true. + case !req.AllPayments && !req.FailedPaymentsOnly && + !req.FailedHtlcsOnly: + + return nil, fmt.Errorf("at least one of the options " + + "`all_payments`, `failed_payments_only`, or " + + "`failed_htlcs_only` must be set to true") + + // `all_payments` cannot be true with `failed_payments_only` or + // `failed_htlcs_only`. `all_payments` includes all records, making + // these options contradictory. + case req.AllPayments && + (req.FailedPaymentsOnly || req.FailedHtlcsOnly): + + return nil, fmt.Errorf("`all_payments` cannot be set to true " + + "while either `failed_payments_only` or " + + "`failed_htlcs_only` is also set to true") + } + rpcsLog.Infof("[DeleteAllPayments] failed_payments_only=%v, "+ "failed_htlcs_only=%v", req.FailedPaymentsOnly, req.FailedHtlcsOnly) From 3364d2f2d66f96d4621ec59978ad44934508f26a Mon Sep 17 00:00:00 2001 From: Mohamed Awnallah Date: Sun, 21 Apr 2024 23:19:39 +0200 Subject: [PATCH 017/109] lntest: delete all payments in `DeleteAllPayments` --- lntest/rpc/lnd.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lntest/rpc/lnd.go b/lntest/rpc/lnd.go index 8f55271f8..e800b9ca4 100644 --- a/lntest/rpc/lnd.go +++ b/lntest/rpc/lnd.go @@ -70,7 +70,7 @@ func (h *HarnessRPC) DeleteAllPayments() { ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout) defer cancel() - req := &lnrpc.DeleteAllPaymentsRequest{} + req := &lnrpc.DeleteAllPaymentsRequest{AllPayments: true} _, err := h.LN.DeleteAllPayments(ctxt, req) h.NoError(err, "DeleteAllPayments") } From 6e1d9b8d6aa8536d0745b2d8a0ba6fbe5c772106 Mon Sep 17 00:00:00 2001 From: Mohamed Awnallah Date: Mon, 22 Apr 2024 11:50:57 +0200 Subject: [PATCH 018/109] lncli: update `AllPayments` in `deletePayments` --- cmd/lncli/cmd_payments.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/lncli/cmd_payments.go b/cmd/lncli/cmd_payments.go index 550bb8f3e..051769afc 100644 --- a/cmd/lncli/cmd_payments.go +++ b/cmd/lncli/cmd_payments.go @@ -1783,6 +1783,7 @@ func deletePayments(ctx *cli.Context) error { what) _, err = client.DeleteAllPayments( ctxc, &lnrpc.DeleteAllPaymentsRequest{ + AllPayments: includeNonFailed, FailedPaymentsOnly: !includeNonFailed, FailedHtlcsOnly: failedHTLCsOnly, }, From b683b385cd24804b4fe184d0dcb1f0525e374891 Mon Sep 17 00:00:00 2001 From: Mohamed Awnallah Date: Sun, 21 Apr 2024 22:53:11 +0200 Subject: [PATCH 019/109] docs: update release-notes-0.18.0.md --- docs/release-notes/release-notes-0.18.0.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/release-notes/release-notes-0.18.0.md b/docs/release-notes/release-notes-0.18.0.md index f59ae179b..9170114a0 100644 --- a/docs/release-notes/release-notes-0.18.0.md +++ b/docs/release-notes/release-notes-0.18.0.md @@ -355,6 +355,12 @@ bitcoin peers' feefilter values into account](https://github.com/lightningnetwor `budget`, and `deadline_height`, the fields `force`, `requested_conf_target`, and `next_broadcast_height` are deprecated. +* [Delete All Payments RPC](https://github.com/lightningnetwork/lnd/pull/8672) + adds `all_payments` option to the `DeleteAllPayments` RPC. This update + ensures that the arguments are provided when calling `DeleteAllPayments` RPC, + whether through gRPC or the REST API, due to the destructive nature of the + operation. + ## lncli Updates * [Documented all available `lncli` From 619c8f4eb84eee8337909f9f112d49c997910693 Mon Sep 17 00:00:00 2001 From: erik Date: Tue, 13 Jun 2023 20:17:03 +0700 Subject: [PATCH 020/109] multi: repleace ioutil.ReadAll --- chainreg/chainregistry.go | 4 ++-- channeldb/migration/lnwire21/announcement_signatures.go | 3 +-- channeldb/migration/lnwire21/channel_announcement.go | 3 +-- channeldb/migration/lnwire21/channel_update.go | 3 +-- channeldb/migration/lnwire21/node_announcement.go | 3 +-- cmd/lncli/cmd_payments.go | 4 ++-- config.go | 5 +++-- contractcourt/htlc_incoming_contest_resolver_test.go | 3 +-- 8 files changed, 12 insertions(+), 16 deletions(-) diff --git a/chainreg/chainregistry.go b/chainreg/chainregistry.go index 036da71a5..8b562e87a 100644 --- a/chainreg/chainregistry.go +++ b/chainreg/chainregistry.go @@ -5,7 +5,7 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "io" "net" "net/url" "os" @@ -547,7 +547,7 @@ func NewPartialChainControl(cfg *Config) (*PartialChainControl, func(), error) { if err != nil { return nil, nil, err } - rpcCert, err = ioutil.ReadAll(certFile) + rpcCert, err = io.ReadAll(certFile) if err != nil { return nil, nil, err } diff --git a/channeldb/migration/lnwire21/announcement_signatures.go b/channeldb/migration/lnwire21/announcement_signatures.go index 639704de0..4c2166a8d 100644 --- a/channeldb/migration/lnwire21/announcement_signatures.go +++ b/channeldb/migration/lnwire21/announcement_signatures.go @@ -2,7 +2,6 @@ package lnwire import ( "io" - "io/ioutil" ) // AnnounceSignatures is a direct message between two endpoints of a @@ -66,7 +65,7 @@ func (a *AnnounceSignatures) Decode(r io.Reader, pver uint32) error { // we'll collect the remainder into the ExtraOpaqueData field. If there // aren't any bytes, then we'll snip off the slice to avoid carrying // around excess capacity. - a.ExtraOpaqueData, err = ioutil.ReadAll(r) + a.ExtraOpaqueData, err = io.ReadAll(r) if err != nil { return err } diff --git a/channeldb/migration/lnwire21/channel_announcement.go b/channeldb/migration/lnwire21/channel_announcement.go index 46efeed88..897844fb1 100644 --- a/channeldb/migration/lnwire21/channel_announcement.go +++ b/channeldb/migration/lnwire21/channel_announcement.go @@ -3,7 +3,6 @@ package lnwire import ( "bytes" "io" - "io/ioutil" "github.com/btcsuite/btcd/chaincfg/chainhash" ) @@ -89,7 +88,7 @@ func (a *ChannelAnnouncement) Decode(r io.Reader, pver uint32) error { // we'll collect the remainder into the ExtraOpaqueData field. If there // aren't any bytes, then we'll snip off the slice to avoid carrying // around excess capacity. - a.ExtraOpaqueData, err = ioutil.ReadAll(r) + a.ExtraOpaqueData, err = io.ReadAll(r) if err != nil { return err } diff --git a/channeldb/migration/lnwire21/channel_update.go b/channeldb/migration/lnwire21/channel_update.go index 6d19e3e4c..77e65e76b 100644 --- a/channeldb/migration/lnwire21/channel_update.go +++ b/channeldb/migration/lnwire21/channel_update.go @@ -4,7 +4,6 @@ import ( "bytes" "fmt" "io" - "io/ioutil" "github.com/btcsuite/btcd/chaincfg/chainhash" ) @@ -160,7 +159,7 @@ func (a *ChannelUpdate) Decode(r io.Reader, pver uint32) error { // we'll collect the remainder into the ExtraOpaqueData field. If there // aren't any bytes, then we'll snip off the slice to avoid carrying // around excess capacity. - a.ExtraOpaqueData, err = ioutil.ReadAll(r) + a.ExtraOpaqueData, err = io.ReadAll(r) if err != nil { return err } diff --git a/channeldb/migration/lnwire21/node_announcement.go b/channeldb/migration/lnwire21/node_announcement.go index 8550fddd3..51cf7367b 100644 --- a/channeldb/migration/lnwire21/node_announcement.go +++ b/channeldb/migration/lnwire21/node_announcement.go @@ -5,7 +5,6 @@ import ( "fmt" "image/color" "io" - "io/ioutil" "net" "unicode/utf8" ) @@ -127,7 +126,7 @@ func (a *NodeAnnouncement) Decode(r io.Reader, pver uint32) error { // we'll collect the remainder into the ExtraOpaqueData field. If there // aren't any bytes, then we'll snip off the slice to avoid carrying // around excess capacity. - a.ExtraOpaqueData, err = ioutil.ReadAll(r) + a.ExtraOpaqueData, err = io.ReadAll(r) if err != nil { return err } diff --git a/cmd/lncli/cmd_payments.go b/cmd/lncli/cmd_payments.go index 550bb8f3e..f9d01ad60 100644 --- a/cmd/lncli/cmd_payments.go +++ b/cmd/lncli/cmd_payments.go @@ -7,7 +7,7 @@ import ( "encoding/hex" "errors" "fmt" - "io/ioutil" + "io" "os" "runtime" "strconv" @@ -987,7 +987,7 @@ func sendToRoute(ctx *cli.Context) error { // The user is signalling that we should read stdin in order to parse // the set of target routes. case args.Present() && args.First() == "-": - b, err := ioutil.ReadAll(os.Stdin) + b, err := io.ReadAll(os.Stdin) if err != nil { return err } diff --git a/config.go b/config.go index f746be041..8a347948b 100644 --- a/config.go +++ b/config.go @@ -8,6 +8,7 @@ import ( "encoding/hex" "errors" "fmt" + "io" "io/ioutil" "net" "os" @@ -2006,7 +2007,7 @@ func extractBtcdRPCParams(btcdConfigPath string) (string, string, error) { // With the file open extract the contents of the configuration file so // we can attempt to locate the RPC credentials. - configContents, err := ioutil.ReadAll(btcdConfigFile) + configContents, err := io.ReadAll(btcdConfigFile) if err != nil { return "", "", err } @@ -2056,7 +2057,7 @@ func extractBitcoindRPCParams(networkName, bitcoindDataDir, bitcoindConfigPath, // With the file open extract the contents of the configuration file so // we can attempt to locate the RPC credentials. - configContents, err := ioutil.ReadAll(bitcoindConfigFile) + configContents, err := io.ReadAll(bitcoindConfigFile) if err != nil { return "", "", "", "", err } diff --git a/contractcourt/htlc_incoming_contest_resolver_test.go b/contractcourt/htlc_incoming_contest_resolver_test.go index a87b1991c..6c4ba6bc4 100644 --- a/contractcourt/htlc_incoming_contest_resolver_test.go +++ b/contractcourt/htlc_incoming_contest_resolver_test.go @@ -3,7 +3,6 @@ package contractcourt import ( "bytes" "io" - "io/ioutil" "testing" sphinx "github.com/lightningnetwork/lightning-onion" @@ -291,7 +290,7 @@ type mockOnionProcessor struct { func (o *mockOnionProcessor) ReconstructHopIterator(r io.Reader, rHash []byte, _ hop.ReconstructBlindingInfo) (hop.Iterator, error) { - data, err := ioutil.ReadAll(r) + data, err := io.ReadAll(r) if err != nil { return nil, err } From ab83343c8718e292c8e392949318678e93df3e56 Mon Sep 17 00:00:00 2001 From: erik Date: Tue, 13 Jun 2023 21:22:44 +0700 Subject: [PATCH 021/109] multi: repleace ioutil.ReadFile --- cert/selfsigned_test.go | 18 +++++++++--------- cert/tls.go | 6 +++--- chanbackup/backupfile.go | 3 +-- chanbackup/backupfile_test.go | 3 +-- cmd/lncli/cmd_macaroon.go | 5 +++-- cmd/lncli/cmd_open_channel.go | 3 +-- cmd/lncli/cmd_profile.go | 3 +-- cmd/lncli/cmd_walletunlocker.go | 3 +-- cmd/lncli/commands.go | 3 +-- cmd/lncli/profile.go | 7 ++++--- config.go | 5 ++--- config_builder.go | 3 +-- itest/lnd_channel_backup_test.go | 13 ++++++------- itest/lnd_misc_test.go | 6 +++--- kvdb/backend.go | 2 +- lnd.go | 3 +-- lntest/node/harness_node.go | 2 +- lnwallet/rpcwallet/rpcwallet.go | 6 +++--- lnwallet/transactions_test.go | 4 ++-- routing/pathfind_test.go | 4 ++-- tls_manager_test.go | 9 +++++---- tor/cmd_onion.go | 2 +- tor/controller.go | 4 ++-- 23 files changed, 55 insertions(+), 62 deletions(-) diff --git a/cert/selfsigned_test.go b/cert/selfsigned_test.go index 614225a5a..ca55c2772 100644 --- a/cert/selfsigned_test.go +++ b/cert/selfsigned_test.go @@ -1,7 +1,7 @@ package cert_test import ( - "io/ioutil" + "os" "path/filepath" "testing" "time" @@ -42,10 +42,10 @@ func TestIsOutdatedCert(t *testing.T) { // number of IPs and domains. for numIPs := 1; numIPs <= len(extraIPs); numIPs++ { for numDomains := 1; numDomains <= len(extraDomains); numDomains++ { - certBytes, err := ioutil.ReadFile(certPath) + certBytes, err := os.ReadFile(certPath) require.NoError(t, err) - keyBytes, err := ioutil.ReadFile(keyPath) + keyBytes, err := os.ReadFile(keyPath) require.NoError(t, err) _, parsedCert, err := cert.LoadCertFromBytes( @@ -98,10 +98,10 @@ func TestIsOutdatedPermutation(t *testing.T) { err = cert.WriteCertPair(certPath, keyPath, certBytes, keyBytes) require.NoError(t, err) - certBytes, err = ioutil.ReadFile(certPath) + certBytes, err = os.ReadFile(certPath) require.NoError(t, err) - keyBytes, err = ioutil.ReadFile(keyPath) + keyBytes, err = os.ReadFile(keyPath) require.NoError(t, err) _, parsedCert, err := cert.LoadCertFromBytes(certBytes, keyBytes) @@ -171,10 +171,10 @@ func TestTLSDisableAutofill(t *testing.T) { require.NoError(t, err) // Read certs from disk. - certBytes, err = ioutil.ReadFile(certPath) + certBytes, err = os.ReadFile(certPath) require.NoError(t, err) - keyBytes, err = ioutil.ReadFile(keyPath) + keyBytes, err = os.ReadFile(keyPath) require.NoError(t, err) // Load the certificate. @@ -230,10 +230,10 @@ func TestTLSConfig(t *testing.T) { err = cert.WriteCertPair(certPath, keyPath, certBytes, keyBytes) require.NoError(t, err) - certBytes, err = ioutil.ReadFile(certPath) + certBytes, err = os.ReadFile(certPath) require.NoError(t, err) - keyBytes, err = ioutil.ReadFile(keyPath) + keyBytes, err = os.ReadFile(keyPath) require.NoError(t, err) // Load the certificate. diff --git a/cert/tls.go b/cert/tls.go index 4e5d7c81e..6f60ae198 100644 --- a/cert/tls.go +++ b/cert/tls.go @@ -3,7 +3,7 @@ package cert import ( "crypto/tls" "crypto/x509" - "io/ioutil" + "os" "sync" ) @@ -31,11 +31,11 @@ var ( func GetCertBytesFromPath(certPath, keyPath string) (certBytes, keyBytes []byte, err error) { - certBytes, err = ioutil.ReadFile(certPath) + certBytes, err = os.ReadFile(certPath) if err != nil { return nil, nil, err } - keyBytes, err = ioutil.ReadFile(keyPath) + keyBytes, err = os.ReadFile(keyPath) if err != nil { return nil, nil, err } diff --git a/chanbackup/backupfile.go b/chanbackup/backupfile.go index 9c1e788c1..5ba6aa756 100644 --- a/chanbackup/backupfile.go +++ b/chanbackup/backupfile.go @@ -2,7 +2,6 @@ package chanbackup import ( "fmt" - "io/ioutil" "os" "path/filepath" @@ -138,7 +137,7 @@ func (b *MultiFile) ExtractMulti(keyChain keychain.KeyRing) (*Multi, error) { // Now that we've confirmed the target file is populated, we'll read // all the contents of the file. This function ensures that file is // always closed, even if we can't read the contents. - multiBytes, err := ioutil.ReadFile(b.fileName) + multiBytes, err := os.ReadFile(b.fileName) if err != nil { return nil, err } diff --git a/chanbackup/backupfile_test.go b/chanbackup/backupfile_test.go index fbd0cc7dd..b0d3ba66f 100644 --- a/chanbackup/backupfile_test.go +++ b/chanbackup/backupfile_test.go @@ -3,7 +3,6 @@ package chanbackup import ( "bytes" "fmt" - "io/ioutil" "math/rand" "os" "path/filepath" @@ -27,7 +26,7 @@ func assertBackupMatches(t *testing.T, filePath string, t.Helper() - packedBackup, err := ioutil.ReadFile(filePath) + packedBackup, err := os.ReadFile(filePath) require.NoError(t, err, "unable to test file") if !bytes.Equal(packedBackup, currentBackup) { diff --git a/cmd/lncli/cmd_macaroon.go b/cmd/lncli/cmd_macaroon.go index 54e03057a..894e8da6b 100644 --- a/cmd/lncli/cmd_macaroon.go +++ b/cmd/lncli/cmd_macaroon.go @@ -6,6 +6,7 @@ import ( "fmt" "io/ioutil" "net" + "os" "strconv" "strings" "unicode" @@ -352,7 +353,7 @@ func printMacaroon(ctx *cli.Context) error { macPath := lncfg.CleanAndExpandPath(ctx.String("macaroon_file")) // Load the specified macaroon file. - macBytes, err = ioutil.ReadFile(macPath) + macBytes, err = os.ReadFile(macPath) if err != nil { return fmt.Errorf("unable to read macaroon path %v: %v", macPath, err) @@ -441,7 +442,7 @@ func constrainMacaroon(ctx *cli.Context) error { sourceMacFile := lncfg.CleanAndExpandPath(args.First()) args = args.Tail() - sourceMacBytes, err := ioutil.ReadFile(sourceMacFile) + sourceMacBytes, err := os.ReadFile(sourceMacFile) if err != nil { return fmt.Errorf("error trying to read source macaroon file "+ "%s: %v", sourceMacFile, err) diff --git a/cmd/lncli/cmd_open_channel.go b/cmd/lncli/cmd_open_channel.go index 74cb1668a..e3044c835 100644 --- a/cmd/lncli/cmd_open_channel.go +++ b/cmd/lncli/cmd_open_channel.go @@ -9,7 +9,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "os" "strconv" "strings" @@ -1016,7 +1015,7 @@ func readTerminalOrFile(quit chan struct{}) (string, error) { // If it's a path to an existing file and it's small enough, let's try // to read its content now. - content, err := ioutil.ReadFile(maybeFile) + content, err := os.ReadFile(maybeFile) if err != nil { return "", err } diff --git a/cmd/lncli/cmd_profile.go b/cmd/lncli/cmd_profile.go index 21666be96..3b1bf6487 100644 --- a/cmd/lncli/cmd_profile.go +++ b/cmd/lncli/cmd_profile.go @@ -2,7 +2,6 @@ package main import ( "fmt" - "io/ioutil" "os" "path" "strings" @@ -423,7 +422,7 @@ func profileAddMacaroon(ctx *cli.Context) error { // Now load and possibly encrypt the macaroon file. macPath := lncfg.CleanAndExpandPath(ctx.GlobalString("macaroonpath")) - macBytes, err := ioutil.ReadFile(macPath) + macBytes, err := os.ReadFile(macPath) if err != nil { return fmt.Errorf("unable to read macaroon path: %w", err) } diff --git a/cmd/lncli/cmd_walletunlocker.go b/cmd/lncli/cmd_walletunlocker.go index 9227d10d4..650ef80ea 100644 --- a/cmd/lncli/cmd_walletunlocker.go +++ b/cmd/lncli/cmd_walletunlocker.go @@ -5,7 +5,6 @@ import ( "bytes" "encoding/hex" "fmt" - "io/ioutil" "os" "strconv" "strings" @@ -712,7 +711,7 @@ func createWatchOnly(ctx *cli.Context) error { } jsonFile := lncfg.CleanAndExpandPath(ctx.Args().First()) - jsonBytes, err := ioutil.ReadFile(jsonFile) + jsonBytes, err := os.ReadFile(jsonFile) if err != nil { return fmt.Errorf("error reading JSON from file %v: %v", jsonFile, err) diff --git a/cmd/lncli/commands.go b/cmd/lncli/commands.go index 5ffca5c73..a510138eb 100644 --- a/cmd/lncli/commands.go +++ b/cmd/lncli/commands.go @@ -9,7 +9,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "math" "os" "strconv" @@ -2833,7 +2832,7 @@ func parseChanBackups(ctx *cli.Context) (*lnrpc.RestoreChanBackupRequest, error) }, nil case ctx.IsSet("multi_file"): - packedMulti, err := ioutil.ReadFile(ctx.String("multi_file")) + packedMulti, err := os.ReadFile(ctx.String("multi_file")) if err != nil { return nil, fmt.Errorf("unable to decode multi packed "+ "backup: %v", err) diff --git a/cmd/lncli/profile.go b/cmd/lncli/profile.go index 90ac69c0e..75dc9ab72 100644 --- a/cmd/lncli/profile.go +++ b/cmd/lncli/profile.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "io/ioutil" + "os" "path" "strings" @@ -129,7 +130,7 @@ func profileFromContext(ctx *cli.Context, store, skipMacaroons bool) ( var tlsCert []byte if tlsCertPath != "" && !insecure { var err error - tlsCert, err = ioutil.ReadFile(tlsCertPath) + tlsCert, err = os.ReadFile(tlsCertPath) if err != nil { return nil, fmt.Errorf("could not load TLS cert "+ "file: %v", err) @@ -167,7 +168,7 @@ func profileFromContext(ctx *cli.Context, store, skipMacaroons bool) ( } // Now load and possibly encrypt the macaroon file. - macBytes, err := ioutil.ReadFile(macPath) + macBytes, err := os.ReadFile(macPath) if err != nil { return nil, fmt.Errorf("unable to read macaroon path (check "+ "the network setting!): %v", err) @@ -222,7 +223,7 @@ func loadProfileFile(file string) (*profileFile, error) { return nil, errNoProfileFile } - content, err := ioutil.ReadFile(file) + content, err := os.ReadFile(file) if err != nil { return nil, fmt.Errorf("could not load profile file %s: %w", file, err) diff --git a/config.go b/config.go index 8a347948b..7084500b4 100644 --- a/config.go +++ b/config.go @@ -9,7 +9,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "net" "os" "os/user" @@ -1846,7 +1845,7 @@ func parseRPCParams(cConfig *lncfg.Chain, nodeConfig interface{}, // We convert the cookie into a user name and password. if conf.RPCCookie != "" { - cookie, err := ioutil.ReadFile(conf.RPCCookie) + cookie, err := os.ReadFile(conf.RPCCookie) if err != nil { return fmt.Errorf("cannot read cookie file: %w", err) @@ -2119,7 +2118,7 @@ func extractBitcoindRPCParams(networkName, bitcoindDataDir, bitcoindConfigPath, if rpcCookiePath != "" { cookiePath = rpcCookiePath } - cookie, err := ioutil.ReadFile(cookiePath) + cookie, err := os.ReadFile(cookiePath) if err == nil { splitCookie := strings.Split(string(cookie), ":") if len(splitCookie) == 2 { diff --git a/config_builder.go b/config_builder.go index bbf291506..895f7e4ad 100644 --- a/config_builder.go +++ b/config_builder.go @@ -6,7 +6,6 @@ import ( "database/sql" "errors" "fmt" - "io/ioutil" "net" "os" "path/filepath" @@ -329,7 +328,7 @@ func (d *DefaultWalletImpl) BuildWalletConfig(ctx context.Context, case d.cfg.WalletUnlockPasswordFile != "" && walletExists: d.logger.Infof("Attempting automatic wallet unlock with " + "password provided in file") - pwBytes, err := ioutil.ReadFile(d.cfg.WalletUnlockPasswordFile) + pwBytes, err := os.ReadFile(d.cfg.WalletUnlockPasswordFile) if err != nil { return nil, nil, nil, fmt.Errorf("error reading "+ "password from file %s: %v", diff --git a/itest/lnd_channel_backup_test.go b/itest/lnd_channel_backup_test.go index c29859e32..0e7393dc3 100644 --- a/itest/lnd_channel_backup_test.go +++ b/itest/lnd_channel_backup_test.go @@ -3,7 +3,6 @@ package itest import ( "context" "fmt" - "io/ioutil" "os" "path/filepath" "strconv" @@ -285,7 +284,7 @@ func testChannelBackupRestoreBasic(ht *lntest.HarnessTest) { // Read the entire Multi backup stored within // this node's channel.backup file. - multi, err := ioutil.ReadFile(backupFilePath) + multi, err := os.ReadFile(backupFilePath) require.NoError(st, err) // Now that we have Dave's backup file, we'll @@ -376,7 +375,7 @@ func testChannelBackupRestoreBasic(ht *lntest.HarnessTest) { // Read the entire Multi backup stored within // this node's channel.backup file. - multi, err := ioutil.ReadFile(backupFilePath) + multi, err := os.ReadFile(backupFilePath) require.NoError(st, err) // Now that we have Dave's backup file, we'll @@ -501,7 +500,7 @@ func runChanRestoreScenarioUnConfirmed(ht *lntest.HarnessTest, useFile bool) { backupFilePath := dave.Cfg.ChanBackupPath() // Read the entire Multi backup stored within this node's // channel.backup file. - multi, err = ioutil.ReadFile(backupFilePath) + multi, err = os.ReadFile(backupFilePath) require.NoError(ht, err) } else { // For this restoration method, we'll grab the current @@ -646,7 +645,7 @@ func runChanRestoreScenarioCommitTypes(ht *lntest.HarnessTest, // Read the entire Multi backup stored within this node's // channels.backup file. - multi, err := ioutil.ReadFile(backupFilePath) + multi, err := os.ReadFile(backupFilePath) require.NoError(ht, err) // If this was a zero conf taproot channel, then since it's private, @@ -774,7 +773,7 @@ func runChanRestoreScenarioForceClose(ht *lntest.HarnessTest, zeroConf bool) { // Read the entire Multi backup stored within this node's // channel.backup file. - multi, err := ioutil.ReadFile(backupFilePath) + multi, err := os.ReadFile(backupFilePath) require.NoError(ht, err) // Now that we have Dave's backup file, we'll create a new nodeRestorer @@ -907,7 +906,7 @@ func testChannelBackupUpdates(ht *lntest.HarnessTest) { // the on disk back up file to our currentBackup pointer above. assertBackupFileState := func() { err := wait.NoError(func() error { - packedBackup, err := ioutil.ReadFile(backupFilePath) + packedBackup, err := os.ReadFile(backupFilePath) if err != nil { return fmt.Errorf("unable to read backup "+ "file: %v", err) diff --git a/itest/lnd_misc_test.go b/itest/lnd_misc_test.go index 7124f1488..163fc436d 100644 --- a/itest/lnd_misc_test.go +++ b/itest/lnd_misc_test.go @@ -4,7 +4,7 @@ import ( "context" "encoding/hex" "fmt" - "io/ioutil" + "os" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/txscript" @@ -708,7 +708,7 @@ func testAbandonChannel(ht *lntest.HarnessTest) { // To make sure the channel is removed from the backup file as well // when being abandoned, grab a backup snapshot so we can compare it // with the later state. - bkupBefore, err := ioutil.ReadFile(alice.Cfg.ChanBackupPath()) + bkupBefore, err := os.ReadFile(alice.Cfg.ChanBackupPath()) require.NoError(ht, err, "channel backup before abandoning channel") // Send request to abandon channel. @@ -733,7 +733,7 @@ func testAbandonChannel(ht *lntest.HarnessTest) { // Make sure the channel is no longer in the channel backup list. err = wait.NoError(func() error { - bkupAfter, err := ioutil.ReadFile(alice.Cfg.ChanBackupPath()) + bkupAfter, err := os.ReadFile(alice.Cfg.ChanBackupPath()) if err != nil { return fmt.Errorf("could not get channel backup "+ "before abandoning channel: %v", err) diff --git a/kvdb/backend.go b/kvdb/backend.go index f034cee7e..c115c4f7d 100644 --- a/kvdb/backend.go +++ b/kvdb/backend.go @@ -218,7 +218,7 @@ func lastCompactionDate(dbFile string) (time.Time, error) { return zeroTime, nil } - tsBytes, err := ioutil.ReadFile(tsFile) + tsBytes, err := os.ReadFile(tsFile) if err != nil { return zeroTime, err } diff --git a/lnd.go b/lnd.go index f4ef03a07..0a85e1bf3 100644 --- a/lnd.go +++ b/lnd.go @@ -8,7 +8,6 @@ import ( "context" "errors" "fmt" - "io/ioutil" "net" "net/http" "net/http/pprof" @@ -83,7 +82,7 @@ func AdminAuthOptions(cfg *Config, skipMacaroons bool) ([]grpc.DialOption, // Get the admin macaroon if macaroons are active. if !skipMacaroons && !cfg.NoMacaroons { // Load the admin macaroon file. - macBytes, err := ioutil.ReadFile(cfg.AdminMacPath) + macBytes, err := os.ReadFile(cfg.AdminMacPath) if err != nil { return nil, fmt.Errorf("unable to read macaroon "+ "path (check the network setting!): %v", err) diff --git a/lntest/node/harness_node.go b/lntest/node/harness_node.go index de6f40a77..1afb095d8 100644 --- a/lntest/node/harness_node.go +++ b/lntest/node/harness_node.go @@ -297,7 +297,7 @@ func (hn *HarnessNode) ReadMacaroon(macPath string, timeout time.Duration) ( // using it. var mac *macaroon.Macaroon err := wait.NoError(func() error { - macBytes, err := ioutil.ReadFile(macPath) + macBytes, err := os.ReadFile(macPath) if err != nil { return fmt.Errorf("error reading macaroon file: %w", err) diff --git a/lnwallet/rpcwallet/rpcwallet.go b/lnwallet/rpcwallet/rpcwallet.go index 5a16490e5..13f435579 100644 --- a/lnwallet/rpcwallet/rpcwallet.go +++ b/lnwallet/rpcwallet/rpcwallet.go @@ -7,7 +7,7 @@ import ( "crypto/x509" "errors" "fmt" - "io/ioutil" + "os" "time" "github.com/btcsuite/btcd/btcec/v2" @@ -1259,7 +1259,7 @@ func extractSignature(in *psbt.PInput, func connectRPC(hostPort, tlsCertPath, macaroonPath string, timeout time.Duration) (*grpc.ClientConn, error) { - certBytes, err := ioutil.ReadFile(tlsCertPath) + certBytes, err := os.ReadFile(tlsCertPath) if err != nil { return nil, fmt.Errorf("error reading TLS cert file %v: %w", tlsCertPath, err) @@ -1271,7 +1271,7 @@ func connectRPC(hostPort, tlsCertPath, macaroonPath string, "certificate") } - macBytes, err := ioutil.ReadFile(macaroonPath) + macBytes, err := os.ReadFile(macaroonPath) if err != nil { return nil, fmt.Errorf("error reading macaroon file %v: %w", macaroonPath, err) diff --git a/lnwallet/transactions_test.go b/lnwallet/transactions_test.go index ab0ef7328..1f15523c4 100644 --- a/lnwallet/transactions_test.go +++ b/lnwallet/transactions_test.go @@ -8,8 +8,8 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "net" + "os" "sort" "strings" "testing" @@ -229,7 +229,7 @@ func TestCommitmentAndHTLCTransactions(t *testing.T) { var testCases []testCase - jsonText, err := ioutil.ReadFile(set.jsonFile) + jsonText, err := os.ReadFile(set.jsonFile) require.NoError(t, err) err = json.Unmarshal(jsonText, &testCases) diff --git a/routing/pathfind_test.go b/routing/pathfind_test.go index de4935a81..57f723ce6 100644 --- a/routing/pathfind_test.go +++ b/routing/pathfind_test.go @@ -8,9 +8,9 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" "math" "net" + "os" "reflect" "strings" "testing" @@ -183,7 +183,7 @@ func makeTestGraph(t *testing.T, useCache bool) (*channeldb.ChannelGraph, func parseTestGraph(t *testing.T, useCache bool, path string) ( *testGraphInstance, error) { - graphJSON, err := ioutil.ReadFile(path) + graphJSON, err := os.ReadFile(path) if err != nil { return nil, err } diff --git a/tls_manager_test.go b/tls_manager_test.go index 935834971..348f095bc 100644 --- a/tls_manager_test.go +++ b/tls_manager_test.go @@ -12,6 +12,7 @@ import ( "io/ioutil" "math/big" "net" + "os" "testing" "time" @@ -199,7 +200,7 @@ func TestGenerateEphemeralCert(t *testing.T) { keyBytes, err := tlsManager.loadEphemeralCertificate() require.NoError(t, err, "failed to generate new certificate") - certBytes, err := ioutil.ReadFile(tmpCertPath) + certBytes, err := os.ReadFile(tmpCertPath) require.NoError(t, err) tlsr, err := cert.NewTLSReloader(certBytes, keyBytes) @@ -207,15 +208,15 @@ func TestGenerateEphemeralCert(t *testing.T) { tlsManager.tlsReloader = tlsr // Make sure .tmp file is created at the tmp cert path. - _, err = ioutil.ReadFile(tmpCertPath) + _, err = os.ReadFile(tmpCertPath) require.NoError(t, err, "couldn't find temp cert file") // But no key should be stored. - _, err = ioutil.ReadFile(cfg.TLSKeyPath) + _, err = os.ReadFile(cfg.TLSKeyPath) require.Error(t, err, "shouldn't have found file") // And no permanent cert file should be stored. - _, err = ioutil.ReadFile(cfg.TLSCertPath) + _, err = os.ReadFile(cfg.TLSCertPath) require.Error(t, err, "shouldn't have found a permanent cert file") // Now test that when we reload the certificate it generates the new diff --git a/tor/cmd_onion.go b/tor/cmd_onion.go index 72f508fc0..3ac928b40 100644 --- a/tor/cmd_onion.go +++ b/tor/cmd_onion.go @@ -124,7 +124,7 @@ func (f *OnionFile) PrivateKey() ([]byte, error) { } // Try to read the Tor private key to pass into the AddOnion call. - privateKeyContent, err := ioutil.ReadFile(f.privateKeyPath) + privateKeyContent, err := os.ReadFile(f.privateKeyPath) if err != nil { return nil, err } diff --git a/tor/controller.go b/tor/controller.go index 241b3ddbe..47ea6e129 100644 --- a/tor/controller.go +++ b/tor/controller.go @@ -8,8 +8,8 @@ import ( "encoding/hex" "errors" "fmt" - "io/ioutil" "net/textproto" + "os" "regexp" "strconv" "strings" @@ -597,7 +597,7 @@ func (c *Controller) getAuthCookie(info protocolInfo) ([]byte, error) { cookieFilePath = strings.Trim(cookieFilePath, "\"") // Read the cookie from the file and ensure it has the correct length. - cookie, err := ioutil.ReadFile(cookieFilePath) + cookie, err := os.ReadFile(cookieFilePath) if err != nil { return nil, err } From 789c6bac8ca4b75d15e9e40f8ded8e394df518bb Mon Sep 17 00:00:00 2001 From: erik Date: Wed, 14 Jun 2023 11:33:44 +0200 Subject: [PATCH 022/109] multi: replace ioutil.WriteFile --- cert/selfsigned.go | 5 ++--- cmd/lncli/cmd_macaroon.go | 5 ++--- cmd/lncli/profile.go | 4 ++-- internal/musig2v040/musig2_test.go | 8 ++++---- kvdb/backend.go | 3 +-- lnrpc/chainrpc/chain_server.go | 3 +-- lnrpc/invoicesrpc/invoices_server.go | 3 +-- lnrpc/routerrpc/router_server.go | 3 +-- lnrpc/signrpc/signer_server.go | 3 +-- lnrpc/walletrpc/walletkit_server.go | 3 +-- tls_manager.go | 3 +-- tls_manager_test.go | 5 ++--- tor/cmd_onion.go | 3 +-- 13 files changed, 20 insertions(+), 31 deletions(-) diff --git a/cert/selfsigned.go b/cert/selfsigned.go index c956afb00..80fe42106 100644 --- a/cert/selfsigned.go +++ b/cert/selfsigned.go @@ -9,7 +9,6 @@ import ( "crypto/x509/pkix" "encoding/pem" "fmt" - "io/ioutil" "math/big" "net" "os" @@ -295,14 +294,14 @@ func GenCertPair(org string, tlsExtraIPs, tlsExtraDomains []string, func WriteCertPair(certFile, keyFile string, certBytes, keyBytes []byte) error { // Write cert and key files. if certFile != "" { - err := ioutil.WriteFile(certFile, certBytes, 0644) + err := os.WriteFile(certFile, certBytes, 0644) if err != nil { return err } } if keyFile != "" { - err := ioutil.WriteFile(keyFile, keyBytes, 0600) + err := os.WriteFile(keyFile, keyBytes, 0600) if err != nil { os.Remove(certFile) return err diff --git a/cmd/lncli/cmd_macaroon.go b/cmd/lncli/cmd_macaroon.go index 894e8da6b..deea4e7ad 100644 --- a/cmd/lncli/cmd_macaroon.go +++ b/cmd/lncli/cmd_macaroon.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/hex" "fmt" - "io/ioutil" "net" "os" "strconv" @@ -193,7 +192,7 @@ func bakeMacaroon(ctx *cli.Context) error { // a file or write to the standard output using hex encoding. switch { case savePath != "": - err = ioutil.WriteFile(savePath, macBytes, 0644) + err = os.WriteFile(savePath, macBytes, 0644) if err != nil { return err } @@ -472,7 +471,7 @@ func constrainMacaroon(ctx *cli.Context) error { } // Now we can output the result. - err = ioutil.WriteFile(destMacFile, destMacBytes, 0644) + err = os.WriteFile(destMacFile, destMacBytes, 0644) if err != nil { return fmt.Errorf("error writing destination macaroon file "+ "%s: %v", destMacFile, err) diff --git a/cmd/lncli/profile.go b/cmd/lncli/profile.go index 75dc9ab72..efbdfc147 100644 --- a/cmd/lncli/profile.go +++ b/cmd/lncli/profile.go @@ -6,7 +6,6 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" "os" "path" "strings" @@ -244,7 +243,8 @@ func saveProfileFile(file string, f *profileFile) error { if err != nil { return fmt.Errorf("could not marshal profile: %w", err) } - return ioutil.WriteFile(file, content, 0644) + + return os.WriteFile(file, content, 0644) } // profileFile is a struct that represents the whole content of a profile file. diff --git a/internal/musig2v040/musig2_test.go b/internal/musig2v040/musig2_test.go index 9ba74f417..47fd71c76 100644 --- a/internal/musig2v040/musig2_test.go +++ b/internal/musig2v040/musig2_test.go @@ -10,7 +10,7 @@ import ( "errors" "flag" "fmt" - "io/ioutil" + "os" "sync" "testing" @@ -256,7 +256,7 @@ func TestMuSig2KeyAggTestVectors(t *testing.T) { var formattedJson bytes.Buffer json.Indent(&formattedJson, jsonBytes, "", "\t") - err = ioutil.WriteFile( + err = os.WriteFile( keyAggTestVectorName, formattedJson.Bytes(), 0644, ) if err != nil { @@ -656,7 +656,7 @@ func TestMuSig2SigningTestVectors(t *testing.T) { var formattedJson bytes.Buffer json.Indent(&formattedJson, jsonBytes, "", "\t") - err = ioutil.WriteFile( + err = os.WriteFile( signTestVectorName, formattedJson.Bytes(), 0644, ) if err != nil { @@ -1540,7 +1540,7 @@ func TestMusig2AggregateNoncesTestVectors(t *testing.T) { var formattedJson bytes.Buffer json.Indent(&formattedJson, jsonBytes, "", "\t") - err = ioutil.WriteFile( + err = os.WriteFile( nonceAggTestVectorName, formattedJson.Bytes(), 0644, ) if err != nil { diff --git a/kvdb/backend.go b/kvdb/backend.go index c115c4f7d..e42c02233 100644 --- a/kvdb/backend.go +++ b/kvdb/backend.go @@ -9,7 +9,6 @@ import ( "encoding/binary" "encoding/hex" "fmt" - "io/ioutil" "os" "path/filepath" "time" @@ -235,7 +234,7 @@ func updateLastCompactionDate(dbFile string) error { byteOrder.PutUint64(tsBytes[:], uint64(time.Now().UnixNano())) tsFile := fmt.Sprintf("%s%s", dbFile, LastCompactionFileNameSuffix) - return ioutil.WriteFile(tsFile, tsBytes[:], 0600) + return os.WriteFile(tsFile, tsBytes[:], 0600) } // GetTestBackend opens (or creates if doesn't exist) a bbolt or etcd diff --git a/lnrpc/chainrpc/chain_server.go b/lnrpc/chainrpc/chain_server.go index 00a30c07c..1defadafc 100644 --- a/lnrpc/chainrpc/chain_server.go +++ b/lnrpc/chainrpc/chain_server.go @@ -7,7 +7,6 @@ import ( "bytes" "context" "errors" - "io/ioutil" "os" "path/filepath" "sync" @@ -153,7 +152,7 @@ func New(cfg *Config) (*Server, lnrpc.MacaroonPerms, error) { if err != nil { return nil, nil, err } - err = ioutil.WriteFile(macFilePath, chainNotifierMacBytes, 0644) + err = os.WriteFile(macFilePath, chainNotifierMacBytes, 0644) if err != nil { _ = os.Remove(macFilePath) return nil, nil, err diff --git a/lnrpc/invoicesrpc/invoices_server.go b/lnrpc/invoicesrpc/invoices_server.go index b62538543..23b8722ca 100644 --- a/lnrpc/invoicesrpc/invoices_server.go +++ b/lnrpc/invoicesrpc/invoices_server.go @@ -7,7 +7,6 @@ import ( "context" "errors" "fmt" - "io/ioutil" "os" "path/filepath" @@ -132,7 +131,7 @@ func New(cfg *Config) (*Server, lnrpc.MacaroonPerms, error) { if err != nil { return nil, nil, err } - err = ioutil.WriteFile(macFilePath, invoicesMacBytes, 0644) + err = os.WriteFile(macFilePath, invoicesMacBytes, 0644) if err != nil { _ = os.Remove(macFilePath) return nil, nil, err diff --git a/lnrpc/routerrpc/router_server.go b/lnrpc/routerrpc/router_server.go index 194bdc996..090fef0ed 100644 --- a/lnrpc/routerrpc/router_server.go +++ b/lnrpc/routerrpc/router_server.go @@ -6,7 +6,6 @@ import ( crand "crypto/rand" "errors" "fmt" - "io/ioutil" "os" "path/filepath" "sync/atomic" @@ -216,7 +215,7 @@ func New(cfg *Config) (*Server, lnrpc.MacaroonPerms, error) { if err != nil { return nil, nil, err } - err = ioutil.WriteFile(macFilePath, routerMacBytes, 0644) + err = os.WriteFile(macFilePath, routerMacBytes, 0644) if err != nil { _ = os.Remove(macFilePath) return nil, nil, err diff --git a/lnrpc/signrpc/signer_server.go b/lnrpc/signrpc/signer_server.go index c29d495eb..4b2ac2c6a 100644 --- a/lnrpc/signrpc/signer_server.go +++ b/lnrpc/signrpc/signer_server.go @@ -8,7 +8,6 @@ import ( "context" "crypto/sha256" "fmt" - "io/ioutil" "os" "path/filepath" @@ -167,7 +166,7 @@ func New(cfg *Config) (*Server, lnrpc.MacaroonPerms, error) { if err != nil { return nil, nil, err } - err = ioutil.WriteFile(macFilePath, signerMacBytes, 0644) + err = os.WriteFile(macFilePath, signerMacBytes, 0644) if err != nil { _ = os.Remove(macFilePath) return nil, nil, err diff --git a/lnrpc/walletrpc/walletkit_server.go b/lnrpc/walletrpc/walletkit_server.go index d3f5131b0..a00c38207 100644 --- a/lnrpc/walletrpc/walletkit_server.go +++ b/lnrpc/walletrpc/walletkit_server.go @@ -10,7 +10,6 @@ import ( "encoding/binary" "errors" "fmt" - "io/ioutil" "math" "os" "path/filepath" @@ -289,7 +288,7 @@ func New(cfg *Config) (*WalletKit, lnrpc.MacaroonPerms, error) { if err != nil { return nil, nil, err } - err = ioutil.WriteFile(macFilePath, walletKitMacBytes, 0644) + err = os.WriteFile(macFilePath, walletKitMacBytes, 0644) if err != nil { _ = os.Remove(macFilePath) return nil, nil, err diff --git a/tls_manager.go b/tls_manager.go index 7801279fa..076cf44bc 100644 --- a/tls_manager.go +++ b/tls_manager.go @@ -7,7 +7,6 @@ import ( "crypto/x509" "errors" "fmt" - "io/ioutil" "net" "net/http" "os" @@ -279,7 +278,7 @@ func (t *TLSManager) ensureEncryption(keyRing keychain.SecretKeyRing) error { if err != nil { return err } - err = ioutil.WriteFile( + err = os.WriteFile( t.cfg.TLSKeyPath, b.Bytes(), modifyFilePermissions, ) if err != nil { diff --git a/tls_manager_test.go b/tls_manager_test.go index 348f095bc..42f010411 100644 --- a/tls_manager_test.go +++ b/tls_manager_test.go @@ -9,7 +9,6 @@ import ( "crypto/x509" "crypto/x509/pkix" "encoding/pem" - "io/ioutil" "math/big" "net" "os" @@ -351,9 +350,9 @@ func writeTestCertFiles(t *testing.T, expiredCert, encryptTLSKey bool, require.NoError(t, err, "failed to encrypt private key") } - err = ioutil.WriteFile(tempDir+"/tls.cert", certBuf.Bytes(), 0644) + err = os.WriteFile(tempDir+"/tls.cert", certBuf.Bytes(), 0644) require.NoError(t, err, "failed to write cert file") - err = ioutil.WriteFile(tempDir+"/tls.key", keyBuf.Bytes(), 0600) + err = os.WriteFile(tempDir+"/tls.key", keyBuf.Bytes(), 0600) require.NoError(t, err, "failed to write key file") return certPath, keyPath, parsedCert diff --git a/tor/cmd_onion.go b/tor/cmd_onion.go index 3ac928b40..6e60504a9 100644 --- a/tor/cmd_onion.go +++ b/tor/cmd_onion.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "os" ) @@ -105,7 +104,7 @@ func (f *OnionFile) StorePrivateKey(privateKey []byte) error { privateKeyContent = b.Bytes() } - err := ioutil.WriteFile( + err := os.WriteFile( f.privateKeyPath, privateKeyContent, f.privateKeyPerm, ) if err != nil { From c7f81d314230c11ab3d5333340b652336bb03302 Mon Sep 17 00:00:00 2001 From: erik Date: Wed, 14 Jun 2023 11:40:27 +0200 Subject: [PATCH 023/109] multi: replace ioutil.Discard --- lnwire/onion_error.go | 3 +-- tlv/stream.go | 3 +-- watchtower/tlv_bench_test.go | 5 ++--- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/lnwire/onion_error.go b/lnwire/onion_error.go index 8b7fc733b..66db6a9f5 100644 --- a/lnwire/onion_error.go +++ b/lnwire/onion_error.go @@ -7,7 +7,6 @@ import ( "encoding/binary" "fmt" "io" - "io/ioutil" "github.com/davecgh/go-spew/spew" "github.com/go-errors/errors" @@ -1304,7 +1303,7 @@ func DecodeFailure(r io.Reader, pver uint32) (FailureMessage, error) { return nil, fmt.Errorf("unable to read pad len: %w", err) } - if _, err := io.CopyN(ioutil.Discard, r, int64(padLength)); err != nil { + if _, err := io.CopyN(io.Discard, r, int64(padLength)); err != nil { return nil, fmt.Errorf("unable to read padding %w", err) } diff --git a/tlv/stream.go b/tlv/stream.go index 3d353ad22..70fade22d 100644 --- a/tlv/stream.go +++ b/tlv/stream.go @@ -4,7 +4,6 @@ import ( "bytes" "errors" "io" - "io/ioutil" "math" ) @@ -262,7 +261,7 @@ func (s *Stream) decode(r io.Reader, parsedTypes TypeMap, p2p bool) (TypeMap, // If the caller provided an initialized TypeMap, record // the encoded bytes. var b *bytes.Buffer - writer := ioutil.Discard + writer := io.Discard if parsedTypes != nil { b = bytes.NewBuffer(make([]byte, 0, length)) writer = b diff --git a/watchtower/tlv_bench_test.go b/watchtower/tlv_bench_test.go index 5ffabde08..e6d8decd7 100644 --- a/watchtower/tlv_bench_test.go +++ b/watchtower/tlv_bench_test.go @@ -3,7 +3,6 @@ package watchtower_test import ( "bytes" "io" - "io/ioutil" "testing" "github.com/lightningnetwork/lnd/lnwallet/chainfee" @@ -104,7 +103,7 @@ func BenchmarkEncodeCreateSession(t *testing.B) { var err error for i := 0; i < t.N; i++ { - err = m.Encode(ioutil.Discard, 0) + err = m.Encode(io.Discard, 0) } require.NoError(t, err) } @@ -118,7 +117,7 @@ func BenchmarkEncodeCreateSessionTLV(t *testing.B) { var err error for i := 0; i < t.N; i++ { - err = m.Encode(ioutil.Discard) + err = m.Encode(io.Discard) } require.NoError(t, err) } From caf2419ff603c90527d1e5a96d653596c116acaa Mon Sep 17 00:00:00 2001 From: erik Date: Wed, 14 Jun 2023 11:43:51 +0200 Subject: [PATCH 024/109] multi: replace ioutil.ReadDir --- lntest/btcd.go | 3 +-- lntest/harness_miner.go | 3 +-- lntest/node/harness_node.go | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/lntest/btcd.go b/lntest/btcd.go index 09f33472b..2d735fa2b 100644 --- a/lntest/btcd.go +++ b/lntest/btcd.go @@ -7,7 +7,6 @@ import ( "encoding/hex" "errors" "fmt" - "io/ioutil" "os" "strings" @@ -135,7 +134,7 @@ func NewBackend(miner string, netParams *chaincfg.Params) ( // the log files, including any compressed log files from // logrorate, before deleting the temporary log dir. logDir := fmt.Sprintf("%s/%s", baseLogDir, netParams.Name) - files, err := ioutil.ReadDir(logDir) + files, err := os.ReadDir(logDir) if err != nil { errStr += fmt.Sprintf( "unable to read log directory: %v\n", err, diff --git a/lntest/harness_miner.go b/lntest/harness_miner.go index a28715321..f6348c078 100644 --- a/lntest/harness_miner.go +++ b/lntest/harness_miner.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "fmt" - "io/ioutil" "os" "path/filepath" "strings" @@ -121,7 +120,7 @@ func (h *HarnessMiner) saveLogs() { // After shutting down the miner, we'll make a copy of the log files // before deleting the temporary log dir. path := fmt.Sprintf("%s/%s", h.logPath, harnessNetParams.Name) - files, err := ioutil.ReadDir(path) + files, err := os.ReadDir(path) require.NoError(h, err, "unable to read log directory") for _, file := range files { diff --git a/lntest/node/harness_node.go b/lntest/node/harness_node.go index 1afb095d8..629497367 100644 --- a/lntest/node/harness_node.go +++ b/lntest/node/harness_node.go @@ -1032,7 +1032,7 @@ func addLogFile(hn *HarnessNode) error { // copyAll copies all files and directories from srcDir to dstDir recursively. // Note that this function does not support links. func copyAll(dstDir, srcDir string) error { - entries, err := ioutil.ReadDir(srcDir) + entries, err := os.ReadDir(srcDir) if err != nil { return err } From df4ddcc57377fa1a0ccafe37e7ecb42f34147211 Mon Sep 17 00:00:00 2001 From: erik Date: Wed, 14 Jun 2023 11:45:56 +0200 Subject: [PATCH 025/109] multi: replace ioutil.TempDir --- htlcswitch/mock.go | 3 +-- lntest/bitcoind_common.go | 3 +-- lntest/node/harness_node.go | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/htlcswitch/mock.go b/htlcswitch/mock.go index a0f38c74f..dfa834c58 100644 --- a/htlcswitch/mock.go +++ b/htlcswitch/mock.go @@ -7,7 +7,6 @@ import ( "encoding/binary" "fmt" "io" - "io/ioutil" "net" "os" "path/filepath" @@ -947,7 +946,7 @@ var _ ChannelLink = (*mockChannelLink)(nil) func newDB() (*channeldb.DB, func(), error) { // First, create a temporary directory to be used for the duration of // this test. - tempDirName, err := ioutil.TempDir("", "channeldb") + tempDirName, err := os.MkdirTemp("", "channeldb") if err != nil { return nil, nil, err } diff --git a/lntest/bitcoind_common.go b/lntest/bitcoind_common.go index 657da7cd3..9cbcd23fd 100644 --- a/lntest/bitcoind_common.go +++ b/lntest/bitcoind_common.go @@ -6,7 +6,6 @@ package lntest import ( "errors" "fmt" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -105,7 +104,7 @@ func newBackend(miner string, netParams *chaincfg.Params, extraArgs []string, return nil, nil, err } - tempBitcoindDir, err := ioutil.TempDir("", "bitcoind") + tempBitcoindDir, err := os.MkdirTemp("", "bitcoind") if err != nil { return nil, nil, fmt.Errorf("unable to create temp directory: %w", err) diff --git a/lntest/node/harness_node.go b/lntest/node/harness_node.go index 629497367..3df5a8e64 100644 --- a/lntest/node/harness_node.go +++ b/lntest/node/harness_node.go @@ -9,7 +9,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -824,7 +823,7 @@ func (hn *HarnessNode) BackupDB() error { } } else { // Backup files. - tempDir, err := ioutil.TempDir("", "past-state") + tempDir, err := os.MkdirTemp("", "past-state") if err != nil { return fmt.Errorf("unable to create temp db folder: %w", err) From 0d94131fca691596e4c46c3c07eb34879baf7dc7 Mon Sep 17 00:00:00 2001 From: erik Date: Wed, 14 Jun 2023 11:48:44 +0200 Subject: [PATCH 026/109] doc: release note --- docs/release-notes/release-notes-0.18.0.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/release-notes-0.18.0.md b/docs/release-notes/release-notes-0.18.0.md index f59ae179b..b70cbfac2 100644 --- a/docs/release-notes/release-notes-0.18.0.md +++ b/docs/release-notes/release-notes-0.18.0.md @@ -389,7 +389,10 @@ bitcoin peers' feefilter values into account](https://github.com/lightningnetwor In particular, the complexity involved in the lifecycle loop has been decoupled into logical steps, with each step having its own responsibility, making it easier to reason about the payment flow. - + +* [Remove io/ioutil package + dependence](https://github.com/lightningnetwork/lnd/pull/7765). + * [Add a watchtower tower client multiplexer](https://github.com/lightningnetwork/lnd/pull/7702) to manage tower clients of different types. From fe829c2508d152c29e4abf9003f9af442eb2ae36 Mon Sep 17 00:00:00 2001 From: ziggie Date: Thu, 4 Apr 2024 01:09:04 +0100 Subject: [PATCH 027/109] mod: bump neutrino version. --- go.mod | 16 ++++++++-------- go.sum | 29 ++++++++++++++++------------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index 54827142b..5dd778818 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ require ( github.com/Yawning/aez v0.0.0-20211027044916-e49e68abd344 github.com/andybalholm/brotli v1.0.4 github.com/btcsuite/btcd v0.24.2-beta.rc1.0.20240403021926-ae5533602c46 - github.com/btcsuite/btcd/btcec/v2 v2.3.2 + github.com/btcsuite/btcd/btcec/v2 v2.3.3 github.com/btcsuite/btcd/btcutil v1.1.5 github.com/btcsuite/btcd/btcutil/psbt v1.1.8 github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 @@ -17,7 +17,7 @@ require ( github.com/btcsuite/btcwallet/wtxmgr v1.5.3 github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f github.com/davecgh/go-spew v1.1.1 - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 github.com/go-errors/errors v1.0.1 github.com/gorilla/websocket v1.5.0 github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 @@ -30,7 +30,7 @@ require ( github.com/jessevdk/go-flags v1.4.0 github.com/jrick/logrotate v1.0.0 github.com/kkdai/bstream v1.0.0 - github.com/lightninglabs/neutrino v0.16.0 + github.com/lightninglabs/neutrino v0.16.1-0.20240425105051-602843d34ffd github.com/lightninglabs/neutrino/cache v1.1.2 github.com/lightningnetwork/lightning-onion v1.2.1-0.20230823005744-06182b1d7d2f github.com/lightningnetwork/lnd/cert v1.2.2 @@ -51,12 +51,12 @@ require ( github.com/urfave/cli v1.22.9 go.etcd.io/etcd/client/pkg/v3 v3.5.7 go.etcd.io/etcd/client/v3 v3.5.7 - golang.org/x/crypto v0.21.0 + golang.org/x/crypto v0.22.0 golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 golang.org/x/net v0.22.0 golang.org/x/sync v0.6.0 - golang.org/x/term v0.18.0 + golang.org/x/term v0.19.0 golang.org/x/time v0.3.0 google.golang.org/grpc v1.59.0 google.golang.org/protobuf v1.33.0 @@ -82,8 +82,8 @@ require ( github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect - github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect - github.com/decred/dcrd/lru v1.0.0 // indirect + github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect + github.com/decred/dcrd/lru v1.1.2 // indirect github.com/docker/cli v20.10.17+incompatible // indirect github.com/docker/docker v24.0.7+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect @@ -172,7 +172,7 @@ require ( go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.17.0 // indirect golang.org/x/mod v0.16.0 // indirect - golang.org/x/sys v0.18.0 // indirect + golang.org/x/sys v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.19.0 // indirect google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect diff --git a/go.sum b/go.sum index e5e56d2c1..e6f6245ff 100644 --- a/go.sum +++ b/go.sum @@ -77,8 +77,8 @@ github.com/btcsuite/btcd v0.24.2-beta.rc1.0.20240403021926-ae5533602c46 h1:tjpNT github.com/btcsuite/btcd v0.24.2-beta.rc1.0.20240403021926-ae5533602c46/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= -github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= -github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/btcec/v2 v2.3.3 h1:6+iXlDKE8RMtKsvK0gshlXIuPbyWM/h84Ensb7o3sC0= +github.com/btcsuite/btcd/btcec/v2 v2.3.3/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= @@ -162,12 +162,15 @@ github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/decred/dcrd/lru v1.1.2 h1:KdCzlkxppuoIDGEvCGah1fZRicrDH36IipvlB1ROkFY= +github.com/decred/dcrd/lru v1.1.2/go.mod h1:gEdCVgXs1/YoBvFWt7Scgknbhwik3FgVSzlnCcXL2N8= github.com/dhui/dktest v0.4.0 h1:z05UmuXZHO/bgj/ds2bGMBu8FI4WA+Ag/m3ghL+om7M= github.com/dhui/dktest v0.4.0/go.mod h1:v/Dbz1LgCBOi2Uki2nUqLBGa83hWBGFMu5MrgMDCc78= github.com/docker/cli v20.10.17+incompatible h1:eO2KS7ZFeov5UJeaDmIs1NFEDRf32PaqRpvoEkKBy5M= @@ -433,8 +436,8 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf h1:HZKvJUHlcXI/f/O0Avg7t8sqkPo78HFzjmeYFl6DPnc= github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf/go.mod h1:vxmQPeIQxPf6Jf9rM8R+B4rKBqLA2AjttNxkFBL2Plk= -github.com/lightninglabs/neutrino v0.16.0 h1:YNTQG32fPR/Zg0vvJVI65OBH8l3U18LSXXtX91hx0q0= -github.com/lightninglabs/neutrino v0.16.0/go.mod h1:x3OmY2wsA18+Kc3TSV2QpSUewOCiscw2mKpXgZv2kZk= +github.com/lightninglabs/neutrino v0.16.1-0.20240425105051-602843d34ffd h1:D8aRocHpoCv43hL8egXEMYyPmyOiefFHZ66338KQB2s= +github.com/lightninglabs/neutrino v0.16.1-0.20240425105051-602843d34ffd/go.mod h1:x3OmY2wsA18+Kc3TSV2QpSUewOCiscw2mKpXgZv2kZk= github.com/lightninglabs/neutrino/cache v1.1.2 h1:C9DY/DAPaPxbFC+xNNEI/z1SJY9GS3shmlu5hIQ798g= github.com/lightninglabs/neutrino/cache v1.1.2/go.mod h1:XJNcgdOw1LQnanGjw8Vj44CvguYA25IMKjWFZczwZuo= github.com/lightninglabs/protobuf-go-hex-display v1.30.0-hex-display h1:pRdza2wleRN1L2fJXd6ZoQ9ZegVFTAb2bOQfruJPKcY= @@ -684,8 +687,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= 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= @@ -840,12 +843,12 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/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-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 9f9d1c9e0b03fdaef9daec634a72f773e69be1ec Mon Sep 17 00:00:00 2001 From: ziggie Date: Wed, 24 Apr 2024 11:02:27 +0100 Subject: [PATCH 028/109] itest: fix typo. --- itest/lnd_psbt_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/itest/lnd_psbt_test.go b/itest/lnd_psbt_test.go index a6f15fd35..cd93fa0c0 100644 --- a/itest/lnd_psbt_test.go +++ b/itest/lnd_psbt_test.go @@ -1010,7 +1010,7 @@ func runFundAndSignPsbt(ht *lntest.HarnessTest, alice *node.HarnessNode) { for _, addrType := range spendAddrTypes { for _, changeType := range changeAddrTypes { - ht.Logf("testing with address type %s and"+ + ht.Logf("testing with address type %s and "+ "change address type %s", addrType, changeType) // First, spend all the coins in the wallet to an From f4b92eb3d40cbacb306c4d4781cbc49128d30fae Mon Sep 17 00:00:00 2001 From: ziggie Date: Thu, 4 Apr 2024 01:13:53 +0100 Subject: [PATCH 029/109] docs: add release-notes. --- docs/release-notes/release-notes-0.18.0.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/release-notes/release-notes-0.18.0.md b/docs/release-notes/release-notes-0.18.0.md index 179f52d75..ee0dd710e 100644 --- a/docs/release-notes/release-notes-0.18.0.md +++ b/docs/release-notes/release-notes-0.18.0.md @@ -129,6 +129,10 @@ * [Fixed](https://github.com/lightningnetwork/lnd/pull/8685) lncli "bumpfee" parsing of the immediate/force flag. + +* [Fixed](https://github.com/lightningnetwork/lnd/pull/8621) the behaviour of + neutrino LND nodes which would loose sync in case they had very unstable + peer connection. # New Features ## Functional Enhancements From c2c0158c84936d2e96669b1dee476b7e5b9aa3b4 Mon Sep 17 00:00:00 2001 From: Carla Kirk-Cohen Date: Fri, 8 Mar 2024 13:33:10 -0500 Subject: [PATCH 030/109] htlcswitch: handle malformed HTLC with invalid onion blinding code This commit adds handling for malformed HTLC errors related to blinded paths. We expect to receive these errors _within_ a blinded path, because all non-introduction nodes are instructed to return malformed errors for failures. Note that we may actually switch back to a malformed error later on if we too are a relaying node in the route, but we handle that case the incoming link. --- htlcswitch/link.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 778e78d70..fd87c2f29 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -2030,6 +2030,19 @@ func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) { failure = &lnwire.FailInvalidOnionKey{ OnionSHA256: msg.ShaOnionBlob, } + + // Handle malformed errors that are part of a blinded route. + // This case is slightly different, because we expect every + // relaying node in the blinded portion of the route to send + // malformed errors. If we're also a relaying node, we're + // likely going to switch this error out anyway for our own + // malformed error, but we handle the case here for + // completeness. + case lnwire.CodeInvalidBlinding: + failure = &lnwire.FailInvalidBlinding{ + OnionSHA256: msg.ShaOnionBlob, + } + default: l.log.Warnf("unexpected failure code received in "+ "UpdateFailMailformedHTLC: %v", msg.FailureCode) From 4d051b4170da75e64747a06a5aab0dacb0b14b4e Mon Sep 17 00:00:00 2001 From: Carla Kirk-Cohen Date: Mon, 22 Apr 2024 14:06:17 -0400 Subject: [PATCH 031/109] multi: handle all blinding point validation in ValidateParsedPayloadTypes This commit moves all our validation related to the presence of fields into ValidateParsedPayloadTypes so that we can handle them in a single place. We draw the distinction between: - Validation of the payload (and the context within it's being parsed, final hop / blinded hop etc) - Processing and validation of encrypted data, where we perform additional cryptographic operations and validate that the fields contained in the blob are valid. This helps draw the line more clearly between the two validation types, rather than splitting some payload-releated blinded hop processing into the encrypted data processing part. The downside of this approach (vs doing the blinded path payload check _after_ payload validation) is that we have to pass additional context into payload validation (ie, whether we got a blinding point in our UpdateAddHtlc - as we already do for isFinalHop). --- htlcswitch/hop/fuzz_test.go | 40 ++++++++++---- htlcswitch/hop/iterator.go | 48 ++++++----------- htlcswitch/hop/iterator_test.go | 31 +++++------ htlcswitch/hop/payload.go | 37 +++++++++++-- htlcswitch/hop/payload_test.go | 93 ++++++++++++++++++++++++++++----- 5 files changed, 174 insertions(+), 75 deletions(-) diff --git a/htlcswitch/hop/fuzz_test.go b/htlcswitch/hop/fuzz_test.go index cbbe88260..f5fe648f5 100644 --- a/htlcswitch/hop/fuzz_test.go +++ b/htlcswitch/hop/fuzz_test.go @@ -97,19 +97,37 @@ func hopFromPayload(p *Payload) (*route.Hop, uint64) { // FuzzPayloadFinal fuzzes final hop payloads, providing the additional context // that the hop should be final (which is usually obtained by the structure -// of the sphinx packet). -func FuzzPayloadFinal(f *testing.F) { - fuzzPayload(f, true) +// of the sphinx packet) for the case where a blinding point was provided in +// UpdateAddHtlc. +func FuzzPayloadFinalBlinding(f *testing.F) { + fuzzPayload(f, true, true) +} + +// FuzzPayloadFinal fuzzes final hop payloads, providing the additional context +// that the hop should be final (which is usually obtained by the structure +// of the sphinx packet) for the case where no blinding point was provided in +// UpdateAddHtlc. +func FuzzPayloadFinalNoBlinding(f *testing.F) { + fuzzPayload(f, true, false) } // FuzzPayloadIntermediate fuzzes intermediate hop payloads, providing the // additional context that a hop should be intermediate (which is usually -// obtained by the structure of the sphinx packet). -func FuzzPayloadIntermediate(f *testing.F) { - fuzzPayload(f, false) +// obtained by the structure of the sphinx packet) for the case where a +// blinding point was provided in UpdateAddHtlc. +func FuzzPayloadIntermediateBlinding(f *testing.F) { + fuzzPayload(f, false, true) } -func fuzzPayload(f *testing.F, finalPayload bool) { +// FuzzPayloadIntermediate fuzzes intermediate hop payloads, providing the +// additional context that a hop should be intermediate (which is usually +// obtained by the structure of the sphinx packet) for the case where no +// blinding point was provided in UpdateAddHtlc. +func FuzzPayloadIntermediateNoBlinding(f *testing.F) { + fuzzPayload(f, false, false) +} + +func fuzzPayload(f *testing.F, finalPayload, updateAddBlinded bool) { f.Fuzz(func(t *testing.T, data []byte) { if len(data) > sphinx.MaxPayloadSize { return @@ -117,7 +135,9 @@ func fuzzPayload(f *testing.F, finalPayload bool) { r := bytes.NewReader(data) - payload1, _, err := NewPayloadFromReader(r, finalPayload) + payload1, _, err := NewPayloadFromReader( + r, finalPayload, updateAddBlinded, + ) if err != nil { return } @@ -146,7 +166,9 @@ func fuzzPayload(f *testing.F, finalPayload bool) { require.NoError(t, err) } - payload2, _, err := NewPayloadFromReader(&b, finalPayload) + payload2, _, err := NewPayloadFromReader( + &b, finalPayload, updateAddBlinded, + ) require.NoError(t, err) require.Equal(t, payload1, payload2) diff --git a/htlcswitch/hop/iterator.go b/htlcswitch/hop/iterator.go index df6f5aac7..7088127c3 100644 --- a/htlcswitch/hop/iterator.go +++ b/htlcswitch/hop/iterator.go @@ -17,6 +17,11 @@ import ( var ( // ErrDecodeFailed is returned when we can't decode blinded data. ErrDecodeFailed = errors.New("could not decode blinded data") + + // ErrNoBlindingPoint is returned when we have not provided a blinding + // point for a validated payload with encrypted data set. + ErrNoBlindingPoint = errors.New("no blinding point set for validated " + + "blinded hop") ) // Iterator is an interface that abstracts away the routing information @@ -109,7 +114,7 @@ func (r *sphinxHopIterator) HopPayload() (*Payload, error) { isFinal := r.processedPacket.Action == sphinx.ExitNode payload, parsed, err := NewPayloadFromReader( bytes.NewReader(r.processedPacket.Payload.Payload), - isFinal, + isFinal, r.blindingKit.UpdateAddBlinding.IsSome(), ) if err != nil { return nil, err @@ -182,35 +187,16 @@ type BlindingKit struct { IncomingAmount lnwire.MilliSatoshi } -// validateBlindingPoint validates that only one blinding point is present for -// the hop and returns the relevant one. -func (b *BlindingKit) validateBlindingPoint(payloadBlinding *btcec.PublicKey, - isFinalHop bool) (*btcec.PublicKey, error) { +// getBlindingPoint returns either the payload or updateAddHtlc blinding point, +// assuming that validation that these values are appropriately set has already +// been handled elsewhere. +func (b *BlindingKit) getBlindingPoint(payloadBlinding *btcec.PublicKey) ( + *btcec.PublicKey, error) { - // Bolt 04: if encrypted_recipient_data is present: - // - if blinding_point (in update add) is set: - // - MUST error if current_blinding_point is set (in payload) - // - otherwise: - // - MUST return an error if current_blinding_point is not present - // (in payload) payloadBlindingSet := payloadBlinding != nil updateBlindingSet := b.UpdateAddBlinding.IsSome() switch { - case !(payloadBlindingSet || updateBlindingSet): - return nil, ErrInvalidPayload{ - Type: record.BlindingPointOnionType, - Violation: OmittedViolation, - FinalHop: isFinalHop, - } - - case payloadBlindingSet && updateBlindingSet: - return nil, ErrInvalidPayload{ - Type: record.BlindingPointOnionType, - Violation: IncludedViolation, - FinalHop: isFinalHop, - } - case payloadBlindingSet: return payloadBlinding, nil @@ -223,9 +209,10 @@ func (b *BlindingKit) validateBlindingPoint(payloadBlinding *btcec.PublicKey, } return pk.Val, nil - } - return nil, fmt.Errorf("expected blinded point set") + default: + return nil, ErrNoBlindingPoint + } } // DecryptAndValidateFwdInfo performs all operations required to decrypt and @@ -235,11 +222,10 @@ func (b *BlindingKit) DecryptAndValidateFwdInfo(payload *Payload, *ForwardingInfo, error) { // We expect this function to be called when we have encrypted data - // present, and a blinding key is set either in the payload or the + // present, and expect validation to already have ensured that a + // blinding key is set either in the payload or the // update_add_htlc message. - blindingPoint, err := b.validateBlindingPoint( - payload.blindingPoint, isFinalHop, - ) + blindingPoint, err := b.getBlindingPoint(payload.blindingPoint) if err != nil { return nil, err } diff --git a/htlcswitch/hop/iterator_test.go b/htlcswitch/hop/iterator_test.go index 60919333b..a850c6dc1 100644 --- a/htlcswitch/hop/iterator_test.go +++ b/htlcswitch/hop/iterator_test.go @@ -216,24 +216,10 @@ func TestDecryptAndValidateFwdInfo(t *testing.T) { expectedErr error }{ { - name: "no blinding point", - data: validData, - processor: &mockProcessor{}, - expectedErr: ErrInvalidPayload{ - Type: record.BlindingPointOnionType, - Violation: OmittedViolation, - }, - }, - { - name: "both blinding points", - data: validData, - updateAddBlinding: &btcec.PublicKey{}, - payloadBlinding: &btcec.PublicKey{}, - processor: &mockProcessor{}, - expectedErr: ErrInvalidPayload{ - Type: record.BlindingPointOnionType, - Violation: IncludedViolation, - }, + name: "no blinding point", + data: validData, + processor: &mockProcessor{}, + expectedErr: ErrNoBlindingPoint, }, { name: "decryption failed", @@ -265,12 +251,19 @@ func TestDecryptAndValidateFwdInfo(t *testing.T) { }, }, { - name: "valid", + name: "valid using update add", updateAddBlinding: &btcec.PublicKey{}, data: validData, processor: &mockProcessor{}, expectedErr: nil, }, + { + name: "valid using payload", + payloadBlinding: &btcec.PublicKey{}, + data: validData, + processor: &mockProcessor{}, + expectedErr: nil, + }, } for _, testCase := range tests { diff --git a/htlcswitch/hop/payload.go b/htlcswitch/hop/payload.go index 70fdb1403..8454bc847 100644 --- a/htlcswitch/hop/payload.go +++ b/htlcswitch/hop/payload.go @@ -138,8 +138,8 @@ func NewLegacyPayload(f *sphinx.HopData) *Payload { // should correspond to the bytes encapsulated in a TLV onion payload. The // final hop bool signals that this payload was the final packet parsed by // sphinx. -func NewPayloadFromReader(r io.Reader, finalHop bool) (*Payload, - map[tlv.Type][]byte, error) { +func NewPayloadFromReader(r io.Reader, finalHop, + updateAddBlinding bool) (*Payload, map[tlv.Type][]byte, error) { var ( cid uint64 @@ -177,7 +177,9 @@ func NewPayloadFromReader(r io.Reader, finalHop bool) (*Payload, // Validate whether the sender properly included or omitted tlv records // in accordance with BOLT 04. - err = ValidateParsedPayloadTypes(parsedTypes, finalHop) + err = ValidateParsedPayloadTypes( + parsedTypes, finalHop, updateAddBlinding, + ) if err != nil { return nil, nil, err } @@ -259,7 +261,7 @@ func NewCustomRecords(parsedTypes tlv.TypeMap) record.CustomSet { // boolean should be true if the payload was parsed for an exit hop. The // requirements for this method are described in BOLT 04. func ValidateParsedPayloadTypes(parsedTypes tlv.TypeMap, - isFinalHop bool) error { + isFinalHop, updateAddBlinding bool) error { _, hasAmt := parsedTypes[record.AmtOnionType] _, hasLockTime := parsedTypes[record.LockTimeOnionType] @@ -267,6 +269,7 @@ func ValidateParsedPayloadTypes(parsedTypes tlv.TypeMap, _, hasMPP := parsedTypes[record.MPPOnionType] _, hasAMP := parsedTypes[record.AMPOnionType] _, hasEncryptedData := parsedTypes[record.EncryptedDataOnionType] + _, hasBlinding := parsedTypes[record.BlindingPointOnionType] // All cleartext hops (including final hop) and the final hop in a // blinded path require the forwading amount and expiry TLVs to be set. @@ -277,6 +280,32 @@ func ValidateParsedPayloadTypes(parsedTypes tlv.TypeMap, needNextHop := !(hasEncryptedData || isFinalHop) switch { + // Both blinding point being set is invalid. + case hasBlinding && updateAddBlinding: + return ErrInvalidPayload{ + Type: record.BlindingPointOnionType, + Violation: IncludedViolation, + FinalHop: isFinalHop, + } + + // If encrypted data is not provided, blinding points should not be + // set. + case !hasEncryptedData && (hasBlinding || updateAddBlinding): + return ErrInvalidPayload{ + Type: record.EncryptedDataOnionType, + Violation: OmittedViolation, + FinalHop: isFinalHop, + } + + // If encrypted data is present, we require that one blinding point + // is set. + case hasEncryptedData && !(hasBlinding || updateAddBlinding): + return ErrInvalidPayload{ + Type: record.EncryptedDataOnionType, + Violation: IncludedViolation, + FinalHop: isFinalHop, + } + // Hops that need forwarding info must include an amount to forward. case needFwdInfo && !hasAmt: return ErrInvalidPayload{ diff --git a/htlcswitch/hop/payload_test.go b/htlcswitch/hop/payload_test.go index 301e57716..666cf64bc 100644 --- a/htlcswitch/hop/payload_test.go +++ b/htlcswitch/hop/payload_test.go @@ -26,6 +26,7 @@ type decodePayloadTest struct { name string payload []byte isFinalHop bool + updateAddBlinded bool expErr error expCustomRecords map[uint64][]byte shouldHaveMPP bool @@ -271,8 +272,9 @@ var decodePayloadTests = []decodePayloadTest{ }, }, { - name: "intermediate hop with encrypted data", - isFinalHop: false, + name: "intermediate hop with encrypted data", + isFinalHop: false, + updateAddBlinded: true, payload: []byte{ // encrypted data 0x0a, 0x03, 0x03, 0x02, 0x01, @@ -365,8 +367,9 @@ var decodePayloadTests = []decodePayloadTest{ shouldHaveTotalAmt: true, }, { - name: "final blinded hop with total amount", - isFinalHop: true, + name: "final blinded hop with total amount", + isFinalHop: true, + updateAddBlinded: true, payload: []byte{ // amount 0x02, 0x00, @@ -378,8 +381,9 @@ var decodePayloadTests = []decodePayloadTest{ shouldHaveEncData: true, }, { - name: "final blinded missing amt", - isFinalHop: true, + name: "final blinded missing amt", + isFinalHop: true, + updateAddBlinded: true, payload: []byte{ // cltv 0x04, 0x00, @@ -394,8 +398,9 @@ var decodePayloadTests = []decodePayloadTest{ }, }, { - name: "final blinded missing cltv", - isFinalHop: true, + name: "final blinded missing cltv", + isFinalHop: true, + updateAddBlinded: true, payload: []byte{ // amount 0x02, 0x00, @@ -410,8 +415,9 @@ var decodePayloadTests = []decodePayloadTest{ }, }, { - name: "intermediate blinded has amount", - isFinalHop: false, + name: "intermediate blinded has amount", + isFinalHop: false, + updateAddBlinded: true, payload: []byte{ // amount 0x02, 0x00, @@ -425,8 +431,9 @@ var decodePayloadTests = []decodePayloadTest{ }, }, { - name: "intermediate blinded has expiry", - isFinalHop: false, + name: "intermediate blinded has expiry", + isFinalHop: false, + updateAddBlinded: true, payload: []byte{ // cltv 0x04, 0x00, @@ -439,6 +446,67 @@ var decodePayloadTests = []decodePayloadTest{ FinalHop: false, }, }, + { + name: "update add blinding no data", + isFinalHop: false, + payload: []byte{ + // cltv + 0x04, 0x00, + }, + updateAddBlinded: true, + expErr: hop.ErrInvalidPayload{ + Type: record.EncryptedDataOnionType, + Violation: hop.OmittedViolation, + FinalHop: false, + }, + }, + { + name: "onion blinding point no data", + isFinalHop: false, + payload: append([]byte{ + // blinding point (type / length) + 0x0c, 0x21, + }, + // blinding point (value) + testPubKey.SerializeCompressed()..., + ), + expErr: hop.ErrInvalidPayload{ + Type: record.EncryptedDataOnionType, + Violation: hop.OmittedViolation, + FinalHop: false, + }, + }, + { + name: "encrypted data no blinding", + isFinalHop: false, + payload: []byte{ + // encrypted data + 0x0a, 0x03, 0x03, 0x02, 0x01, + }, + expErr: hop.ErrInvalidPayload{ + Type: record.EncryptedDataOnionType, + Violation: hop.IncludedViolation, + }, + }, + { + name: "both blinding points", + isFinalHop: false, + updateAddBlinded: true, + payload: append([]byte{ + // encrypted data + 0x0a, 0x03, 0x03, 0x02, 0x01, + // blinding point (type / length) + 0x0c, 0x21, + }, + // blinding point (value) + testPubKey.SerializeCompressed()..., + ), + expErr: hop.ErrInvalidPayload{ + Type: record.BlindingPointOnionType, + Violation: hop.IncludedViolation, + FinalHop: false, + }, + }, } // TestDecodeHopPayloadRecordValidation asserts that parsing the payloads in the @@ -481,6 +549,7 @@ func testDecodeHopPayloadValidation(t *testing.T, test decodePayloadTest) { p, _, err := hop.NewPayloadFromReader( bytes.NewReader(test.payload), test.isFinalHop, + test.updateAddBlinded, ) if !reflect.DeepEqual(test.expErr, err) { t.Fatalf("expected error mismatch, want: %v, got: %v", From b81a6f3d2f16b2d5c3cd8dd8cc0204c21cf6a748 Mon Sep 17 00:00:00 2001 From: Carla Kirk-Cohen Date: Tue, 23 Apr 2024 11:27:14 -0400 Subject: [PATCH 032/109] htlcswitch: split parsing and validation of TLV payloads When handling blinded errors, we need to know whether there was a blinding key in our payload when we successfully parsed our payload but then found an invalid set of fields. The combination of parsing and validation in NewPayloadFromReader means that we don't know whether a blinding point was available to us by the time the error is returned. This commit splits parsing and validation into two functions so that we can take a look at what we actually pulled of the payload in between parsing and TLV validation. --- htlcswitch/hop/fuzz_test.go | 25 +++++++++----- htlcswitch/hop/iterator.go | 10 ++++-- htlcswitch/hop/payload.go | 60 ++++++++++++++++++---------------- htlcswitch/hop/payload_test.go | 10 ++++-- 4 files changed, 63 insertions(+), 42 deletions(-) diff --git a/htlcswitch/hop/fuzz_test.go b/htlcswitch/hop/fuzz_test.go index f5fe648f5..e5c00b525 100644 --- a/htlcswitch/hop/fuzz_test.go +++ b/htlcswitch/hop/fuzz_test.go @@ -135,19 +135,23 @@ func fuzzPayload(f *testing.F, finalPayload, updateAddBlinded bool) { r := bytes.NewReader(data) - payload1, _, err := NewPayloadFromReader( - r, finalPayload, updateAddBlinded, - ) + payload1, parsed, err := ParseTLVPayload(r) if err != nil { return } + if err = ValidateParsedPayloadTypes( + parsed, finalPayload, updateAddBlinded, + ); err != nil { + return + } + var b bytes.Buffer hop, nextChanID := hopFromPayload(payload1) err = hop.PackHopPayload(&b, nextChanID, finalPayload) switch { // PackHopPayload refuses to encode an AMP record - // without an MPP record. However, NewPayloadFromReader + // without an MPP record. However, ValidateParsedPayloadTypes // does allow decoding an AMP record without an MPP // record, since validation is done at a later stage. Do // not report a bug for this case. @@ -156,9 +160,9 @@ func fuzzPayload(f *testing.F, finalPayload, updateAddBlinded bool) { // PackHopPayload will not encode regular payloads or final // hops in blinded routes that do not have an amount or expiry - // TLV set. However, NewPayloadFromReader will allow creation - // of payloads where these TLVs are present, but they have - // zero values because validation is done at a later stage. + // TLV set. However, ValidateParsedPayloadTypes will allow + // creation of payloads where these TLVs are present, but they + // have zero values because validation is done at a later stage. case errors.Is(err, route.ErrMissingField): return @@ -166,8 +170,11 @@ func fuzzPayload(f *testing.F, finalPayload, updateAddBlinded bool) { require.NoError(t, err) } - payload2, _, err := NewPayloadFromReader( - &b, finalPayload, updateAddBlinded, + payload2, parsed, err := ParseTLVPayload(&b) + require.NoError(t, err) + + err = ValidateParsedPayloadTypes( + parsed, finalPayload, updateAddBlinded, ) require.NoError(t, err) diff --git a/htlcswitch/hop/iterator.go b/htlcswitch/hop/iterator.go index 7088127c3..7ba0e9dd8 100644 --- a/htlcswitch/hop/iterator.go +++ b/htlcswitch/hop/iterator.go @@ -112,14 +112,20 @@ func (r *sphinxHopIterator) HopPayload() (*Payload, error) { // to decode only what we need to make routing decisions. case sphinx.PayloadTLV: isFinal := r.processedPacket.Action == sphinx.ExitNode - payload, parsed, err := NewPayloadFromReader( + payload, parsed, err := ParseTLVPayload( bytes.NewReader(r.processedPacket.Payload.Payload), - isFinal, r.blindingKit.UpdateAddBlinding.IsSome(), ) if err != nil { return nil, err } + if err := ValidateTLVPayload( + parsed, isFinal, + r.blindingKit.UpdateAddBlinding.IsSome(), + ); err != nil { + return nil, err + } + // If we had an encrypted data payload present, pull out our // forwarding info from the blob. if payload.encryptedData != nil { diff --git a/htlcswitch/hop/payload.go b/htlcswitch/hop/payload.go index 8454bc847..9e717bbd2 100644 --- a/htlcswitch/hop/payload.go +++ b/htlcswitch/hop/payload.go @@ -133,14 +133,10 @@ func NewLegacyPayload(f *sphinx.HopData) *Payload { } } -// NewPayloadFromReader builds a new Hop from the passed io.Reader and returns -// a map of all the types that were found in the payload. The reader -// should correspond to the bytes encapsulated in a TLV onion payload. The -// final hop bool signals that this payload was the final packet parsed by -// sphinx. -func NewPayloadFromReader(r io.Reader, finalHop, - updateAddBlinding bool) (*Payload, map[tlv.Type][]byte, error) { - +// ParseTLVPayload builds a new Hop from the passed io.Reader and returns +// a map of all the types that were found in the payload. This function +// does not perform validation of TLV types included in the payload. +func ParseTLVPayload(r io.Reader) (*Payload, map[tlv.Type][]byte, error) { var ( cid uint64 amt uint64 @@ -175,25 +171,6 @@ func NewPayloadFromReader(r io.Reader, finalHop, return nil, nil, err } - // Validate whether the sender properly included or omitted tlv records - // in accordance with BOLT 04. - err = ValidateParsedPayloadTypes( - parsedTypes, finalHop, updateAddBlinding, - ) - if err != nil { - return nil, nil, err - } - - // Check for violation of the rules for mandatory fields. - violatingType := getMinRequiredViolation(parsedTypes) - if violatingType != nil { - return nil, nil, ErrInvalidPayload{ - Type: *violatingType, - Violation: RequiredViolation, - FinalHop: finalHop, - } - } - // If no MPP field was parsed, set the MPP field on the resulting // payload to nil. if _, ok := parsedTypes[record.MPPOnionType]; !ok { @@ -234,7 +211,34 @@ func NewPayloadFromReader(r io.Reader, finalHop, blindingPoint: blindingPoint, customRecords: customRecords, totalAmtMsat: lnwire.MilliSatoshi(totalAmtMsat), - }, nil, nil + }, parsedTypes, nil +} + +// ValidateTLVPayload validates the TLV fields that were included in a TLV +// payload. +func ValidateTLVPayload(parsedTypes map[tlv.Type][]byte, + finalHop bool, updateAddBlinding bool) error { + + // Validate whether the sender properly included or omitted tlv records + // in accordance with BOLT 04. + err := ValidateParsedPayloadTypes( + parsedTypes, finalHop, updateAddBlinding, + ) + if err != nil { + return err + } + + // Check for violation of the rules for mandatory fields. + violatingType := getMinRequiredViolation(parsedTypes) + if violatingType != nil { + return ErrInvalidPayload{ + Type: *violatingType, + Violation: RequiredViolation, + FinalHop: finalHop, + } + } + + return nil } // ForwardingInfo returns the basic parameters required for HTLC forwarding, diff --git a/htlcswitch/hop/payload_test.go b/htlcswitch/hop/payload_test.go index 666cf64bc..c22144d7b 100644 --- a/htlcswitch/hop/payload_test.go +++ b/htlcswitch/hop/payload_test.go @@ -547,9 +547,13 @@ func testDecodeHopPayloadValidation(t *testing.T, test decodePayloadTest) { testChildIndex = uint32(9) ) - p, _, err := hop.NewPayloadFromReader( - bytes.NewReader(test.payload), test.isFinalHop, - test.updateAddBlinded, + p, parsedTypes, err := hop.ParseTLVPayload( + bytes.NewReader(test.payload), + ) + require.NoError(t, err) + + err = hop.ValidateTLVPayload( + parsedTypes, test.isFinalHop, test.updateAddBlinded, ) if !reflect.DeepEqual(test.expErr, err) { t.Fatalf("expected error mismatch, want: %v, got: %v", From 776c8892677d4b32d99ba62bed56f962f84d15e7 Mon Sep 17 00:00:00 2001 From: Carla Kirk-Cohen Date: Thu, 25 Apr 2024 09:46:31 -0400 Subject: [PATCH 033/109] multi: return route role from HopPayload We need to know what role we're playing to be able to handle errors correctly, but the information that we need for this is held by our iterator: - Whether we had a blinding point in update add (blinding kit) - Whether we had a blinding point in payload As we're now going to use the route role return value even when our err!=nil, we rename the error to signal that we're using less canonical golang here. An alternative to this approach is to attach a RouteRole to our ErrInvalidPayload. The downside of that approach is: - Propagate context through parsing (whether we had updateAddHtlc) - Clumsy handling for errors that are not of type ErrInvalidPayload --- .../htlc_incoming_contest_resolver.go | 2 +- .../htlc_incoming_contest_resolver_test.go | 4 +- htlcswitch/hop/iterator.go | 105 ++++++++++++++++-- htlcswitch/hop/iterator_test.go | 6 +- htlcswitch/link.go | 13 ++- htlcswitch/mock.go | 4 +- 6 files changed, 110 insertions(+), 24 deletions(-) diff --git a/contractcourt/htlc_incoming_contest_resolver.go b/contractcourt/htlc_incoming_contest_resolver.go index e73e3e45b..b104f8d70 100644 --- a/contractcourt/htlc_incoming_contest_resolver.go +++ b/contractcourt/htlc_incoming_contest_resolver.go @@ -543,7 +543,7 @@ func (h *htlcIncomingContestResolver) decodePayload() (*hop.Payload, return nil, nil, err } - payload, err := iterator.HopPayload() + payload, _, err := iterator.HopPayload() if err != nil { return nil, nil, err } diff --git a/contractcourt/htlc_incoming_contest_resolver_test.go b/contractcourt/htlc_incoming_contest_resolver_test.go index 6c4ba6bc4..55d93a6fb 100644 --- a/contractcourt/htlc_incoming_contest_resolver_test.go +++ b/contractcourt/htlc_incoming_contest_resolver_test.go @@ -263,7 +263,7 @@ type mockHopIterator struct { hop.Iterator } -func (h *mockHopIterator) HopPayload() (*hop.Payload, error) { +func (h *mockHopIterator) HopPayload() (*hop.Payload, hop.RouteRole, error) { var nextAddress [8]byte if !h.isExit { nextAddress = [8]byte{0x01} @@ -275,7 +275,7 @@ func (h *mockHopIterator) HopPayload() (*hop.Payload, error) { ForwardAmount: 100, OutgoingCltv: 40, ExtraBytes: [12]byte{}, - }), nil + }), hop.RouteRoleCleartext, nil } func (h *mockHopIterator) EncodeNextHop(w io.Writer) error { diff --git a/htlcswitch/hop/iterator.go b/htlcswitch/hop/iterator.go index 7ba0e9dd8..c387bae3a 100644 --- a/htlcswitch/hop/iterator.go +++ b/htlcswitch/hop/iterator.go @@ -24,6 +24,62 @@ var ( "blinded hop") ) +// RouteRole represents the different types of roles a node can have as a +// recipient of a HTLC. +type RouteRole uint8 + +const ( + // RouteRoleCleartext represents a regular route hop. + RouteRoleCleartext RouteRole = iota + + // RouteRoleIntroduction represents an introduction node in a blinded + // path, characterized by a blinding point in the onion payload. + RouteRoleIntroduction + + // RouteRoleRelaying represents a relaying node in a blinded path, + // characterized by a blinding point in update_add_htlc. + RouteRoleRelaying +) + +// String representation of a role in a route. +func (h RouteRole) String() string { + switch h { + case RouteRoleCleartext: + return "cleartext" + + case RouteRoleRelaying: + return "blinded relay" + + case RouteRoleIntroduction: + return "introduction node" + + default: + return fmt.Sprintf("unknown route role: %d", h) + } +} + +// NewRouteRole returns the role we're playing in a route depending on the +// blinding points set (or not). If we are in the situation where we received +// blinding points in both the update add message and the payload: +// - We must have had a valid update add blinding point, because we were able +// to decrypt our onion to get the payload blinding point. +// - We return a relaying node role, because an introduction node (by +// definition) does not receive a blinding point in update add. +// - We assume the sending node to be buggy (including a payload blinding +// where it shouldn't), and rely on validation elsewhere to handle this. +func NewRouteRole(updateAddBlinding, payloadBlinding bool) RouteRole { + switch { + case updateAddBlinding: + return RouteRoleRelaying + + case payloadBlinding: + return RouteRoleIntroduction + + default: + return RouteRoleCleartext + } +} + // Iterator is an interface that abstracts away the routing information // included in HTLC's which includes the entirety of the payment path of an // HTLC. This interface provides two basic method which carry out: how to @@ -35,8 +91,11 @@ type Iterator interface { // information encoded within the returned ForwardingInfo is to be used // by each hop to authenticate the information given to it by the prior // hop. The payload will also contain any additional TLV fields provided - // by the sender. - HopPayload() (*Payload, error) + // by the sender. The role that this hop plays in the context of + // route blinding (regular, introduction or relaying) is returned + // whenever the payload is successfully parsed, even if we subsequently + // face a validation error. + HopPayload() (*Payload, RouteRole, error) // EncodeNextHop encodes the onion packet destined for the next hop // into the passed io.Writer. @@ -95,18 +154,21 @@ func (r *sphinxHopIterator) EncodeNextHop(w io.Writer) error { // HopPayload returns the set of fields that detail exactly _how_ this hop // should forward the HTLC to the next hop. Additionally, the information // encoded within the returned ForwardingInfo is to be used by each hop to -// authenticate the information given to it by the prior hop. The payload will -// also contain any additional TLV fields provided by the sender. +// authenticate the information given to it by the prior hop. The role that +// this hop plays in the context of route blinding (regular, introduction or +// relaying) is returned whenever the payload is successfully parsed, even if +// we subsequently face a validation error. The payload will also contain any +// additional TLV fields provided by the sender. // // NOTE: Part of the HopIterator interface. -func (r *sphinxHopIterator) HopPayload() (*Payload, error) { +func (r *sphinxHopIterator) HopPayload() (*Payload, RouteRole, error) { switch r.processedPacket.Payload.Type { // If this is the legacy payload, then we'll extract the information // directly from the pre-populated ForwardingInstructions field. case sphinx.PayloadLegacy: fwdInst := r.processedPacket.ForwardingInstructions - return NewLegacyPayload(fwdInst), nil + return NewLegacyPayload(fwdInst), RouteRoleCleartext, nil // Otherwise, if this is the TLV payload, then we'll make a new stream // to decode only what we need to make routing decisions. @@ -116,14 +178,32 @@ func (r *sphinxHopIterator) HopPayload() (*Payload, error) { bytes.NewReader(r.processedPacket.Payload.Payload), ) if err != nil { - return nil, err + // If we couldn't even parse our payload then we do + // a best-effort of determining our role in a blinded + // route, accepting that we can't know whether we + // were the introduction node (as the payload + // is not parseable). + routeRole := RouteRoleCleartext + if r.blindingKit.UpdateAddBlinding.IsSome() { + routeRole = RouteRoleRelaying + } + + return nil, routeRole, err } + // Now that we've parsed our payload we can determine which + // role we're playing in the route. + _, payloadBlinding := parsed[record.BlindingPointOnionType] + routeRole := NewRouteRole( + r.blindingKit.UpdateAddBlinding.IsSome(), + payloadBlinding, + ) + if err := ValidateTLVPayload( parsed, isFinal, r.blindingKit.UpdateAddBlinding.IsSome(), ); err != nil { - return nil, err + return nil, routeRole, err } // If we had an encrypted data payload present, pull out our @@ -133,17 +213,18 @@ func (r *sphinxHopIterator) HopPayload() (*Payload, error) { payload, isFinal, parsed, ) if err != nil { - return nil, err + return nil, routeRole, err } payload.FwdInfo = *fwdInfo } - return payload, err + return payload, routeRole, nil default: - return nil, fmt.Errorf("unknown sphinx payload type: %v", - r.processedPacket.Payload.Type) + return nil, RouteRoleCleartext, + fmt.Errorf("unknown sphinx payload type: %v", + r.processedPacket.Payload.Type) } } diff --git a/htlcswitch/hop/iterator_test.go b/htlcswitch/hop/iterator_test.go index a850c6dc1..e69361b0a 100644 --- a/htlcswitch/hop/iterator_test.go +++ b/htlcswitch/hop/iterator_test.go @@ -88,10 +88,10 @@ func TestSphinxHopIteratorForwardingInstructions(t *testing.T) { for i, testCase := range testCases { iterator.processedPacket = testCase.sphinxPacket - pld, err := iterator.HopPayload() - if err != nil { + pld, _, pldErr := iterator.HopPayload() + if pldErr != nil { t.Fatalf("#%v: unable to extract forwarding "+ - "instructions: %v", i, err) + "instructions: %v", i, pldErr) } fwdInfo := pld.ForwardingInfo() diff --git a/htlcswitch/link.go b/htlcswitch/link.go index fd87c2f29..5f250636d 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -3293,14 +3293,18 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg, heightNow := l.cfg.BestHeight() - pld, err := chanIterator.HopPayload() - if err != nil { + pld, _, pldErr := chanIterator.HopPayload() + if pldErr != nil { // If we're unable to process the onion payload, or we // received invalid onion payload failure, then we // should send an error back to the caller so the HTLC // can be canceled. var failedType uint64 - if e, ok := err.(hop.ErrInvalidPayload); ok { + + // We need to get the underlying error value, so we + // can't use errors.As as suggested by the linter. + //nolint:errorlint + if e, ok := pldErr.(hop.ErrInvalidPayload); ok { failedType = uint64(e.Type) } @@ -3316,7 +3320,8 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg, ) l.log.Errorf("unable to decode forwarding "+ - "instructions: %v", err) + "instructions: %v", pldErr) + continue } diff --git a/htlcswitch/mock.go b/htlcswitch/mock.go index dfa834c58..0dbefd45c 100644 --- a/htlcswitch/mock.go +++ b/htlcswitch/mock.go @@ -330,10 +330,10 @@ func newMockHopIterator(hops ...*hop.Payload) hop.Iterator { return &mockHopIterator{hops: hops} } -func (r *mockHopIterator) HopPayload() (*hop.Payload, error) { +func (r *mockHopIterator) HopPayload() (*hop.Payload, hop.RouteRole, error) { h := r.hops[0] r.hops = r.hops[1:] - return h, nil + return h, hop.RouteRoleCleartext, nil } func (r *mockHopIterator) ExtraOnionBlob() []byte { From 9f038c6191ee90a19fbf863a01a67d0ee5a3fd10 Mon Sep 17 00:00:00 2001 From: Carla Kirk-Cohen Date: Mon, 8 Apr 2024 10:22:56 -0400 Subject: [PATCH 034/109] htlcswitch: introduce wrapper type error encrypter to identify blinded Introduce two wrapper types for our existing SphinxErrorEncrypter that are used to represent error encrypters where we're a part of a blinded route. These encrypters are functionally the same as a sphinx encrypter, and are just used as "markers" so that we know that we need to handle our error differently due to our different role. We need to persist this information to account for restart cases where we've resovled the outgoing HTLC, then restart and need to handle the error for the incoming link. Specifically, this is relevant for: - On chain resolution messages received after restart - Forwarding packages that are re-forwarded after restart This is also generally helpful, because we can store this information in one place (the circuit) rather than trying to reconstruct it in various places when forwarding the failure back over the switch. --- htlcswitch/circuit.go | 6 +++ htlcswitch/hop/error_encryptor.go | 77 ++++++++++++++++++++++++++++++- 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/htlcswitch/circuit.go b/htlcswitch/circuit.go index efb2a4779..700b087f5 100644 --- a/htlcswitch/circuit.go +++ b/htlcswitch/circuit.go @@ -205,6 +205,12 @@ func (c *PaymentCircuit) Decode(r io.Reader) error { // Test encrypter. c.ErrorEncrypter = NewMockObfuscator() + case hop.EncrypterTypeIntroduction: + c.ErrorEncrypter = hop.NewIntroductionErrorEncrypter() + + case hop.EncrypterTypeRelaying: + c.ErrorEncrypter = hop.NewRelayingErrorEncrypter() + default: return UnknownEncrypterType(encrypterType) } diff --git a/htlcswitch/hop/error_encryptor.go b/htlcswitch/hop/error_encryptor.go index 7b6a3dd1a..127370e4d 100644 --- a/htlcswitch/hop/error_encryptor.go +++ b/htlcswitch/hop/error_encryptor.go @@ -25,6 +25,18 @@ const ( // EncrypterTypeMock is used to identify a mock obfuscator instance. EncrypterTypeMock = 2 + + // EncrypterTypeIntroduction is used to identify a sphinx onion error + // encrypter where we are the introduction node in a blinded route. It + // has the same functionality as EncrypterTypeSphinx, but is used to + // mark our special-case error handling. + EncrypterTypeIntroduction = 3 + + // EncrypterTypeRelaying is used to identify a sphinx onion error + // encryper where we are a relaying node in a blinded route. It has + // the same functionality as a EncrypterTypeSphinx, but is used to mark + // our special-case error handling. + EncrypterTypeRelaying = 4 ) // ErrorEncrypterExtracter defines a function signature that extracts an @@ -197,9 +209,72 @@ func (s *SphinxErrorEncrypter) Reextract( s.OnionErrorEncrypter = sphinxEncrypter.OnionErrorEncrypter return nil - } // A compile time check to ensure SphinxErrorEncrypter implements the // ErrorEncrypter interface. var _ ErrorEncrypter = (*SphinxErrorEncrypter)(nil) + +// A compile time check to ensure that IntroductionErrorEncrypter implements +// the ErrorEncrypter interface. +var _ ErrorEncrypter = (*IntroductionErrorEncrypter)(nil) + +// IntroductionErrorEncrypter is a wrapper type on SphinxErrorEncrypter which +// is used to signal that we have special HTLC error handling for this hop. +type IntroductionErrorEncrypter struct { + // ErrorEncrypter is the underlying error encrypter, embedded + // directly in the struct so that we don't have to re-implement the + // ErrorEncrypter interface. + ErrorEncrypter +} + +// NewIntroductionErrorEncrypter returns a blank IntroductionErrorEncrypter. +func NewIntroductionErrorEncrypter() *IntroductionErrorEncrypter { + return &IntroductionErrorEncrypter{ + ErrorEncrypter: NewSphinxErrorEncrypter(), + } +} + +// Type returns the identifier for an introduction error encrypter. +func (i *IntroductionErrorEncrypter) Type() EncrypterType { + return EncrypterTypeIntroduction +} + +// Reextract rederives the error encrypter from the currently held EphemeralKey, +// relying on the logic in the underlying SphinxErrorEncrypter. +func (i *IntroductionErrorEncrypter) Reextract( + extract ErrorEncrypterExtracter) error { + + return i.ErrorEncrypter.Reextract(extract) +} + +// A compile time check to ensure that RelayingErrorEncrypte implements +// the ErrorEncrypter interface. +var _ ErrorEncrypter = (*RelayingErrorEncrypter)(nil) + +// RelayingErrorEncrypter is a wrapper type on SphinxErrorEncrypter which +// is used to signal that we have special HTLC error handling for this hop. +type RelayingErrorEncrypter struct { + ErrorEncrypter +} + +// NewRelayingErrorEncrypter returns a blank RelayingErrorEncrypter with +// an underlying SphinxErrorEncrypter. +func NewRelayingErrorEncrypter() *RelayingErrorEncrypter { + return &RelayingErrorEncrypter{ + ErrorEncrypter: NewSphinxErrorEncrypter(), + } +} + +// Type returns the identifier for a relaying error encrypter. +func (r *RelayingErrorEncrypter) Type() EncrypterType { + return EncrypterTypeRelaying +} + +// Reextract rederives the error encrypter from the currently held EphemeralKey, +// relying on the logic in the underlying SphinxErrorEncrypter. +func (r *RelayingErrorEncrypter) Reextract( + extract ErrorEncrypterExtracter) error { + + return r.ErrorEncrypter.Reextract(extract) +} From 72260adddb30c4e9c18a14e37f6abf5bcd365712 Mon Sep 17 00:00:00 2001 From: Carla Kirk-Cohen Date: Tue, 23 Apr 2024 12:33:04 -0400 Subject: [PATCH 035/109] htlcswitch: create error obfuscator with wrapped type for blinded Create our error encrypter with a wrapped type if we have a blinding point present. Doing this in the iterator allows us to track this information when we have both pieces of information available to us, compared to trying to handle this later down the line: - Downstream link on failure: we know that we've set a blinding point for out outgoing HTLC, but not whether we're introduction or not - Upstream link on failure: once the failure packet has been sent through the switch, we no longer know whether we were the introduction point (without looking it up / examining our payload again / propagating this information through the switch). --- htlcswitch/hop/iterator.go | 30 +++++++++++++--- htlcswitch/link.go | 70 +++++++++++++++++++++++++++----------- htlcswitch/mock.go | 2 +- 3 files changed, 77 insertions(+), 25 deletions(-) diff --git a/htlcswitch/hop/iterator.go b/htlcswitch/hop/iterator.go index c387bae3a..a89f1b734 100644 --- a/htlcswitch/hop/iterator.go +++ b/htlcswitch/hop/iterator.go @@ -103,8 +103,8 @@ type Iterator interface { // ExtractErrorEncrypter returns the ErrorEncrypter needed for this hop, // along with a failure code to signal if the decoding was successful. - ExtractErrorEncrypter(ErrorEncrypterExtracter) (ErrorEncrypter, - lnwire.FailCode) + ExtractErrorEncrypter(extractor ErrorEncrypterExtracter, + introductionNode bool) (ErrorEncrypter, lnwire.FailCode) } // sphinxHopIterator is the Sphinx implementation of hop iterator which uses @@ -235,9 +235,31 @@ func (r *sphinxHopIterator) HopPayload() (*Payload, RouteRole, error) { // // NOTE: Part of the HopIterator interface. func (r *sphinxHopIterator) ExtractErrorEncrypter( - extracter ErrorEncrypterExtracter) (ErrorEncrypter, lnwire.FailCode) { + extracter ErrorEncrypterExtracter, introductionNode bool) ( + ErrorEncrypter, lnwire.FailCode) { - return extracter(r.ogPacket.EphemeralKey) + encrypter, errCode := extracter(r.ogPacket.EphemeralKey) + if errCode != lnwire.CodeNone { + return nil, errCode + } + + // If we're in a blinded path, wrap the error encrypter that we just + // derived in a "marker" type which we'll use to know what type of + // error we're handling. + switch { + case introductionNode: + return &IntroductionErrorEncrypter{ + ErrorEncrypter: encrypter, + }, errCode + + case r.blindingKit.UpdateAddBlinding.IsSome(): + return &RelayingErrorEncrypter{ + ErrorEncrypter: encrypter, + }, errCode + + default: + return encrypter, errCode + } } // BlindingProcessor is an interface that provides the cryptographic operations diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 5f250636d..b5cba787c 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -3262,7 +3262,7 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg, // DecodeHopIterator function which process the Sphinx packet. chanIterator, failureCode := decodeResps[i].Result() if failureCode != lnwire.CodeNone { - // If we're unable to process the onion blob than we + // If we're unable to process the onion blob then we // should send the malformed htlc error to payment // sender. l.sendMalformedHTLCError(pd.HtlcIndex, failureCode, @@ -3273,27 +3273,9 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg, continue } - // Retrieve onion obfuscator from onion blob in order to - // produce initial obfuscation of the onion failureCode. - obfuscator, failureCode := chanIterator.ExtractErrorEncrypter( - l.cfg.ExtractErrorEncrypter, - ) - if failureCode != lnwire.CodeNone { - // If we're unable to process the onion blob than we - // should send the malformed htlc error to payment - // sender. - l.sendMalformedHTLCError( - pd.HtlcIndex, failureCode, onionBlob[:], pd.SourceRef, - ) - - l.log.Errorf("unable to decode onion "+ - "obfuscator: %v", failureCode) - continue - } - heightNow := l.cfg.BestHeight() - pld, _, pldErr := chanIterator.HopPayload() + pld, routeRole, pldErr := chanIterator.HopPayload() if pldErr != nil { // If we're unable to process the onion payload, or we // received invalid onion payload failure, then we @@ -3308,6 +3290,33 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg, failedType = uint64(e.Type) } + // If we couldn't parse the payload, make our best + // effort at creating an error encrypter that knows + // what blinding type we were, but if we couldn't + // parse the payload we have no way of knowing whether + // we were the introduction node or not. + // + //nolint:lll + obfuscator, failCode := chanIterator.ExtractErrorEncrypter( + l.cfg.ExtractErrorEncrypter, + // We need our route role here because we + // couldn't parse or validate the payload. + routeRole == hop.RouteRoleIntroduction, + ) + if failCode != lnwire.CodeNone { + l.log.Errorf("could not extract error "+ + "encrypter: %v", pldErr) + + // We can't process this htlc, send back + // malformed. + l.sendMalformedHTLCError( + pd.HtlcIndex, failureCode, + onionBlob[:], pd.SourceRef, + ) + + continue + } + // TODO: currently none of the test unit infrastructure // is setup to handle TLV payloads, so testing this // would require implementing a separate mock iterator @@ -3325,6 +3334,27 @@ func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg, continue } + // Retrieve onion obfuscator from onion blob in order to + // produce initial obfuscation of the onion failureCode. + obfuscator, failureCode := chanIterator.ExtractErrorEncrypter( + l.cfg.ExtractErrorEncrypter, + routeRole == hop.RouteRoleIntroduction, + ) + if failureCode != lnwire.CodeNone { + // If we're unable to process the onion blob than we + // should send the malformed htlc error to payment + // sender. + l.sendMalformedHTLCError( + pd.HtlcIndex, failureCode, onionBlob[:], + pd.SourceRef, + ) + + l.log.Errorf("unable to decode onion "+ + "obfuscator: %v", failureCode) + + continue + } + fwdInfo := pld.ForwardingInfo() // Check whether the payload we've just processed uses our diff --git a/htlcswitch/mock.go b/htlcswitch/mock.go index 0dbefd45c..cd3e5026b 100644 --- a/htlcswitch/mock.go +++ b/htlcswitch/mock.go @@ -341,7 +341,7 @@ func (r *mockHopIterator) ExtraOnionBlob() []byte { } func (r *mockHopIterator) ExtractErrorEncrypter( - extracter hop.ErrorEncrypterExtracter) (hop.ErrorEncrypter, + extracter hop.ErrorEncrypterExtracter, _ bool) (hop.ErrorEncrypter, lnwire.FailCode) { return extracter(nil) From de9c9c028c64566f75dbf00d4b05c448128f53e9 Mon Sep 17 00:00:00 2001 From: Carla Kirk-Cohen Date: Mon, 8 Apr 2024 15:14:11 -0400 Subject: [PATCH 036/109] htlcswitch: set packet obfuscator for failures through switch Set obfuscator for use in blinded error handling when we forward failures through the switch. --- htlcswitch/mailbox.go | 1 + htlcswitch/switch.go | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/htlcswitch/mailbox.go b/htlcswitch/mailbox.go index 99066497c..a729e3ba5 100644 --- a/htlcswitch/mailbox.go +++ b/htlcswitch/mailbox.go @@ -738,6 +738,7 @@ func (m *memoryMailBox) FailAdd(pkt *htlcPacket) { sourceRef: pkt.sourceRef, hasSource: true, localFailure: localFailure, + obfuscator: pkt.obfuscator, linkFailure: linkError, htlc: &lnwire.UpdateFailHTLC{ Reason: reason, diff --git a/htlcswitch/switch.go b/htlcswitch/switch.go index 70b819b1e..d473d8422 100644 --- a/htlcswitch/switch.go +++ b/htlcswitch/switch.go @@ -1297,6 +1297,11 @@ func (s *Switch) handlePacketForward(packet *htlcPacket) error { fail, isFail := htlc.(*lnwire.UpdateFailHTLC) if isFail && !packet.hasSource { + // HTLC resolutions and messages restored from disk + // don't have the obfuscator set from the original htlc + // add packet - set it here for use in blinded errors. + packet.obfuscator = circuit.ErrorEncrypter + switch { // No message to encrypt, locally sourced payment. case circuit.ErrorEncrypter == nil: @@ -1485,6 +1490,7 @@ func (s *Switch) failAddPacket(packet *htlcPacket, failure *LinkError) error { incomingTimeout: packet.incomingTimeout, outgoingTimeout: packet.outgoingTimeout, circuit: packet.circuit, + obfuscator: packet.obfuscator, linkFailure: failure, htlc: &lnwire.UpdateFailHTLC{ Reason: reason, @@ -1841,6 +1847,10 @@ out: // resolution message on restart. resolutionMsg.errChan <- nil + // Create a htlc packet for this resolution. We do + // not have some of the information that we'll need + // for blinded error handling here , so we'll rely on + // our forwarding logic to fill it in later. pkt := &htlcPacket{ outgoingChanID: resolutionMsg.SourceChan, outgoingHTLCID: resolutionMsg.HtlcIndex, @@ -2065,6 +2075,8 @@ func (s *Switch) reforwardResolutions() error { // The circuit is still open, so we can assume that the link or // switch (if we are the source) hasn't cleaned it up yet. + // We rely on our forwarding logic to fill in details that + // are not currently available to us. resPkt := &htlcPacket{ outgoingChanID: resMsg.SourceChan, outgoingHTLCID: resMsg.HtlcIndex, @@ -2214,7 +2226,8 @@ func (s *Switch) reforwardSettleFails(fwdPkgs []*channeldb.FwdPkg) { // we can continue to propagate it. This // failure originated from another node, so // the linkFailure field is not set on this - // packet. + // packet. We rely on the link to fill in + // additional circuit information for us. failPacket := &htlcPacket{ outgoingChanID: fwdPkg.Source, outgoingHTLCID: pd.ParentIndex, From 43687181f73a59a65460d562f897acb83f6cddf8 Mon Sep 17 00:00:00 2001 From: Carla Kirk-Cohen Date: Mon, 8 Apr 2024 15:51:15 -0400 Subject: [PATCH 037/109] htlcswitch: convert blinded failures for blinded payments --- htlcswitch/hop/error_encryptor.go | 6 ++ htlcswitch/link.go | 118 ++++++++++++++++++++++++++++-- 2 files changed, 117 insertions(+), 7 deletions(-) diff --git a/htlcswitch/hop/error_encryptor.go b/htlcswitch/hop/error_encryptor.go index 127370e4d..23272ec00 100644 --- a/htlcswitch/hop/error_encryptor.go +++ b/htlcswitch/hop/error_encryptor.go @@ -39,6 +39,12 @@ const ( EncrypterTypeRelaying = 4 ) +// IsBlinded returns a boolean indicating whether the error encrypter belongs +// to a blinded route. +func (e EncrypterType) IsBlinded() bool { + return e == EncrypterTypeIntroduction || e == EncrypterTypeRelaying +} + // ErrorEncrypterExtracter defines a function signature that extracts an // ErrorEncrypter from an sphinx OnionPacket. type ErrorEncrypterExtracter func(*btcec.PublicKey) (ErrorEncrypter, diff --git a/htlcswitch/link.go b/htlcswitch/link.go index b5cba787c..ed3151728 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -1793,8 +1793,20 @@ func (l *channelLink) handleDownstreamPkt(pkt *htlcPacket) { htlc.ID = pkt.incomingHTLCID // We send the HTLC message to the peer which initially created - // the HTLC. - l.cfg.Peer.SendMessage(false, htlc) + // the HTLC. If the incoming blinding point is non-nil, we + // know that we are a relaying node in a blinded path. + // Otherwise, we're either an introduction node or not part of + // a blinded path at all. + if err := l.sendIncomingHTLCFailureMsg( + htlc.ID, + pkt.obfuscator, + htlc.Reason, + ); err != nil { + l.log.Errorf("unable to send HTLC failure: %v", + err) + + return + } // If the packet does not have a link failure set, it failed // further down the route so we notify a forwarding failure. @@ -3720,11 +3732,14 @@ func (l *channelLink) sendHTLCError(pd *lnwallet.PaymentDescriptor, return } - l.cfg.Peer.SendMessage(false, &lnwire.UpdateFailHTLC{ - ChanID: l.ChanID(), - ID: pd.HtlcIndex, - Reason: reason, - }) + // Send the appropriate failure message depending on whether we're + // in a blinded route or not. + if err := l.sendIncomingHTLCFailureMsg( + pd.HtlcIndex, e, reason, + ); err != nil { + l.log.Errorf("unable to send HTLC failure: %v", err) + return + } // Notify a link failure on our incoming link. Outgoing htlc information // is not available at this point, because we have not decrypted the @@ -3753,6 +3768,95 @@ func (l *channelLink) sendHTLCError(pd *lnwallet.PaymentDescriptor, ) } +// sendPeerHTLCFailure handles sending a HTLC failure message back to the +// peer from which the HTLC was received. This function is primarily used to +// handle the special requirements of route blinding, specifically: +// - Forwarding nodes must switch out any errors with MalformedFailHTLC +// - Introduction nodes should return regular HTLC failure messages. +// +// It accepts the original opaque failure, which will be used in the case +// that we're not part of a blinded route and an error encrypter that'll be +// used if we are the introduction node and need to present an error as if +// we're the failing party. +// +// Note: this function does not yet handle special error cases for receiving +// nodes in blinded paths, as LND does not support blinded receives. +func (l *channelLink) sendIncomingHTLCFailureMsg(htlcIndex uint64, + e hop.ErrorEncrypter, + originalFailure lnwire.OpaqueReason) error { + + var msg lnwire.Message + switch { + // Our circuit's error encrypter will be nil if this was a locally + // initiated payment. We can only hit a blinded error for a locally + // initiated payment if we allow ourselves to be picked as the + // introduction node for our own payments and in that case we + // shouldn't reach this code. To prevent the HTLC getting stuck, + // we fail it back and log an error. + // code. + case e == nil: + msg = &lnwire.UpdateFailHTLC{ + ChanID: l.ChanID(), + ID: htlcIndex, + Reason: originalFailure, + } + + l.log.Errorf("Unexpected blinded failure when "+ + "we are the sending node, incoming htlc: %v(%v)", + l.ShortChanID(), htlcIndex) + + // For cleartext hops (ie, non-blinded/normal) we don't need any + // transformation on the error message and can just send the original. + case !e.Type().IsBlinded(): + msg = &lnwire.UpdateFailHTLC{ + ChanID: l.ChanID(), + ID: htlcIndex, + Reason: originalFailure, + } + + // When we're the introduction node, we need to convert the error to + // a UpdateFailHTLC. + case e.Type() == hop.EncrypterTypeIntroduction: + l.log.Debugf("Introduction blinded node switching out failure "+ + "error: %v", htlcIndex) + + // The specification does not require that we set the onion + // blob. + failureMsg := lnwire.NewInvalidBlinding(nil) + reason, err := e.EncryptFirstHop(failureMsg) + if err != nil { + return err + } + + msg = &lnwire.UpdateFailHTLC{ + ChanID: l.ChanID(), + ID: htlcIndex, + Reason: reason, + } + + // If we are a relaying node, we need to switch out any error that + // we've received to a malformed HTLC error. + case e.Type() == hop.EncrypterTypeRelaying: + l.log.Debugf("Relaying blinded node switching out malformed "+ + "error: %v", htlcIndex) + + msg = &lnwire.UpdateFailMalformedHTLC{ + ChanID: l.ChanID(), + ID: htlcIndex, + FailureCode: lnwire.CodeInvalidBlinding, + } + + default: + return fmt.Errorf("unexpected encrypter: %d", e) + } + + if err := l.cfg.Peer.SendMessage(false, msg); err != nil { + l.log.Warnf("Send update fail failed: %v", err) + } + + return nil +} + // sendMalformedHTLCError helper function which sends the malformed HTLC update // to the payment sender. func (l *channelLink) sendMalformedHTLCError(htlcIndex uint64, From d13a73a93a97bb34a9dbb63ee5a43662a7fa31c2 Mon Sep 17 00:00:00 2001 From: Carla Kirk-Cohen Date: Thu, 15 Feb 2024 09:18:51 -0500 Subject: [PATCH 038/109] itest: add test coverage for failure at blinded receiver --- itest/list_on_test.go | 4 +++ itest/lnd_route_blinding_test.go | 56 ++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/itest/list_on_test.go b/itest/list_on_test.go index 4696fc80e..8f8574d5b 100644 --- a/itest/list_on_test.go +++ b/itest/list_on_test.go @@ -566,6 +566,10 @@ var allTestCases = []*lntest.TestCase{ Name: "forward blinded", TestFunc: testForwardBlindedRoute, }, + { + Name: "receiver blinded error", + TestFunc: testReceiverBlindedError, + }, { Name: "removetx", TestFunc: testRemoveTx, diff --git a/itest/lnd_route_blinding_test.go b/itest/lnd_route_blinding_test.go index e2d1ec033..2e41e4ba0 100644 --- a/itest/lnd_route_blinding_test.go +++ b/itest/lnd_route_blinding_test.go @@ -788,3 +788,59 @@ func testForwardBlindedRoute(ht *lntest.HarnessTest) { ht.AssertHTLCNotActive(ht.Bob, testCase.channels[1], hash[:]) ht.AssertHTLCNotActive(ht.Alice, testCase.channels[0], hash[:]) } + +// Tests handling of errors from the receiving node in a blinded route, testing +// a payment over: Alice -- Bob -- Carol -- Dave, where Bob is the introduction +// node. +// +// Note that at present the payment fails at Dave because we do not yet support +// receiving to blinded routes. In future, we can substitute this test out to +// trigger an IncorrectPaymentDetails failure. In the meantime, this test +// provides valuable coverage for the case where a node in the route is not +// spec compliant (ie, does not return the blinded failure and just uses a +// normal one) because Dave will not appropriately convert the error. +func testReceiverBlindedError(ht *lntest.HarnessTest) { + ctx, testCase := newBlindedForwardTest(ht) + defer testCase.cleanup() + route := testCase.setup(ctx) + + sendAndResumeBlindedPayment(ctx, ht, testCase, route) +} + +// sendAndResumeBlindedPayment sends a blinded payment through the test +// network provided, intercepting the payment at Carol and allowing it to +// resume. This utility function allows us to ensure that payments at least +// reach Carol and asserts that all errors appear to originate from the +// introduction node. +func sendAndResumeBlindedPayment(ctx context.Context, ht *lntest.HarnessTest, + testCase *blindedForwardTest, route *routing.BlindedPayment) { + + blindedRoute := testCase.createRouteToBlinded(10_000_000, route) + + // Before we dispatch the payment, spin up a goroutine that will + // intercept the HTLC on Carol's forward. This allows us to ensure + // that the HTLC actually reaches the location we expect it to. + resolveHTLC := testCase.interceptFinalHop() + + // First, test sending the payment all the way through to Dave. We + // expect this payment to fail, because he does not know how to + // process payments to a blinded route (not yet supported). + testCase.sendBlindedPayment(ctx, blindedRoute) + + // When Carol intercepts the HTLC, instruct her to resume the payment + // so that it'll reach Dave and fail. + resolveHTLC(routerrpc.ResolveHoldForwardAction_RESUME) + + // Wait for the HTLC to reflect as failed for Alice. + preimage, err := lntypes.MakePreimage(testCase.preimage[:]) + require.NoError(ht, err) + pmt := ht.AssertPaymentStatus(ht.Alice, preimage, lnrpc.Payment_FAILED) + require.Len(ht, pmt.Htlcs, 1) + require.EqualValues( + ht, 1, pmt.Htlcs[0].Failure.FailureSourceIndex, + ) + require.Equal( + ht, lnrpc.Failure_INVALID_ONION_BLINDING, + pmt.Htlcs[0].Failure.Code, + ) +} From 4535cf6c650e374461e8d9e03514274185d7c699 Mon Sep 17 00:00:00 2001 From: Carla Kirk-Cohen Date: Thu, 15 Feb 2024 09:55:41 -0500 Subject: [PATCH 039/109] itest: add coverage for failure within a blinded route --- itest/list_on_test.go | 4 +++ itest/lnd_route_blinding_test.go | 57 ++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/itest/list_on_test.go b/itest/list_on_test.go index 8f8574d5b..677f4cf9e 100644 --- a/itest/list_on_test.go +++ b/itest/list_on_test.go @@ -570,6 +570,10 @@ var allTestCases = []*lntest.TestCase{ Name: "receiver blinded error", TestFunc: testReceiverBlindedError, }, + { + Name: "relayer blinded error", + TestFunc: testRelayingBlindedError, + }, { Name: "removetx", TestFunc: testRemoveTx, diff --git a/itest/lnd_route_blinding_test.go b/itest/lnd_route_blinding_test.go index 2e41e4ba0..b2e0cf9d3 100644 --- a/itest/lnd_route_blinding_test.go +++ b/itest/lnd_route_blinding_test.go @@ -524,6 +524,43 @@ func (b *blindedForwardTest) interceptFinalHop() func(routerrpc.ResolveHoldForwa return resolve } +// drainCarolLiquidity will drain all of the liquidity in Carol's channel in +// the direction requested: +// - incoming: Carol has no incoming liquidity from Bob +// - outgoing: Carol has no outgoing liquidity to Dave. +func (b *blindedForwardTest) drainCarolLiquidity(incoming bool) { + sendingNode := b.carol + receivingNode := b.dave + + if incoming { + sendingNode = b.ht.Bob + receivingNode = b.carol + } + + resp := sendingNode.RPC.ListChannels(&lnrpc.ListChannelsRequest{ + Peer: receivingNode.PubKey[:], + }) + require.Len(b.ht, resp.Channels, 1) + + // We can't send our channel reserve, and leave some buffer for fees. + paymentAmt := resp.Channels[0].LocalBalance - + int64(resp.Channels[0].RemoteConstraints.ChanReserveSat) - 25000 + + invoice := receivingNode.RPC.AddInvoice(&lnrpc.Invoice{ + // Leave some leeway for fees for the HTLC. + Value: paymentAmt, + }) + + pmtClient := sendingNode.RPC.SendPayment( + &routerrpc.SendPaymentRequest{ + PaymentRequest: invoice.PaymentRequest, + TimeoutSeconds: 60, + }, + ) + + b.ht.AssertPaymentStatusFromStream(pmtClient, lnrpc.Payment_SUCCEEDED) +} + // setupFourHopNetwork creates a network with the following topology and // liquidity: // Alice (100k)----- Bob (100k) ----- Carol (100k) ----- Dave @@ -807,6 +844,26 @@ func testReceiverBlindedError(ht *lntest.HarnessTest) { sendAndResumeBlindedPayment(ctx, ht, testCase, route) } +// testRelayingBlindedError tests handling of errors from relaying nodes in a +// blinded route, testing a failure over on Carol's outgoing link in the +// following topology: Alice -- Bob -- Carol -- Dave, where Bob is the +// introduction node. +func testRelayingBlindedError(ht *lntest.HarnessTest) { + ctx, testCase := newBlindedForwardTest(ht) + defer testCase.cleanup() + route := testCase.setup(ctx) + + // Before we send our payment, drain all of Carol's liquidity + // so that she can't forward the payment to Dave. + testCase.drainCarolLiquidity(false) + + // Then dispatch the payment through Carol which will fail due to + // a lack of liquidity. This check only happens _after_ the interceptor + // has given the instruction to resume so we can use test + // infrastructure that will go ahead and intercept the payment. + sendAndResumeBlindedPayment(ctx, ht, testCase, route) +} + // sendAndResumeBlindedPayment sends a blinded payment through the test // network provided, intercepting the payment at Carol and allowing it to // resume. This utility function allows us to ensure that payments at least From 428a33fbda6c6c2a7b136af7ef09a5a4a6c48590 Mon Sep 17 00:00:00 2001 From: Carla Kirk-Cohen Date: Thu, 15 Feb 2024 10:13:41 -0500 Subject: [PATCH 040/109] itest: add coverage for failure at the introduction node --- itest/list_on_test.go | 4 ++++ itest/lnd_route_blinding_test.go | 34 +++++++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/itest/list_on_test.go b/itest/list_on_test.go index 677f4cf9e..18285c85f 100644 --- a/itest/list_on_test.go +++ b/itest/list_on_test.go @@ -574,6 +574,10 @@ var allTestCases = []*lntest.TestCase{ Name: "relayer blinded error", TestFunc: testRelayingBlindedError, }, + { + Name: "introduction blinded error", + TestFunc: testIntroductionNodeError, + }, { Name: "removetx", TestFunc: testRemoveTx, diff --git a/itest/lnd_route_blinding_test.go b/itest/lnd_route_blinding_test.go index b2e0cf9d3..7cedbf3f0 100644 --- a/itest/lnd_route_blinding_test.go +++ b/itest/lnd_route_blinding_test.go @@ -841,7 +841,7 @@ func testReceiverBlindedError(ht *lntest.HarnessTest) { defer testCase.cleanup() route := testCase.setup(ctx) - sendAndResumeBlindedPayment(ctx, ht, testCase, route) + sendAndResumeBlindedPayment(ctx, ht, testCase, route, true) } // testRelayingBlindedError tests handling of errors from relaying nodes in a @@ -861,7 +861,7 @@ func testRelayingBlindedError(ht *lntest.HarnessTest) { // a lack of liquidity. This check only happens _after_ the interceptor // has given the instruction to resume so we can use test // infrastructure that will go ahead and intercept the payment. - sendAndResumeBlindedPayment(ctx, ht, testCase, route) + sendAndResumeBlindedPayment(ctx, ht, testCase, route, true) } // sendAndResumeBlindedPayment sends a blinded payment through the test @@ -870,14 +870,18 @@ func testRelayingBlindedError(ht *lntest.HarnessTest) { // reach Carol and asserts that all errors appear to originate from the // introduction node. func sendAndResumeBlindedPayment(ctx context.Context, ht *lntest.HarnessTest, - testCase *blindedForwardTest, route *routing.BlindedPayment) { + testCase *blindedForwardTest, route *routing.BlindedPayment, + interceptAtCarol bool) { blindedRoute := testCase.createRouteToBlinded(10_000_000, route) // Before we dispatch the payment, spin up a goroutine that will // intercept the HTLC on Carol's forward. This allows us to ensure // that the HTLC actually reaches the location we expect it to. - resolveHTLC := testCase.interceptFinalHop() + var resolveHTLC func(routerrpc.ResolveHoldForwardAction) + if interceptAtCarol { + resolveHTLC = testCase.interceptFinalHop() + } // First, test sending the payment all the way through to Dave. We // expect this payment to fail, because he does not know how to @@ -886,7 +890,9 @@ func sendAndResumeBlindedPayment(ctx context.Context, ht *lntest.HarnessTest, // When Carol intercepts the HTLC, instruct her to resume the payment // so that it'll reach Dave and fail. - resolveHTLC(routerrpc.ResolveHoldForwardAction_RESUME) + if interceptAtCarol { + resolveHTLC(routerrpc.ResolveHoldForwardAction_RESUME) + } // Wait for the HTLC to reflect as failed for Alice. preimage, err := lntypes.MakePreimage(testCase.preimage[:]) @@ -901,3 +907,21 @@ func sendAndResumeBlindedPayment(ctx context.Context, ht *lntest.HarnessTest, pmt.Htlcs[0].Failure.Code, ) } + +// testIntroductionNodeError tests handling of errors in a blinded route when +// the introduction node is the source of the error. This test sends a payment +// over Alice -- Bob -- Carol -- Dave, where Bob is the introduction node and +// has insufficient outgoing liquidity to forward on to carol. +func testIntroductionNodeError(ht *lntest.HarnessTest) { + ctx, testCase := newBlindedForwardTest(ht) + defer testCase.cleanup() + route := testCase.setup(ctx) + + // Before we send our payment, drain all of Carol's incoming liquidity + // so that she can't receive the forward from Bob, causing a failure + // at the introduction node. + testCase.drainCarolLiquidity(true) + + // Send the payment, but do not expect it to reach Carol at all. + sendAndResumeBlindedPayment(ctx, ht, testCase, route, false) +} From d57c6fab47d186f0a687f352364ce761d1feb81d Mon Sep 17 00:00:00 2001 From: Carla Kirk-Cohen Date: Fri, 15 Mar 2024 11:53:52 -0400 Subject: [PATCH 041/109] itest: add coverage for disabling blinded forwards --- itest/list_on_test.go | 4 ++++ itest/lnd_route_blinding_test.go | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/itest/list_on_test.go b/itest/list_on_test.go index 18285c85f..796a96805 100644 --- a/itest/list_on_test.go +++ b/itest/list_on_test.go @@ -578,6 +578,10 @@ var allTestCases = []*lntest.TestCase{ Name: "introduction blinded error", TestFunc: testIntroductionNodeError, }, + { + Name: "disable introduction node", + TestFunc: testDisableIntroductionNode, + }, { Name: "removetx", TestFunc: testRemoveTx, diff --git a/itest/lnd_route_blinding_test.go b/itest/lnd_route_blinding_test.go index 7cedbf3f0..4cbd75ff6 100644 --- a/itest/lnd_route_blinding_test.go +++ b/itest/lnd_route_blinding_test.go @@ -925,3 +925,23 @@ func testIntroductionNodeError(ht *lntest.HarnessTest) { // Send the payment, but do not expect it to reach Carol at all. sendAndResumeBlindedPayment(ctx, ht, testCase, route, false) } + +// testDisableIntroductionNode tests disabling of blinded forwards for the +// introduction node. +func testDisableIntroductionNode(ht *lntest.HarnessTest) { + // Disable route blinding for Bob, then re-connect to Alice. + ht.RestartNodeWithExtraArgs(ht.Bob, []string{ + "--protocol.no-route-blinding", + }) + ht.EnsureConnected(ht.Alice, ht.Bob) + + ctx, testCase := newBlindedForwardTest(ht) + defer testCase.cleanup() + route := testCase.setup(ctx) + // We always expect failures to look like they originated at Bob + // because blinded errors are converted. However, our tests intercepts + // all of Carol's forwards and we're not providing it any interceptor + // instructions. This means that the test will hang/timeout at Carol + // if Bob _doesn't_ fail the HTLC back as expected. + sendAndResumeBlindedPayment(ctx, ht, testCase, route, false) +} From 5b2869b0ecb7aa4d00ca34d12b9b0918cd1a8a0f Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Sun, 17 Mar 2024 15:51:09 -0400 Subject: [PATCH 042/109] tlv: add new Blob type alias In this commit, we add a new type alias for a blob type. This type can be used in areas where a byte slice is used to store a TLV value, which may be a fully opaque nested TLV. --- tlv/go.mod | 12 ++++++------ tlv/go.sum | 31 ++++++++++++------------------- tlv/record.go | 4 ++++ 3 files changed, 22 insertions(+), 25 deletions(-) diff --git a/tlv/go.mod b/tlv/go.mod index f61284752..bfc3922c6 100644 --- a/tlv/go.mod +++ b/tlv/go.mod @@ -1,23 +1,23 @@ module github.com/lightningnetwork/lnd/tlv require ( - github.com/btcsuite/btcd v0.23.3 - github.com/btcsuite/btcd/btcec/v2 v2.1.3 + github.com/btcsuite/btcd v0.24.1-0.20240301210420-1a2b599bf1af + github.com/btcsuite/btcd/btcec/v2 v2.3.2 github.com/davecgh/go-spew v1.1.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 github.com/lightningnetwork/lnd/fn v1.0.4 - github.com/stretchr/testify v1.8.2 + github.com/stretchr/testify v1.8.4 golang.org/x/exp v0.0.0-20231226003508-02704c960a9b ) require ( - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect github.com/kr/pretty v0.3.0 // indirect github.com/lightninglabs/neutrino/cache v1.1.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rogpeppe/go-internal v1.9.0 // indirect - golang.org/x/crypto v0.7.0 // indirect - golang.org/x/sys v0.13.0 // indirect + golang.org/x/crypto v0.16.0 // indirect + golang.org/x/sys v0.15.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/tlv/go.sum b/tlv/go.sum index 25b1c26c2..fb4166322 100644 --- a/tlv/go.sum +++ b/tlv/go.sum @@ -1,11 +1,10 @@ -github.com/btcsuite/btcd v0.23.3 h1:4KH/JKy9WiCd+iUS9Mu0Zp7Dnj17TGdKrg9xc/FGj24= -github.com/btcsuite/btcd v0.23.3/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= -github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= -github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd v0.24.1-0.20240301210420-1a2b599bf1af h1:F60A3wst4/fy9Yr1Vn8MYmFlfn7DNLxp8o8UTvhqgBE= +github.com/btcsuite/btcd v0.24.1-0.20240301210420-1a2b599bf1af/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg= +github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= +github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= @@ -28,24 +27,18 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/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.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20231226003508-02704c960a9b h1:kLiC65FbiHWFAOu+lxwNPujcsl8VYyTYYEZnsOO1WK4= golang.org/x/exp v0.0.0-20231226003508-02704c960a9b/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/tlv/record.go b/tlv/record.go index a872e6004..7813ee771 100644 --- a/tlv/record.go +++ b/tlv/record.go @@ -17,6 +17,10 @@ type Type uint64 // slice containing the encoded data. type TypeMap map[Type][]byte +// Blob is a type alias for a byte slice. It's used to indicate that a slice of +// bytes is actually an encoded TLV stream. +type Blob = []byte + // Encoder is a signature for methods that can encode TLV values. An error // should be returned if the Encoder cannot support the underlying type of val. // The provided scratch buffer must be non-nil. From 956b00b5993f987190d7c2d002c203dbe1cbd95e Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Sat, 30 Mar 2024 17:24:38 -0700 Subject: [PATCH 043/109] tlv: add in new BigSizeT type This type is useful when one wants to encode an integer as an underlying BigSize record. It wraps any integer, then handles the transformation into and out of the BigSize encoding on disk. --- tlv/record_type.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tlv/record_type.go b/tlv/record_type.go index 297617d5a..46c68a323 100644 --- a/tlv/record_type.go +++ b/tlv/record_type.go @@ -159,3 +159,30 @@ func ZeroRecordT[T TlvType, V any]() RecordT[T, V] { Val: v, } } + +// BigSizeT is a high-order type that represents a TLV record that encodes an +// integer as a BigSize value in the stream. +type BigSizeT[T constraints.Integer] struct { + // We'll store the base value in the struct as a uin64, but then expose + // a public method to cast to the specified type. + v uint64 +} + +// NewBigSizeT creates a new BigSizeT type from a given integer type. +func NewBigSizeT[T constraints.Integer](val T) BigSizeT[T] { + return BigSizeT[T]{ + v: uint64(val), + } +} + +// Int returns the underlying integer value of the BigSize record. +func (b BigSizeT[T]) Int() T { + return T(b.v) +} + +// Record returns the underlying record interface for the record type. +func (t *BigSizeT[T]) Record() Record { + // We use a zero value for the type here as this should be used with + // the higher order RecordT type. + return MakeBigSizeRecord(0, &t.v) +} From c6dae6c3c0056518cd8b1b1ab6bd748fc252383e Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Thu, 25 Apr 2024 16:51:12 +0200 Subject: [PATCH 044/109] tlv: rename receivers, add ValOpt ValOpt returns an Option of the underlying value. --- tlv/record_type.go | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/tlv/record_type.go b/tlv/record_type.go index 46c68a323..9bfcd1aaa 100644 --- a/tlv/record_type.go +++ b/tlv/record_type.go @@ -104,15 +104,15 @@ type OptionalRecordT[T TlvType, V any] struct { // TlvType returns the type of the record. This is the value used to identify // this type on the wire. This value is bound to the specified TlvType type // param. -func (t *OptionalRecordT[T, V]) TlvType() Type { +func (o *OptionalRecordT[T, V]) TlvType() Type { zeroRecord := ZeroRecordT[T, V]() return zeroRecord.TlvType() } // WhenSomeV executes the given function if the optional record is present. // This operates on the inner most type, V, which is the value of the record. -func (t *OptionalRecordT[T, V]) WhenSomeV(f func(V)) { - t.Option.WhenSome(func(r RecordT[T, V]) { +func (o *OptionalRecordT[T, V]) WhenSomeV(f func(V)) { + o.Option.WhenSome(func(r RecordT[T, V]) { f(r.Val) }) } @@ -126,7 +126,7 @@ func (o *OptionalRecordT[T, V]) UnwrapOrFailV(t *testing.T) V { return inner.Val } -// UnwrapOrErr is used to extract a value from an option, if the option is +// UnwrapOrErrV is used to extract a value from an option, if the option is // empty, then the specified error is returned directly. This gives the // underlying value of the record, instead of the record itself. func (o *OptionalRecordT[T, V]) UnwrapOrErrV(err error) (V, error) { @@ -141,10 +141,19 @@ func (o *OptionalRecordT[T, V]) UnwrapOrErrV(err error) (V, error) { } // Zero returns a zero value of the record type. -func (t *OptionalRecordT[T, V]) Zero() RecordT[T, V] { +func (o *OptionalRecordT[T, V]) Zero() RecordT[T, V] { return ZeroRecordT[T, V]() } +// ValOpt returns an Option of the underlying value. This can be used to chain +// other option related methods to avoid needing to first go through the outer +// record. +func (o *OptionalRecordT[T, V]) ValOpt() fn.Option[V] { + return fn.MapOption(func(record RecordT[T, V]) V { + return record.Val + })(o.Option) +} + // SomeRecordT creates a new OptionalRecordT type from a given RecordT type. func SomeRecordT[T TlvType, V any](record RecordT[T, V]) OptionalRecordT[T, V] { return OptionalRecordT[T, V]{ @@ -181,8 +190,8 @@ func (b BigSizeT[T]) Int() T { } // Record returns the underlying record interface for the record type. -func (t *BigSizeT[T]) Record() Record { +func (b *BigSizeT[T]) Record() Record { // We use a zero value for the type here as this should be used with // the higher order RecordT type. - return MakeBigSizeRecord(0, &t.v) + return MakeBigSizeRecord(0, &b.v) } From e8031fdccfad9b488b4161455001b8ab21e791a9 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 23 Apr 2024 18:33:39 -0700 Subject: [PATCH 045/109] lnrpc: ensure parsing of the Amp flag for payments is consistent In this commit, we fix an inconsistent in the API related to AMP payments. When a payment request isn't specified, we require the `--amp` flag on the CLI to make an AMP payment. However, for payment requests, we don't require this flag. To fix this inconsistency, we now require the `--amp` flag to _also_ be set for payment requests. --- docs/release-notes/release-notes-0.18.0.md | 5 +++ itest/lnd_amp_test.go | 3 ++ lnrpc/routerrpc/router_backend.go | 8 +++++ lntest/harness.go | 39 ++++++++++++++++++++-- 4 files changed, 52 insertions(+), 3 deletions(-) diff --git a/docs/release-notes/release-notes-0.18.0.md b/docs/release-notes/release-notes-0.18.0.md index cb638c0ee..01a821db6 100644 --- a/docs/release-notes/release-notes-0.18.0.md +++ b/docs/release-notes/release-notes-0.18.0.md @@ -368,6 +368,10 @@ bitcoin peers' feefilter values into account](https://github.com/lightningnetwor whether through gRPC or the REST API, due to the destructive nature of the operation. +* When paying an AMP payment request, [the `--amp` flag is now + required](https://github.com/lightningnetwork/lnd/pull/8681) to be consistent + w/ the flow when a payment request isn't used. + ## lncli Updates * [Documented all available `lncli` @@ -532,6 +536,7 @@ bitcoin peers' feefilter values into account](https://github.com/lightningnetwor * Marcos Fernandez Perez * Matt Morehouse * Mohamed Awnallah +* Olaoluwa Osuntokun * Ononiwu Maureen Chiamaka * Slyghtning * Tee8z diff --git a/itest/lnd_amp_test.go b/itest/lnd_amp_test.go index a96911319..23bfd8654 100644 --- a/itest/lnd_amp_test.go +++ b/itest/lnd_amp_test.go @@ -129,6 +129,7 @@ func testSendPaymentAMPInvoiceCase(ht *lntest.HarnessTest, PaymentAddr: externalPayAddr, TimeoutSeconds: 60, FeeLimitMsat: noFeeLimitMsat, + Amp: true, } payment := ht.SendPaymentAssertSettled(mts.alice, sendReq) @@ -252,6 +253,7 @@ func testSendPaymentAMPInvoiceRepeat(ht *lntest.HarnessTest) { // Now we'll use Carol to pay the invoice that Dave created. ht.CompletePaymentRequests( carol, []string{addInvoiceResp.PaymentRequest}, + lntest.WithAMP(), ) // Dave should get a notification that the invoice has been settled. @@ -274,6 +276,7 @@ func testSendPaymentAMPInvoiceRepeat(ht *lntest.HarnessTest) { // has received another payment. ht.CompletePaymentRequests( carol, []string{addInvoiceResp.PaymentRequest}, + lntest.WithAMP(), ) // Dave should get another notification. diff --git a/lnrpc/routerrpc/router_backend.go b/lnrpc/routerrpc/router_backend.go index 18233991d..9fde63411 100644 --- a/lnrpc/routerrpc/router_backend.go +++ b/lnrpc/routerrpc/router_backend.go @@ -940,6 +940,14 @@ func (r *RouterBackend) extractIntentFromSendRequest( payAddr := payReq.PaymentAddr if payReq.Features.HasFeature(lnwire.AMPOptional) { + // The opt-in AMP flag is required to pay an AMP + // invoice. + if !rpcPayReq.Amp { + return nil, fmt.Errorf("the AMP flag (--amp " + + "or SendPaymentRequest.Amp) must be " + + "set to pay an AMP invoice") + } + // Generate random SetID and root share. var setID [32]byte _, err = rand.Read(setID[:]) diff --git a/lntest/harness.go b/lntest/harness.go index 5c2bef488..889bb156e 100644 --- a/lntest/harness.go +++ b/lntest/harness.go @@ -105,6 +105,32 @@ type HarnessTest struct { cleaned bool } +// harnessOpts contains functional option to modify the behavior of the various +// harness calls. +type harnessOpts struct { + useAMP bool +} + +// defaultHarnessOpts returns a new instance of the harnessOpts with default +// values specified. +func defaultHarnessOpts() harnessOpts { + return harnessOpts{ + useAMP: false, + } +} + +// HarnessOpt is a functional option that can be used to modify the behavior of +// harness functionality. +type HarnessOpt func(*harnessOpts) + +// WithAMP is a functional option that can be used to enable the AMP feature +// for sending payments. +func WithAMP() HarnessOpt { + return func(h *harnessOpts) { + h.useAMP = true + } +} + // NewHarnessTest creates a new instance of a harnessTest from a regular // testing.T instance. func NewHarnessTest(t *testing.T, lndBinary string, feeService WebFeeService, @@ -1438,7 +1464,13 @@ func (h *HarnessTest) FundCoinsP2TR(amt btcutil.Amount, // all payment requests. This function does not return until all payments // have reached the specified status. func (h *HarnessTest) completePaymentRequestsAssertStatus(hn *node.HarnessNode, - paymentRequests []string, status lnrpc.Payment_PaymentStatus) { + paymentRequests []string, status lnrpc.Payment_PaymentStatus, + opts ...HarnessOpt) { + + payOpts := defaultHarnessOpts() + for _, opt := range opts { + opt(&payOpts) + } // Create a buffered chan to signal the results. results := make(chan rpc.PaymentClient, len(paymentRequests)) @@ -1449,6 +1481,7 @@ func (h *HarnessTest) completePaymentRequestsAssertStatus(hn *node.HarnessNode, PaymentRequest: payReq, TimeoutSeconds: int32(wait.PaymentTimeout.Seconds()), FeeLimitMsat: noFeeLimitMsat, + Amp: payOpts.useAMP, } stream := hn.RPC.SendPayment(req) @@ -1477,10 +1510,10 @@ func (h *HarnessTest) completePaymentRequestsAssertStatus(hn *node.HarnessNode, // requests. This function does not return until all payments successfully // complete without errors. func (h *HarnessTest) CompletePaymentRequests(hn *node.HarnessNode, - paymentRequests []string) { + paymentRequests []string, opts ...HarnessOpt) { h.completePaymentRequestsAssertStatus( - hn, paymentRequests, lnrpc.Payment_SUCCEEDED, + hn, paymentRequests, lnrpc.Payment_SUCCEEDED, opts..., ) } From d0441a2a291db1cf2c538b31e7c95269b3aef987 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 26 Apr 2024 02:34:25 +0800 Subject: [PATCH 046/109] multi: add default conf targt in SendCoins/SendMany/OpenChannel/CloseChannel --- itest/lnd_misc_test.go | 15 ++++++---- rpcserver.go | 66 +++++++++++++++++++++++++++++++++++++++--- sweep/walletsweep.go | 7 ----- 3 files changed, 72 insertions(+), 16 deletions(-) diff --git a/itest/lnd_misc_test.go b/itest/lnd_misc_test.go index 163fc436d..3c247c4a1 100644 --- a/itest/lnd_misc_test.go +++ b/itest/lnd_misc_test.go @@ -815,13 +815,18 @@ func testSweepAllCoins(ht *lntest.HarnessTest) { TargetConf: 6, }) + // TODO(yy): we still allow default values to be used when neither conf + // target or fee rate is set in 0.18.0. When future release forbidden + // this behavior, we should revive the test below, which asserts either + // conf target or fee rate is set. + // // Send coins to a compatible address without specifying fee rate or // conf target. - ainz.RPC.SendCoinsAssertErr(&lnrpc.SendCoinsRequest{ - Addr: ht.Miner.NewMinerAddress().String(), - SendAll: true, - Label: sendCoinsLabel, - }) + // ainz.RPC.SendCoinsAssertErr(&lnrpc.SendCoinsRequest{ + // Addr: ht.Miner.NewMinerAddress().String(), + // SendAll: true, + // Label: sendCoinsLabel, + // }) // Send coins to a compatible address. ainz.RPC.SendCoins(&lnrpc.SendCoinsRequest{ diff --git a/rpcserver.go b/rpcserver.go index fad2cc307..6b90dab65 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -85,6 +85,13 @@ import ( "gopkg.in/macaroon-bakery.v2/bakery" ) +const ( + // defaultNumBlocksEstimate is the number of blocks that we fall back + // to issuing an estimate for if a fee pre fence doesn't specify an + // explicit conf target or fee rate. + defaultNumBlocksEstimate = 6 +) + var ( // readPermissions is a slice of all entities that allow read // permissions for authorization purposes, all lowercase. @@ -1239,15 +1246,46 @@ func (r *rpcServer) EstimateFee(ctx context.Context, return resp, nil } +// maybeUseDefaultConf makes sure that when the user doesn't set either the fee +// rate or conf target, the default conf target is used. +func maybeUseDefaultConf(satPerByte int64, satPerVByte uint64, + targetConf uint32) uint32 { + + // If the fee rate is set, there's no need to use the default conf + // target. In this case, we just return the targetConf from the + // request. + if satPerByte != 0 || satPerVByte != 0 { + return targetConf + } + + // Return the user specified conf target if set. + if targetConf != 0 { + return targetConf + } + + // If the fee rate is not set, yet the conf target is zero, the default + // 6 will be returned. + rpcsLog.Errorf("Expected either 'sat_per_vbyte' or 'conf_target' to " + + "be set, using default conf of 6 instead") + + return defaultNumBlocksEstimate +} + // SendCoins executes a request to send coins to a particular address. Unlike // SendMany, this RPC call only allows creating a single output at a time. func (r *rpcServer) SendCoins(ctx context.Context, in *lnrpc.SendCoinsRequest) (*lnrpc.SendCoinsResponse, error) { + // Keep the old behavior prior to 0.18.0 - when the user doesn't set + // fee rate or conf target, the default conf target of 6 is used. + targetConf := maybeUseDefaultConf( + in.SatPerByte, in.SatPerVbyte, uint32(in.TargetConf), + ) + // Calculate an appropriate fee rate for this transaction. feePerKw, err := lnrpc.CalculateFeeRate( uint64(in.SatPerByte), in.SatPerVbyte, // nolint:staticcheck - uint32(in.TargetConf), r.server.cc.FeeEstimator, + targetConf, r.server.cc.FeeEstimator, ) if err != nil { return nil, err @@ -1465,10 +1503,16 @@ func (r *rpcServer) SendCoins(ctx context.Context, func (r *rpcServer) SendMany(ctx context.Context, in *lnrpc.SendManyRequest) (*lnrpc.SendManyResponse, error) { + // Keep the old behavior prior to 0.18.0 - when the user doesn't set + // fee rate or conf target, the default conf target of 6 is used. + targetConf := maybeUseDefaultConf( + in.SatPerByte, in.SatPerVbyte, uint32(in.TargetConf), + ) + // Calculate an appropriate fee rate for this transaction. feePerKw, err := lnrpc.CalculateFeeRate( uint64(in.SatPerByte), in.SatPerVbyte, // nolint:staticcheck - uint32(in.TargetConf), r.server.cc.FeeEstimator, + targetConf, r.server.cc.FeeEstimator, ) if err != nil { return nil, err @@ -2129,10 +2173,17 @@ func (r *rpcServer) parseOpenChannelReq(in *lnrpc.OpenChannelRequest, // Skip estimating fee rate for PSBT funding. if in.FundingShim == nil || in.FundingShim.GetPsbtShim() == nil { + // Keep the old behavior prior to 0.18.0 - when the user + // doesn't set fee rate or conf target, the default conf target + // of 6 is used. + targetConf := maybeUseDefaultConf( + in.SatPerByte, in.SatPerVbyte, uint32(in.TargetConf), + ) + // Calculate an appropriate fee rate for this transaction. feeRate, err = lnrpc.CalculateFeeRate( uint64(in.SatPerByte), in.SatPerVbyte, - uint32(in.TargetConf), r.server.cc.FeeEstimator, + targetConf, r.server.cc.FeeEstimator, ) if err != nil { return nil, err @@ -2680,12 +2731,19 @@ func (r *rpcServer) CloseChannel(in *lnrpc.CloseChannelRequest, "is offline (try force closing it instead): %v", err) } + // Keep the old behavior prior to 0.18.0 - when the user + // doesn't set fee rate or conf target, the default conf target + // of 6 is used. + targetConf := maybeUseDefaultConf( + in.SatPerByte, in.SatPerVbyte, uint32(in.TargetConf), + ) + // Based on the passed fee related parameters, we'll determine // an appropriate fee rate for the cooperative closure // transaction. feeRate, err := lnrpc.CalculateFeeRate( uint64(in.SatPerByte), in.SatPerVbyte, // nolint:staticcheck - uint32(in.TargetConf), r.server.cc.FeeEstimator, + targetConf, r.server.cc.FeeEstimator, ) if err != nil { return err diff --git a/sweep/walletsweep.go b/sweep/walletsweep.go index 5328ae508..8eb3764a1 100644 --- a/sweep/walletsweep.go +++ b/sweep/walletsweep.go @@ -16,13 +16,6 @@ import ( "github.com/lightningnetwork/lnd/lnwallet/chanfunding" ) -const ( - // defaultNumBlocksEstimate is the number of blocks that we fall back - // to issuing an estimate for if a fee pre fence doesn't specify an - // explicit conf target or fee rate. - defaultNumBlocksEstimate = 6 -) - var ( // ErrNoFeePreference is returned when we attempt to satisfy a sweep // request from a client whom did not specify a fee preference. From db52e7e381687bfb6d264845e4eacdd16b3f822c Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 26 Apr 2024 02:42:14 +0800 Subject: [PATCH 047/109] docs: update release notes --- docs/release-notes/release-notes-0.18.0.md | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/docs/release-notes/release-notes-0.18.0.md b/docs/release-notes/release-notes-0.18.0.md index ff4a947d8..f21f14aa6 100644 --- a/docs/release-notes/release-notes-0.18.0.md +++ b/docs/release-notes/release-notes-0.18.0.md @@ -342,14 +342,6 @@ bitcoin peers' feefilter values into account](https://github.com/lightningnetwor add coin selection strategy option to the following on-chain RPC calls `EstimateFee`, `SendMany`, `SendCoins`, `BatchOpenChannel`, `SendOutputs`, and `FundPsbt`. -* Previously when callng `SendCoins`, `SendMany`, `OpenChannel` and - `CloseChannel` for coop close, it is allowed to specify both an empty - `SatPerVbyte` and `TargetConf`, and a default conf target of 6 will be used. - This is [no longer allowed]( - https://github.com/lightningnetwork/lnd/pull/8422) and the caller must - specify either `SatPerVbyte` or `TargetConf` so the fee estimator can do a - proper fee estimation. - * `BumpFee` has been updated to take advantage of the [new budget-based sweeper](https://github.com/lightningnetwork/lnd/pull/8667). The param `force` has been deprecated and replaced with a new param `immediate`, and a @@ -421,6 +413,18 @@ bitcoin peers' feefilter values into account](https://github.com/lightningnetwor manage the lifecycle of the inputs. ## Breaking Changes + +* Previously when callng `SendCoins`, `SendMany`, `OpenChannel` and + `CloseChannel` for coop close, it is allowed to specify both an empty + `SatPerVbyte` and `TargetConf`, and a default conf target of 6 will be used. + This will [no longer be + allowed](https://github.com/lightningnetwork/lnd/pull/8422) in the next + release (v0.19.0) and the caller must specify either `SatPerVbyte` or + `TargetConf` so the fee estimator can do a proper fee estimation. For current + release, [an error will be + logged](https://github.com/lightningnetwork/lnd/pull/8693) when no values are + specified. + ## Performance Improvements * Watchtower client DB migration to massively [improve the start-up From ba34f220b9d30de93376b31c73cec67df47ad7a4 Mon Sep 17 00:00:00 2001 From: bitromortac Date: Fri, 26 Apr 2024 13:21:25 +0200 Subject: [PATCH 048/109] make: add cache directory for linter Mounts a local temporary folder to the linter docker container in order to persist the linter cache across runs. --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 41fabbfcc..088bb4880 100644 --- a/Makefile +++ b/Makefile @@ -69,6 +69,7 @@ DOCKER_TOOLS = docker run \ --rm \ -v $(shell bash -c "go env GOCACHE || (mkdir -p /tmp/go-cache; echo /tmp/go-cache)"):/tmp/build/.cache \ -v $(shell bash -c "go env GOMODCACHE || (mkdir -p /tmp/go-modcache; echo /tmp/go-modcache)"):/tmp/build/.modcache \ + -v $(shell bash -c "mkdir -p /tmp/go-lint-cache; echo /tmp/go-lint-cache"):/root/.cache/golangci-lint \ -v $$(pwd):/build lnd-tools GREEN := "\\033[0;32m" From 2140f1940f55ae7a78b27f7305f7a977d003aed7 Mon Sep 17 00:00:00 2001 From: Carla Kirk-Cohen Date: Thu, 25 Apr 2024 13:38:00 -0400 Subject: [PATCH 049/109] itest: manually set timeout on cancel payment and provide cancel For tests where our payments require an on-chain resolution, provide longer timeout and return cancel functions. --- itest/lnd_route_blinding_test.go | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/itest/lnd_route_blinding_test.go b/itest/lnd_route_blinding_test.go index 4cbd75ff6..8a796c2dd 100644 --- a/itest/lnd_route_blinding_test.go +++ b/itest/lnd_route_blinding_test.go @@ -448,9 +448,11 @@ func (b *blindedForwardTest) createRouteToBlinded(paymentAmt int64, return resp.Routes[0] } -// sendBlindedPayment dispatches a payment to the route provided. +// sendBlindedPayment dispatches a payment to the route provided, returning a +// cancel function for the payment. Timeout is set for very long to allow +// time for on-chain resolution. func (b *blindedForwardTest) sendBlindedPayment(ctx context.Context, - route *lnrpc.Route) { + route *lnrpc.Route) func() { hash := sha256.Sum256(b.preimage[:]) sendReq := &routerrpc.SendToRouteRequest{ @@ -458,11 +460,13 @@ func (b *blindedForwardTest) sendBlindedPayment(ctx context.Context, Route: route, } - // Dispatch in a goroutine because this call is blocking - we assume - // that we'll have assertions that this payment is sent by the caller. + ctx, cancel := context.WithTimeout(ctx, time.Hour) go func() { - b.ht.Alice.RPC.SendToRouteV2(sendReq) + _, err := b.ht.Alice.RPC.Router.SendToRouteV2(ctx, sendReq) + require.NoError(b.ht, err) }() + + return cancel } // interceptFinalHop launches a goroutine to intercept Carol's htlcs and @@ -805,7 +809,8 @@ func testForwardBlindedRoute(ht *lntest.HarnessTest) { resolveHTLC := testCase.interceptFinalHop() // Once our interceptor is set up, we can send the blinded payment. - testCase.sendBlindedPayment(ctx, blindedRoute) + cancelPmt := testCase.sendBlindedPayment(ctx, blindedRoute) + defer cancelPmt() // Wait for the HTLC to be active on Alice's channel. hash := sha256.Sum256(testCase.preimage[:]) @@ -886,7 +891,8 @@ func sendAndResumeBlindedPayment(ctx context.Context, ht *lntest.HarnessTest, // First, test sending the payment all the way through to Dave. We // expect this payment to fail, because he does not know how to // process payments to a blinded route (not yet supported). - testCase.sendBlindedPayment(ctx, blindedRoute) + cancelPmt := testCase.sendBlindedPayment(ctx, blindedRoute) + defer cancelPmt() // When Carol intercepts the HTLC, instruct her to resume the payment // so that it'll reach Dave and fail. From 75d4a4c295e1307ad8de065c1b1e8e46249696d2 Mon Sep 17 00:00:00 2001 From: Carla Kirk-Cohen Date: Mon, 8 Apr 2024 11:46:43 -0400 Subject: [PATCH 050/109] itest: add coverage for blinded error resolution from on-chain failure This itest adds a test that we still propagate blinded errors back properly after a restart with an on-chain resolution. The test also updates our sendpayment timeout to longer so that there's time to resolve the on chain claim. --- itest/list_on_test.go | 4 ++ itest/lnd_route_blinding_test.go | 109 ++++++++++++++++++++++++++++++- 2 files changed, 111 insertions(+), 2 deletions(-) diff --git a/itest/list_on_test.go b/itest/list_on_test.go index 796a96805..2434ee92d 100644 --- a/itest/list_on_test.go +++ b/itest/list_on_test.go @@ -582,6 +582,10 @@ var allTestCases = []*lntest.TestCase{ Name: "disable introduction node", TestFunc: testDisableIntroductionNode, }, + { + Name: "on chain to blinded", + TestFunc: testErrorHandlingOnChainFailure, + }, { Name: "removetx", TestFunc: testRemoveTx, diff --git a/itest/lnd_route_blinding_test.go b/itest/lnd_route_blinding_test.go index 8a796c2dd..1cae46a0c 100644 --- a/itest/lnd_route_blinding_test.go +++ b/itest/lnd_route_blinding_test.go @@ -355,14 +355,16 @@ func (b *blindedForwardTest) setup( ctx context.Context) *routing.BlindedPayment { b.carol = b.ht.NewNode("Carol", []string{ - "requireinterceptor", + "--requireinterceptor", "--bitcoin.timelockdelta=18", }) var err error b.carolInterceptor, err = b.carol.RPC.Router.HtlcInterceptor(ctx) require.NoError(b.ht, err, "interceptor") - b.dave = b.ht.NewNode("Dave", nil) + b.dave = b.ht.NewNode("Dave", []string{ + "--bitcoin.timelockdelta=18", + }) b.channels = setupFourHopNetwork(b.ht, b.carol, b.dave) @@ -951,3 +953,106 @@ func testDisableIntroductionNode(ht *lntest.HarnessTest) { // if Bob _doesn't_ fail the HTLC back as expected. sendAndResumeBlindedPayment(ctx, ht, testCase, route, false) } + +// testErrorHandlingOnChainFailure tests handling of blinded errors when we're +// resolving from an on-chain resolution. This test also tests that we're able +// to resolve blinded HTLCs on chain between restarts, as we've got all the +// infrastructure in place already for error testing. +func testErrorHandlingOnChainFailure(ht *lntest.HarnessTest) { + // Setup a test case, note that we don't use its built in clean up + // because we're going to close a channel so we'll close out the + // rest manually. + ctx, testCase := newBlindedForwardTest(ht) + + // Note that we send a larger amount here do it'll be worthwhile for + // the sweeper to claim. + route := testCase.setup(ctx) + blindedRoute := testCase.createRouteToBlinded(50_000_000, route) + + // Once our interceptor is set up, we can send the blinded payment. + cancelPmt := testCase.sendBlindedPayment(ctx, blindedRoute) + defer cancelPmt() + + // Wait for the HTLC to be active on Alice and Bob's channels. + hash := sha256.Sum256(testCase.preimage[:]) + ht.AssertOutgoingHTLCActive(ht.Alice, testCase.channels[0], hash[:]) + ht.AssertOutgoingHTLCActive(ht.Bob, testCase.channels[1], hash[:]) + + // Intercept the forward on Carol's link, but do not take any action + // so that we have the chance to force close with this HTLC in flight. + carolHTLC, err := testCase.carolInterceptor.Recv() + require.NoError(ht, err) + + // Force close Bob <-> Carol. + closeStream, _ := ht.CloseChannelAssertPending( + ht.Bob, testCase.channels[1], true, + ) + + ht.AssertStreamChannelForceClosed( + ht.Bob, testCase.channels[1], false, closeStream, + ) + + // SuspendCarol so that she can't interfere with the resolution of the + // HTLC from now on. + restartCarol := ht.SuspendNode(testCase.carol) + + // Mine blocks so that Bob will claim his CSV delayed local commitment, + // we've already mined 1 block so we need one less than our CSV. + ht.MineBlocks(node.DefaultCSV - 1) + ht.AssertNumPendingSweeps(ht.Bob, 1) + ht.MineEmptyBlocks(1) + ht.Miner.MineBlocksAndAssertNumTxes(1, 1) + + // Restart bob so that we can test that he's able to recover everything + // he needs to claim a blinded HTLC. + ht.RestartNode(ht.Bob) + + // Mine enough blocks for Bob to trigger timeout of his outgoing HTLC. + // Carol's incoming expiry height is Bob's outgoing so we can use this + // value. + info := ht.Bob.RPC.GetInfo() + target := carolHTLC.IncomingExpiry - info.BlockHeight + ht.MineBlocks(target) + + // Wait for Bob's timeout transaction in the mempool, since we've + // suspended Carol we don't need to account for her commitment output + // claim. + ht.Miner.MineBlocksAndAssertNumTxes(1, 1) + + // Assert that the HTLC has cleared. + ht.AssertHTLCNotActive(ht.Alice, testCase.channels[0], hash[:]) + ht.AssertHTLCNotActive(ht.Bob, testCase.channels[0], hash[:]) + + // Wait for the HTLC to reflect as failed for Alice. + paymentStream := ht.Alice.RPC.TrackPaymentV2(hash[:]) + htlcs := ht.ReceiveTrackPayment(paymentStream).Htlcs + require.Len(ht, htlcs, 1) + require.NotNil(ht, htlcs[0].Failure) + require.Equal( + ht, htlcs[0].Failure.Code, + lnrpc.Failure_INVALID_ONION_BLINDING, + ) + + // Clean up the rest of our force close: mine blocks so that Bob's CSV + // expires plus one block to trigger his sweep and then mine it. + ht.MineBlocks(node.DefaultCSV + 1) + ht.Miner.MineBlocksAndAssertNumTxes(1, 1) + + // Bring carol back up so that we can close out the rest of our + // channels cooperatively. She requires an interceptor to start up + // so we just re-register our interceptor. + require.NoError(ht, restartCarol()) + _, err = testCase.carol.RPC.Router.HtlcInterceptor(ctx) + require.NoError(ht, err, "interceptor") + + // Assert that Carol has started up and reconnected to dave so that + // we can close out channels cooperatively. + ht.EnsureConnected(testCase.carol, testCase.dave) + + // Manually close out the rest of our channels and cancel (don't use + // built in cleanup which will try close the already-force-closed + // channel). + ht.CloseChannel(ht.Alice, testCase.channels[0]) + ht.CloseChannel(testCase.carol, testCase.channels[2]) + testCase.cancel() +} From eaa85920ea1dca750eaa31b6f23c161135df24b0 Mon Sep 17 00:00:00 2001 From: Carla Kirk-Cohen Date: Sat, 17 Feb 2024 17:50:38 -0500 Subject: [PATCH 051/109] multi: enable optional route blinding feature --- feature/default_sets.go | 5 + feature/deps.go | 6 + feature/manager.go | 10 +- lnrpc/lightning.pb.go | 674 ++++++++++++++-------------- lnrpc/lightning.proto | 2 + lnrpc/lightning.swagger.json | 4 + lnrpc/peersrpc/peers.swagger.json | 2 + lnrpc/routerrpc/router.swagger.json | 2 + lnwire/features.go | 10 + server.go | 1 + 10 files changed, 383 insertions(+), 333 deletions(-) diff --git a/feature/default_sets.go b/feature/default_sets.go index 3b7e0f7ea..cc802fe85 100644 --- a/feature/default_sets.go +++ b/feature/default_sets.go @@ -79,6 +79,11 @@ var defaultSetDesc = setDesc{ SetInit: {}, // I SetNodeAnn: {}, // N }, + lnwire.RouteBlindingOptional: { + SetInit: {}, // I + SetNodeAnn: {}, // N + SetInvoice: {}, // 9 + }, lnwire.ShutdownAnySegwitOptional: { SetInit: {}, // I SetNodeAnn: {}, // N diff --git a/feature/deps.go b/feature/deps.go index b9fec2da0..350d49acf 100644 --- a/feature/deps.go +++ b/feature/deps.go @@ -79,6 +79,12 @@ var deps = depDesc{ lnwire.AnchorsZeroFeeHtlcTxOptional: {}, lnwire.ExplicitChannelTypeOptional: {}, }, + lnwire.RouteBlindingOptional: { + lnwire.TLVOnionPayloadOptional: {}, + }, + lnwire.RouteBlindingRequired: { + lnwire.TLVOnionPayloadRequired: {}, + }, } // ValidateDeps asserts that a feature vector sets all features and their diff --git a/feature/manager.go b/feature/manager.go index 98317eb8f..c7029e893 100644 --- a/feature/manager.go +++ b/feature/manager.go @@ -60,6 +60,9 @@ type Config struct { // segwit witness versions for co-op closes. NoAnySegwit bool + // NoRouteBlinding unsets route blinding feature bits. + NoRouteBlinding bool + // CustomFeatures is a set of custom features to advertise in each // set. CustomFeatures map[Set][]lnwire.FeatureBit @@ -123,6 +126,8 @@ func newManager(cfg Config, desc setDesc) (*Manager, error) { raw.Unset(lnwire.PaymentAddrRequired) raw.Unset(lnwire.MPPOptional) raw.Unset(lnwire.MPPRequired) + raw.Unset(lnwire.RouteBlindingOptional) + raw.Unset(lnwire.RouteBlindingRequired) raw.Unset(lnwire.AMPOptional) raw.Unset(lnwire.AMPRequired) raw.Unset(lnwire.KeysendOptional) @@ -179,7 +184,10 @@ func newManager(cfg Config, desc setDesc) (*Manager, error) { raw.Unset(lnwire.SimpleTaprootChannelsOptionalStaging) raw.Unset(lnwire.SimpleTaprootChannelsRequiredStaging) } - + if cfg.NoRouteBlinding { + raw.Unset(lnwire.RouteBlindingOptional) + raw.Unset(lnwire.RouteBlindingRequired) + } for _, custom := range cfg.CustomFeatures[set] { if custom > set.Maximum() { return nil, fmt.Errorf("feature bit: %v "+ diff --git a/lnrpc/lightning.pb.go b/lnrpc/lightning.pb.go index b2bc8034c..161fd2f11 100644 --- a/lnrpc/lightning.pb.go +++ b/lnrpc/lightning.pb.go @@ -651,6 +651,8 @@ const ( FeatureBit_ANCHORS_OPT FeatureBit = 21 FeatureBit_ANCHORS_ZERO_FEE_HTLC_REQ FeatureBit = 22 FeatureBit_ANCHORS_ZERO_FEE_HTLC_OPT FeatureBit = 23 + FeatureBit_ROUTE_BLINDING_REQUIRED FeatureBit = 24 + FeatureBit_ROUTE_BLINDING_OPTIONAL FeatureBit = 25 FeatureBit_AMP_REQ FeatureBit = 30 FeatureBit_AMP_OPT FeatureBit = 31 ) @@ -681,6 +683,8 @@ var ( 21: "ANCHORS_OPT", 22: "ANCHORS_ZERO_FEE_HTLC_REQ", 23: "ANCHORS_ZERO_FEE_HTLC_OPT", + 24: "ROUTE_BLINDING_REQUIRED", + 25: "ROUTE_BLINDING_OPTIONAL", 30: "AMP_REQ", 31: "AMP_OPT", } @@ -708,6 +712,8 @@ var ( "ANCHORS_OPT": 21, "ANCHORS_ZERO_FEE_HTLC_REQ": 22, "ANCHORS_ZERO_FEE_HTLC_OPT": 23, + "ROUTE_BLINDING_REQUIRED": 24, + "ROUTE_BLINDING_OPTIONAL": 25, "AMP_REQ": 30, "AMP_OPT": 31, } @@ -20669,7 +20675,7 @@ var file_lightning_proto_rawDesc = []byte{ 0x41, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x44, 0x45, 0x54, 0x41, 0x49, 0x4c, 0x53, 0x10, 0x04, 0x12, 0x27, 0x0a, 0x23, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x49, 0x4e, 0x53, 0x55, 0x46, 0x46, 0x49, 0x43, 0x49, 0x45, 0x4e, 0x54, 0x5f, - 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x05, 0x2a, 0xcf, 0x04, 0x0a, 0x0a, 0x46, 0x65, + 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x05, 0x2a, 0x89, 0x05, 0x0a, 0x0a, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x42, 0x69, 0x74, 0x12, 0x18, 0x0a, 0x14, 0x44, 0x41, 0x54, 0x41, 0x4c, 0x4f, 0x53, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x45, 0x43, 0x54, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x44, 0x41, 0x54, 0x41, 0x4c, 0x4f, 0x53, 0x53, 0x5f, 0x50, @@ -20705,338 +20711,342 @@ var file_lightning_proto_rawDesc = []byte{ 0x45, 0x52, 0x4f, 0x5f, 0x46, 0x45, 0x45, 0x5f, 0x48, 0x54, 0x4c, 0x43, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x16, 0x12, 0x1d, 0x0a, 0x19, 0x41, 0x4e, 0x43, 0x48, 0x4f, 0x52, 0x53, 0x5f, 0x5a, 0x45, 0x52, 0x4f, 0x5f, 0x46, 0x45, 0x45, 0x5f, 0x48, 0x54, 0x4c, 0x43, 0x5f, 0x4f, 0x50, 0x54, 0x10, - 0x17, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x4d, 0x50, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x1e, 0x12, 0x0b, - 0x0a, 0x07, 0x41, 0x4d, 0x50, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x1f, 0x2a, 0xac, 0x01, 0x0a, 0x0d, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x12, 0x1a, 0x0a, - 0x16, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, - 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x55, 0x50, 0x44, - 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x50, 0x45, 0x4e, 0x44, - 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, - 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, - 0x44, 0x10, 0x02, 0x12, 0x1f, 0x0a, 0x1b, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, - 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x45, - 0x52, 0x52, 0x10, 0x03, 0x12, 0x24, 0x0a, 0x20, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, - 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x50, - 0x41, 0x52, 0x41, 0x4d, 0x45, 0x54, 0x45, 0x52, 0x10, 0x04, 0x32, 0xb9, 0x27, 0x0a, 0x09, 0x4c, - 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x4a, 0x0a, 0x0d, 0x57, 0x61, 0x6c, 0x6c, - 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x57, - 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, - 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, - 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, - 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, - 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, - 0x12, 0x44, 0x0a, 0x0b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x12, - 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, - 0x46, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x09, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x6f, - 0x69, 0x6e, 0x73, 0x12, 0x17, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, - 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, - 0x73, 0x70, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, 0x73, - 0x70, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x15, - 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, - 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x30, 0x01, 0x12, 0x3b, 0x0a, 0x08, 0x53, 0x65, - 0x6e, 0x64, 0x4d, 0x61, 0x6e, 0x79, 0x12, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, - 0x65, 0x6e, 0x64, 0x4d, 0x61, 0x6e, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x61, 0x6e, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0a, 0x4e, 0x65, 0x77, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, - 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x53, 0x69, - 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, - 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x4a, 0x0a, 0x0d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x12, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, - 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x12, 0x19, 0x2e, 0x6c, 0x6e, - 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x50, 0x65, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x69, 0x73, - 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x3e, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x12, 0x17, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x47, 0x0a, 0x13, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x50, 0x65, - 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x50, 0x65, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x10, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, - 0x65, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x38, 0x0a, 0x07, 0x47, 0x65, - 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x15, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, - 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x6c, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x44, 0x65, 0x62, 0x75, 0x67, - 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, - 0x44, 0x65, 0x62, 0x75, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x62, 0x75, - 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, - 0x0f, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, - 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x76, - 0x65, 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x50, 0x0a, 0x0f, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, - 0x6c, 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, - 0x6e, 0x67, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x47, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, - 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, - 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, - 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x16, 0x53, 0x75, - 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, - 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, - 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x30, 0x01, 0x12, 0x4d, 0x0a, 0x0e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x43, 0x68, 0x61, 0x6e, - 0x6e, 0x65, 0x6c, 0x73, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, - 0x73, 0x65, 0x64, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, - 0x64, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x41, 0x0a, 0x0f, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, - 0x53, 0x79, 0x6e, 0x63, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x70, 0x65, - 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, - 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x43, 0x0a, 0x0b, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, - 0x6e, 0x65, 0x6c, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x70, 0x65, 0x6e, - 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x30, 0x01, 0x12, 0x53, 0x0a, 0x10, 0x42, 0x61, 0x74, - 0x63, 0x68, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1e, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x6e, 0x43, - 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x6e, 0x43, - 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, - 0x0a, 0x10, 0x46, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x74, - 0x65, 0x70, 0x12, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x75, 0x6e, 0x64, 0x69, - 0x6e, 0x67, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x67, 0x1a, - 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x53, 0x74, 0x65, 0x70, 0x52, 0x65, 0x73, 0x70, 0x12, 0x50, 0x0a, 0x0f, - 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x12, - 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x41, - 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x1b, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x41, 0x63, 0x63, - 0x65, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x46, - 0x0a, 0x0c, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1a, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x43, 0x68, 0x61, 0x6e, - 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x30, 0x01, 0x12, 0x4d, 0x0a, 0x0e, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, - 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x41, - 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x61, 0x79, - 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, - 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x88, - 0x02, 0x01, 0x28, 0x01, 0x30, 0x01, 0x12, 0x3a, 0x0a, 0x0f, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x61, - 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, - 0x65, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, - 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x03, 0x88, 0x02, 0x01, 0x28, 0x01, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0f, 0x53, 0x65, - 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x19, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, - 0x0a, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x0e, 0x2e, 0x6c, 0x6e, - 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, - 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, - 0x76, 0x6f, 0x69, 0x63, 0x65, 0x73, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, - 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, - 0x0d, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x12, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x61, - 0x73, 0x68, 0x1a, 0x0e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x69, - 0x63, 0x65, 0x12, 0x41, 0x0a, 0x11, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x49, - 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x1a, 0x0e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, - 0x69, 0x63, 0x65, 0x30, 0x01, 0x12, 0x32, 0x0a, 0x0c, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x50, - 0x61, 0x79, 0x52, 0x65, 0x71, 0x12, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, - 0x79, 0x52, 0x65, 0x71, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x1a, 0x0d, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x50, 0x61, 0x79, 0x52, 0x65, 0x71, 0x12, 0x47, 0x0a, 0x0c, 0x4c, 0x69, 0x73, - 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, - 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, - 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, - 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x12, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x0d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, - 0x62, 0x65, 0x47, 0x72, 0x61, 0x70, 0x68, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x47, 0x72, 0x61, 0x70, 0x68, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, - 0x6e, 0x65, 0x6c, 0x47, 0x72, 0x61, 0x70, 0x68, 0x12, 0x47, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4e, - 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, - 0x64, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x39, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x49, 0x6e, 0x66, 0x6f, - 0x12, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x49, 0x6e, 0x66, - 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x64, 0x67, 0x65, 0x12, 0x36, 0x0a, 0x0b, - 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x6c, 0x6e, - 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, - 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x44, 0x0a, 0x0b, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x6f, 0x75, - 0x74, 0x65, 0x73, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x6f, 0x75, 0x74, - 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x0e, 0x47, 0x65, - 0x74, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x2e, 0x6c, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x35, 0x0a, 0x0a, 0x53, - 0x74, 0x6f, 0x70, 0x44, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x12, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x57, 0x0a, 0x15, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43, - 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x47, 0x72, 0x61, 0x70, 0x68, 0x12, 0x20, 0x2e, 0x6c, 0x6e, - 0x72, 0x70, 0x63, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, - 0x79, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x1a, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x54, 0x6f, 0x70, 0x6f, 0x6c, - 0x6f, 0x67, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0a, 0x44, - 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x62, 0x75, - 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, - 0x0a, 0x09, 0x46, 0x65, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x17, 0x2e, 0x6c, 0x6e, - 0x72, 0x70, 0x63, 0x2e, 0x46, 0x65, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x65, 0x65, - 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, - 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, - 0x0a, 0x11, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, - 0x6f, 0x72, 0x79, 0x12, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, 0x77, - 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, - 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x13, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, - 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x21, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x68, 0x61, 0x6e, - 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x14, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, - 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x54, 0x0a, 0x17, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, - 0x41, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, - 0x73, 0x12, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, - 0x63, 0x6b, 0x75, 0x70, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, - 0x63, 0x6b, 0x75, 0x70, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x4e, 0x0a, 0x10, - 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, - 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, - 0x6b, 0x75, 0x70, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x1a, 0x1f, 0x2e, 0x6c, 0x6e, - 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, - 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x15, - 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, - 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, - 0x73, 0x74, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, - 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x17, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, + 0x17, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x42, 0x4c, 0x49, 0x4e, 0x44, + 0x49, 0x4e, 0x47, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, 0x44, 0x10, 0x18, 0x12, 0x1b, + 0x0a, 0x17, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x42, 0x4c, 0x49, 0x4e, 0x44, 0x49, 0x4e, 0x47, + 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x10, 0x19, 0x12, 0x0b, 0x0a, 0x07, 0x41, + 0x4d, 0x50, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x1e, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x4d, 0x50, 0x5f, + 0x4f, 0x50, 0x54, 0x10, 0x1f, 0x2a, 0xac, 0x01, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x55, 0x50, 0x44, 0x41, 0x54, + 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, + 0x4e, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, + 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, + 0x1c, 0x0a, 0x18, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, + 0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x02, 0x12, 0x1f, 0x0a, + 0x1b, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, + 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x45, 0x52, 0x52, 0x10, 0x03, 0x12, 0x24, + 0x0a, 0x20, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, + 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x50, 0x41, 0x52, 0x41, 0x4d, 0x45, 0x54, + 0x45, 0x52, 0x10, 0x04, 0x32, 0xb9, 0x27, 0x0a, 0x09, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, + 0x6e, 0x67, 0x12, 0x4a, 0x0a, 0x0d, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, + 0x6e, 0x63, 0x65, 0x12, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x42, + 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, + 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, + 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, + 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, + 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, + 0x0f, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x44, 0x0a, 0x0b, 0x45, 0x73, + 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, + 0x63, 0x2e, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x73, 0x74, + 0x69, 0x6d, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x3e, 0x0a, 0x09, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x12, 0x17, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, + 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x44, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x12, + 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, 0x73, 0x70, + 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x15, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, + 0x69, 0x62, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x30, 0x01, 0x12, 0x3b, 0x0a, 0x08, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x61, 0x6e, 0x79, + 0x12, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x61, 0x6e, + 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, + 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x61, 0x6e, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x41, 0x0a, 0x0a, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, + 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, + 0x63, 0x2e, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x0d, 0x56, 0x65, + 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, + 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x50, 0x65, 0x65, 0x72, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0e, + 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x12, 0x1c, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6c, + 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, + 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x09, 0x4c, + 0x69, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x12, 0x17, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, + 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x13, 0x53, + 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x50, 0x65, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x73, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x1a, 0x10, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x30, 0x01, 0x12, 0x38, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, + 0x15, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, + 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, + 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x44, 0x65, 0x62, 0x75, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1a, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x62, 0x75, 0x67, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x62, 0x75, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x52, 0x65, + 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x49, 0x6e, + 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, + 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x66, + 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0f, 0x50, 0x65, 0x6e, + 0x64, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x12, 0x1d, 0x2e, 0x6c, + 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x61, 0x6e, + 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x61, 0x6e, 0x6e, + 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0c, 0x4c, + 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, + 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1f, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, + 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x30, 0x01, 0x12, 0x4d, 0x0a, 0x0e, + 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x12, 0x1c, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x43, 0x68, 0x61, + 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6c, + 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x43, 0x68, 0x61, 0x6e, 0x6e, + 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0f, 0x4f, + 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x19, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, + 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, + 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x43, + 0x0a, 0x0b, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x19, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, + 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, + 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x30, 0x01, 0x12, 0x53, 0x0a, 0x10, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x6e, + 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x10, 0x46, 0x75, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x74, 0x65, 0x70, 0x12, 0x1b, 0x2e, 0x6c, + 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x67, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, + 0x63, 0x2e, 0x46, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x74, + 0x65, 0x70, 0x52, 0x65, 0x73, 0x70, 0x12, 0x50, 0x0a, 0x0f, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, + 0x6c, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, + 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x46, 0x0a, 0x0c, 0x43, 0x6c, 0x6f, 0x73, + 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, + 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, + 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x30, 0x01, + 0x12, 0x4d, 0x0a, 0x0e, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, + 0x65, 0x6c, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x62, 0x61, 0x6e, 0x64, + 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, + 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x3f, 0x0a, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x12, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x88, 0x02, 0x01, 0x28, 0x01, 0x30, 0x01, + 0x12, 0x3a, 0x0a, 0x0f, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x53, + 0x79, 0x6e, 0x63, 0x12, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0b, + 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x19, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, + 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x88, 0x02, 0x01, + 0x28, 0x01, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0f, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x41, 0x64, 0x64, 0x49, 0x6e, + 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x0e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, + 0x76, 0x6f, 0x69, 0x63, 0x65, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, + 0x64, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x45, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x73, + 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, + 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x0d, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, + 0x70, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, + 0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x0e, 0x2e, 0x6c, + 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x41, 0x0a, 0x11, + 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, + 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, + 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x0e, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x30, 0x01, 0x12, + 0x32, 0x0a, 0x0c, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x50, 0x61, 0x79, 0x52, 0x65, 0x71, 0x12, + 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, 0x79, 0x52, 0x65, 0x71, 0x53, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x1a, 0x0d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, 0x79, + 0x52, 0x65, 0x71, 0x12, 0x47, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x79, 0x6d, + 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x0d, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, + 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1f, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x50, + 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, + 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x40, 0x0a, 0x0d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x47, 0x72, 0x61, 0x70, + 0x68, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, + 0x6c, 0x47, 0x72, 0x61, 0x70, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x47, 0x72, 0x61, + 0x70, 0x68, 0x12, 0x47, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, + 0x72, 0x69, 0x63, 0x73, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, + 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, 0x72, + 0x69, 0x63, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x0b, 0x47, + 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x6c, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, + 0x65, 0x6c, 0x45, 0x64, 0x67, 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, + 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, + 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x44, + 0x0a, 0x0b, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x19, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, + 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x77, 0x6f, + 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, + 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, + 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x35, 0x0a, 0x0a, 0x53, 0x74, 0x6f, 0x70, 0x44, 0x61, 0x65, + 0x6d, 0x6f, 0x6e, 0x12, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x6f, 0x70, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x15, + 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, + 0x47, 0x72, 0x61, 0x70, 0x68, 0x12, 0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x72, + 0x61, 0x70, 0x68, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x53, 0x75, 0x62, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x47, 0x72, 0x61, 0x70, 0x68, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0a, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, + 0x76, 0x65, 0x6c, 0x12, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x62, 0x75, + 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x09, 0x46, 0x65, 0x65, 0x52, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x17, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x65, + 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x65, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, + 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x11, 0x46, 0x6f, 0x72, 0x77, + 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1f, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, + 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, + 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x4e, 0x0a, 0x13, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, + 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x21, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, + 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x6c, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, + 0x12, 0x54, 0x0a, 0x17, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x41, 0x6c, 0x6c, 0x43, 0x68, 0x61, + 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12, 0x1e, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x45, 0x78, + 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, 0x6e, + 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x4e, 0x0a, 0x10, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, + 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, 0x6e, 0x61, + 0x70, 0x73, 0x68, 0x6f, 0x74, 0x1a, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, + 0x72, 0x69, 0x66, 0x79, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12, - 0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, - 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, - 0x63, 0x6b, 0x75, 0x70, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x30, 0x01, 0x12, 0x47, - 0x0a, 0x0c, 0x42, 0x61, 0x6b, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x12, 0x1a, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x6b, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, - 0x6f, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x42, 0x61, 0x6b, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x4d, - 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, - 0x44, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x10, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x12, 0x1e, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x61, - 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x61, - 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, - 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, - 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, - 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x53, 0x0a, 0x18, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, - 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1a, 0x2e, 0x6c, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x50, 0x65, 0x72, - 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x15, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, - 0x72, 0x52, 0x50, 0x43, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x12, 0x1c, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x50, 0x43, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, - 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x1b, 0x2e, 0x6c, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x50, 0x43, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, - 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x56, 0x0a, - 0x11, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x12, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x43, - 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, - 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x17, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, - 0x62, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, - 0x12, 0x25, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, - 0x62, 0x65, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x30, 0x01, 0x12, - 0x44, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x12, 0x19, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x14, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x48, - 0x74, 0x6c, 0x63, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x48, 0x74, 0x6c, 0x63, - 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x23, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, - 0x48, 0x74, 0x6c, 0x63, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x6e, 0x65, - 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, 0x6c, 0x6e, 0x64, 0x2f, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x43, + 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, + 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, + 0x0a, 0x17, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, + 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12, 0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70, + 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, + 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, 0x6e, + 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x30, 0x01, 0x12, 0x47, 0x0a, 0x0c, 0x42, 0x61, 0x6b, 0x65, + 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, + 0x2e, 0x42, 0x61, 0x6b, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x6b, + 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x50, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, + 0x6e, 0x49, 0x44, 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, + 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x12, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, + 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x18, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x4d, 0x61, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x56, 0x0a, 0x15, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x50, 0x43, 0x4d, 0x69, + 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, + 0x2e, 0x52, 0x50, 0x43, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, + 0x50, 0x43, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x56, 0x0a, 0x11, 0x53, 0x65, 0x6e, 0x64, 0x43, + 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1f, 0x2e, 0x6c, + 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x58, 0x0a, 0x17, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43, 0x75, 0x73, 0x74, + 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x25, 0x2e, 0x6c, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43, 0x75, 0x73, 0x74, + 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x14, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x30, 0x01, 0x12, 0x44, 0x0a, 0x0b, 0x4c, 0x69, 0x73, + 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x5f, 0x0a, 0x14, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x48, 0x74, 0x6c, 0x63, 0x52, 0x65, 0x73, + 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x48, 0x74, 0x6c, 0x63, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x48, 0x74, 0x6c, 0x63, 0x52, 0x65, + 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, + 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, + 0x6c, 0x6e, 0x64, 0x2f, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( diff --git a/lnrpc/lightning.proto b/lnrpc/lightning.proto index 162dc35f9..2ad22e089 100644 --- a/lnrpc/lightning.proto +++ b/lnrpc/lightning.proto @@ -4311,6 +4311,8 @@ enum FeatureBit { ANCHORS_OPT = 21; ANCHORS_ZERO_FEE_HTLC_REQ = 22; ANCHORS_ZERO_FEE_HTLC_OPT = 23; + ROUTE_BLINDING_REQUIRED = 24; + ROUTE_BLINDING_OPTIONAL = 25; AMP_REQ = 30; AMP_OPT = 31; } diff --git a/lnrpc/lightning.swagger.json b/lnrpc/lightning.swagger.json index c0ea92d82..3a7132fc0 100644 --- a/lnrpc/lightning.swagger.json +++ b/lnrpc/lightning.swagger.json @@ -1470,6 +1470,8 @@ "ANCHORS_OPT", "ANCHORS_ZERO_FEE_HTLC_REQ", "ANCHORS_ZERO_FEE_HTLC_OPT", + "ROUTE_BLINDING_REQUIRED", + "ROUTE_BLINDING_OPTIONAL", "AMP_REQ", "AMP_OPT" ] @@ -4694,6 +4696,8 @@ "ANCHORS_OPT", "ANCHORS_ZERO_FEE_HTLC_REQ", "ANCHORS_ZERO_FEE_HTLC_OPT", + "ROUTE_BLINDING_REQUIRED", + "ROUTE_BLINDING_OPTIONAL", "AMP_REQ", "AMP_OPT" ], diff --git a/lnrpc/peersrpc/peers.swagger.json b/lnrpc/peersrpc/peers.swagger.json index c7b9970cf..b667994a4 100644 --- a/lnrpc/peersrpc/peers.swagger.json +++ b/lnrpc/peersrpc/peers.swagger.json @@ -77,6 +77,8 @@ "ANCHORS_OPT", "ANCHORS_ZERO_FEE_HTLC_REQ", "ANCHORS_ZERO_FEE_HTLC_OPT", + "ROUTE_BLINDING_REQUIRED", + "ROUTE_BLINDING_OPTIONAL", "AMP_REQ", "AMP_OPT" ], diff --git a/lnrpc/routerrpc/router.swagger.json b/lnrpc/routerrpc/router.swagger.json index 8e1c646c1..1d948d3f8 100644 --- a/lnrpc/routerrpc/router.swagger.json +++ b/lnrpc/routerrpc/router.swagger.json @@ -772,6 +772,8 @@ "ANCHORS_OPT", "ANCHORS_ZERO_FEE_HTLC_REQ", "ANCHORS_ZERO_FEE_HTLC_OPT", + "ROUTE_BLINDING_REQUIRED", + "ROUTE_BLINDING_OPTIONAL", "AMP_REQ", "AMP_OPT" ], diff --git a/lnwire/features.go b/lnwire/features.go index ab6facc75..e4dd7f4f8 100644 --- a/lnwire/features.go +++ b/lnwire/features.go @@ -141,6 +141,14 @@ const ( // transactions, which also imply anchor commitments. AnchorsZeroFeeHtlcTxOptional FeatureBit = 23 + // RouteBlindingRequired is a required feature bit that signals that + // the node supports blinded payments. + RouteBlindingRequired FeatureBit = 24 + + // RouteBlindingOptional is an optional feature bit that signals that + // the node supports blinded payments. + RouteBlindingOptional FeatureBit = 25 + // ShutdownAnySegwitRequired is an required feature bit that signals // that the sender is able to properly handle/parse segwit witness // programs up to version 16. This enables utilization of Taproot @@ -315,6 +323,8 @@ var Features = map[FeatureBit]string{ ScidAliasOptional: "scid-alias", ZeroConfRequired: "zero-conf", ZeroConfOptional: "zero-conf", + RouteBlindingRequired: "route-blinding", + RouteBlindingOptional: "route-blinding", ShutdownAnySegwitRequired: "shutdown-any-segwit", ShutdownAnySegwitOptional: "shutdown-any-segwit", SimpleTaprootChannelsRequiredFinal: "simple-taproot-chans", diff --git a/server.go b/server.go index 2979880a2..43390ca57 100644 --- a/server.go +++ b/server.go @@ -549,6 +549,7 @@ func newServer(cfg *Config, listenAddrs []net.Addr, NoAnySegwit: cfg.ProtocolOptions.NoAnySegwit(), CustomFeatures: cfg.ProtocolOptions.ExperimentalProtocol.CustomFeatures(), NoTaprootChans: !cfg.ProtocolOptions.TaprootChans, + NoRouteBlinding: cfg.ProtocolOptions.NoRouteBlinding(), }) if err != nil { return nil, err From 7867cb3a70bd44c651c594ed51142fff40981762 Mon Sep 17 00:00:00 2001 From: Carla Kirk-Cohen Date: Fri, 22 Mar 2024 13:47:00 -0400 Subject: [PATCH 052/109] multi: turn on route blinding by default --- config.go | 5 ++--- lncfg/protocol.go | 8 -------- lncfg/protocol_integration.go | 7 ------- 3 files changed, 2 insertions(+), 18 deletions(-) diff --git a/config.go b/config.go index 7084500b4..6c8df62dd 100644 --- a/config.go +++ b/config.go @@ -627,9 +627,8 @@ func DefaultConfig() Config { RejectCacheSize: channeldb.DefaultRejectCacheSize, ChannelCacheSize: channeldb.DefaultChannelCacheSize, }, - Prometheus: lncfg.DefaultPrometheus(), - Watchtower: lncfg.DefaultWatchtowerCfg(defaultTowerDir), - ProtocolOptions: lncfg.DefaultProtocol(), + Prometheus: lncfg.DefaultPrometheus(), + Watchtower: lncfg.DefaultWatchtowerCfg(defaultTowerDir), HealthChecks: &lncfg.HealthCheckConfig{ ChainCheck: &lncfg.CheckConfig{ Interval: defaultChainInterval, diff --git a/lncfg/protocol.go b/lncfg/protocol.go index 59027a09b..e98b4dcf8 100644 --- a/lncfg/protocol.go +++ b/lncfg/protocol.go @@ -59,14 +59,6 @@ type ProtocolOptions struct { NoRouteBlindingOption bool `long:"no-route-blinding" description:"do not forward payments that are a part of a blinded route"` } -// DefaultProtocol returns a protocol config with route blinding turned off, -// temporarily in place until full handling of blinded route errors is merged. -func DefaultProtocol() *ProtocolOptions { - return &ProtocolOptions{ - NoRouteBlindingOption: true, - } -} - // Wumbo returns true if lnd should permit the creation and acceptance of wumbo // channels. func (l *ProtocolOptions) Wumbo() bool { diff --git a/lncfg/protocol_integration.go b/lncfg/protocol_integration.go index f44aa1246..841f8e9eb 100644 --- a/lncfg/protocol_integration.go +++ b/lncfg/protocol_integration.go @@ -62,13 +62,6 @@ type ProtocolOptions struct { NoRouteBlindingOption bool `long:"no-route-blinding" description:"do not forward payments that are a part of a blinded route"` } -// DefaultProtocol returns a protocol config with route blinding turned on, -// so that itests can run against route blinding features even while we've -// got it turned off for the daemon (pending completion of error handling). -func DefaultProtocol() *ProtocolOptions { - return &ProtocolOptions{} -} - // Wumbo returns true if lnd should permit the creation and acceptance of wumbo // channels. func (l *ProtocolOptions) Wumbo() bool { From 6572f5cb74a589bc73eb64a7a71c91ddaae2ebf8 Mon Sep 17 00:00:00 2001 From: Carla Kirk-Cohen Date: Tue, 20 Feb 2024 19:43:56 -0500 Subject: [PATCH 053/109] docs: add error handling link --- docs/release-notes/release-notes-0.18.0.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/release-notes/release-notes-0.18.0.md b/docs/release-notes/release-notes-0.18.0.md index ff4a947d8..3135764ff 100644 --- a/docs/release-notes/release-notes-0.18.0.md +++ b/docs/release-notes/release-notes-0.18.0.md @@ -211,8 +211,11 @@ bitcoin peers' feefilter values into account](https://github.com/lightningnetwor * [Preparatory work](https://github.com/lightningnetwork/lnd/pull/8159) for forwarding of blinded routes was added, along with [support](https://github.com/lightningnetwork/lnd/pull/8160) - for forwarding blinded payments. Forwarding of blinded payments is disabled - by default, and the feature is not yet advertised to the network. + for forwarding blinded payments and [error handling](https://github.com/lightningnetwork/lnd/pull/8485). + With this change, LND is now eligible to be selected as part of a blinded + route and can forward payments on behalf of nodes that have support for + receiving to blinded paths. This upgrade provides a meaningful improvement + to the anonymity set and usability of blinded paths in the Lightning Network. * Introduced [fee bumper](https://github.com/lightningnetwork/lnd/pull/8424) to handle bumping the fees of sweeping transactions properly. A From 5f22d97b513bf7871c9f82e0c859ca22d725b56e Mon Sep 17 00:00:00 2001 From: fuyangpengqi <995764973@qq.com> Date: Thu, 18 Apr 2024 20:58:15 +0800 Subject: [PATCH 054/109] chore: fix function names in comment Signed-off-by: fuyangpengqi <995764973@qq.com> --- aezeed/bench_test.go | 2 +- autopilot/agent_test.go | 4 ++-- pilot.go | 2 +- rpcserver.go | 2 +- server.go | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/aezeed/bench_test.go b/aezeed/bench_test.go index c54c17944..3fa0edb21 100644 --- a/aezeed/bench_test.go +++ b/aezeed/bench_test.go @@ -11,7 +11,7 @@ var ( seed *CipherSeed ) -// BenchmarkFrommnemonic benchmarks the process of converting a cipher seed +// BenchmarkTomnemonic benchmarks the process of converting a cipher seed // (given the salt), to an enciphered mnemonic. func BenchmarkTomnemonic(b *testing.B) { scryptN = 32768 diff --git a/autopilot/agent_test.go b/autopilot/agent_test.go index 758401868..39e86906e 100644 --- a/autopilot/agent_test.go +++ b/autopilot/agent_test.go @@ -254,7 +254,7 @@ func respondMoreChans(t *testing.T, testCtx *testContext, resp moreChansResp) { } } -// respondMoreChans consumes the nodeScoresArgs element and responds to the +// respondNodeScores consumes the nodeScoresArgs element and responds to the // agent with the given node scores. func respondNodeScores(t *testing.T, testCtx *testContext, resp map[NodeID]*NodeScore) { @@ -468,7 +468,7 @@ func TestAgentChannelCloseSignal(t *testing.T) { } } -// TestAgentBalanceUpdateIncrease ensures that once the agent receives an +// TestAgentBalanceUpdate ensures that once the agent receives an // outside signal concerning a balance update, then it will re-query the // heuristic to determine its next action. func TestAgentBalanceUpdate(t *testing.T) { diff --git a/pilot.go b/pilot.go index b0bb6d9f8..380dc5f09 100644 --- a/pilot.go +++ b/pilot.go @@ -17,7 +17,7 @@ import ( "github.com/lightningnetwork/lnd/tor" ) -// validateAtplConfig is a helper method that makes sure the passed +// validateAtplCfg is a helper method that makes sure the passed // configuration is sane. Currently it checks that the heuristic configuration // makes sense. In case the config is valid, it will return a list of // WeightedHeuristics that can be combined for use with the autopilot agent. diff --git a/rpcserver.go b/rpcserver.go index 517bca41e..f17d29e1c 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1886,7 +1886,7 @@ func newFundingShimAssembler(chanPointShim *lnrpc.ChanPointShim, initiator bool, ), nil } -// newFundingShimAssembler returns a new fully populated +// newPsbtAssembler returns a new fully populated // chanfunding.PsbtAssembler using a FundingShim obtained from an RPC caller. func newPsbtAssembler(req *lnrpc.OpenChannelRequest, normalizedMinConfs int32, psbtShim *lnrpc.PsbtShim, netParams *chaincfg.Params) ( diff --git a/server.go b/server.go index 2c8b75af1..ed0c990e5 100644 --- a/server.go +++ b/server.go @@ -3469,7 +3469,7 @@ func (s *server) nextPeerBackoff(pubStr string, return s.cfg.MinBackoff } -// shouldDropConnection determines if our local connection to a remote peer +// shouldDropLocalConnection determines if our local connection to a remote peer // should be dropped in the case of concurrent connection establishment. In // order to deterministically decide which connection should be dropped, we'll // utilize the ordering of the local and remote public key. If we didn't use From eb605a02fd14b93a95dd17f118d0a420d95c5e44 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 26 Apr 2024 12:26:15 -0700 Subject: [PATCH 055/109] sqldb+kvdb: update to sqlite v1.29.8 Updates to SQLite 3.45.3: https://www.sqlite.org/releaselog/3_45_3.html. May also address https://github.com/lightningnetwork/lnd/issues/8666. --- kvdb/go.mod | 12 ++++++------ kvdb/go.sum | 40 +++++++++++++++++++++++++--------------- sqldb/go.mod | 12 ++++++------ sqldb/go.sum | 40 +++++++++++++++++++++++++--------------- 4 files changed, 62 insertions(+), 42 deletions(-) diff --git a/kvdb/go.mod b/kvdb/go.mod index c09adfc47..017c4c6f0 100644 --- a/kvdb/go.mod +++ b/kvdb/go.mod @@ -16,7 +16,7 @@ require ( go.etcd.io/etcd/client/v3 v3.5.7 go.etcd.io/etcd/server/v3 v3.5.7 golang.org/x/net v0.22.0 - modernc.org/sqlite v1.29.5 + modernc.org/sqlite v1.29.8 ) require ( @@ -41,7 +41,7 @@ require ( github.com/golang-migrate/migrate/v4 v4.17.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/google/uuid v1.4.0 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect @@ -63,7 +63,7 @@ require ( github.com/lib/pq v1.10.9 // indirect github.com/lightningnetwork/lnd/ticker v1.1.0 // indirect github.com/lightningnetwork/lnd/tor v1.0.0 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/miekg/dns v1.1.43 // indirect github.com/mitchellh/mapstructure v1.4.1 // indirect @@ -107,7 +107,7 @@ require ( golang.org/x/crypto v0.21.0 // indirect golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect golang.org/x/mod v0.16.0 // indirect - golang.org/x/sys v0.18.0 // indirect + golang.org/x/sys v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.19.0 // indirect @@ -120,9 +120,9 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect - modernc.org/libc v1.41.0 // indirect + modernc.org/libc v1.49.3 // indirect modernc.org/mathutil v1.6.0 // indirect - modernc.org/memory v1.7.2 // indirect + modernc.org/memory v1.8.0 // indirect modernc.org/strutil v1.2.0 // indirect modernc.org/token v1.1.0 // indirect sigs.k8s.io/yaml v1.2.0 // indirect diff --git a/kvdb/go.sum b/kvdb/go.sum index a41bc8234..9ecf1542a 100644 --- a/kvdb/go.sum +++ b/kvdb/go.sum @@ -180,14 +180,14 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= -github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= +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.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.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/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= @@ -305,8 +305,8 @@ github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= -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.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= @@ -604,10 +604,10 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -717,18 +717,28 @@ gotest.tools/v3 v3.3.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +modernc.org/cc/v4 v4.20.0 h1:45Or8mQfbUqJOG9WaxvlFYOAQO0lQ5RvqBcFCXngjxk= +modernc.org/cc/v4 v4.20.0/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= +modernc.org/ccgo/v4 v4.16.0 h1:ofwORa6vx2FMm0916/CkZjpFPSR70VwTjUCe2Eg5BnA= +modernc.org/ccgo/v4 v4.16.0/go.mod h1:dkNyWIjFrVIZ68DTo36vHK+6/ShBn4ysU61So6PIqCI= 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/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= -modernc.org/libc v1.41.0 h1:g9YAc6BkKlgORsUWj+JwqoB1wU3o4DE3bM3yvA3k+Gk= -modernc.org/libc v1.41.0/go.mod h1:w0eszPsiXoOnoMJgrXjglgLuDy/bt5RR4y3QzUUeodY= +modernc.org/libc v1.49.3 h1:j2MRCRdwJI2ls/sGbeSk0t2bypOG/uvPZUsGQFDulqg= +modernc.org/libc v1.49.3/go.mod h1:yMZuGkn7pXbKfoT/M35gFJOAEdSKdxL0q64sF7KqCDo= 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.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E= -modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E= -modernc.org/sqlite v1.29.5 h1:8l/SQKAjDtZFo9lkJLdk8g9JEOeYRG4/ghStDCCTiTE= -modernc.org/sqlite v1.29.5/go.mod h1:S02dvcmm7TnTRvGhv8IGYyLnIt7AS2KPaB1F/71p75U= +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.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.29.8 h1:nGKglNx9K5v0As+zF0/Gcl1kMkmaU1XynYyq92PbsC8= +modernc.org/sqlite v1.29.8/go.mod h1:lQPm27iqa4UNZpmr4Aor0MH0HkCLbt1huYDfWylLZFk= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= diff --git a/sqldb/go.mod b/sqldb/go.mod index 7c9404723..fcf6c3ee9 100644 --- a/sqldb/go.mod +++ b/sqldb/go.mod @@ -11,7 +11,7 @@ require ( github.com/ory/dockertest/v3 v3.10.0 github.com/stretchr/testify v1.9.0 golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 - modernc.org/sqlite v1.29.5 + modernc.org/sqlite v1.29.8 ) require ( @@ -28,7 +28,7 @@ require ( github.com/dustin/go-humanize v1.0.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/google/uuid v1.4.0 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect @@ -38,7 +38,7 @@ require ( github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgproto3/v2 v2.3.3 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect - github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/mitchellh/mapstructure v1.4.1 // indirect github.com/moby/term v0.5.0 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect @@ -55,15 +55,15 @@ require ( go.uber.org/atomic v1.7.0 // indirect golang.org/x/crypto v0.20.0 // indirect golang.org/x/mod v0.16.0 // indirect - golang.org/x/sys v0.18.0 // indirect + golang.org/x/sys v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.19.0 // indirect gopkg.in/yaml.v2 v2.3.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect - modernc.org/libc v1.41.0 // indirect + modernc.org/libc v1.49.3 // indirect modernc.org/mathutil v1.6.0 // indirect - modernc.org/memory v1.7.2 // indirect + modernc.org/memory v1.8.0 // indirect modernc.org/strutil v1.2.0 // indirect modernc.org/token v1.1.0 // indirect ) diff --git a/sqldb/go.sum b/sqldb/go.sum index 080895df5..2d92b7667 100644 --- a/sqldb/go.sum +++ b/sqldb/go.sum @@ -51,12 +51,12 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= -github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= +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/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.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.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/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -90,8 +90,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-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.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= @@ -183,9 +183,9 @@ golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/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-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -213,18 +213,28 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.3.0 h1:MfDY1b1/0xN1CyMlQDac0ziEy9zJQd9CXBRRDHw2jJo= gotest.tools/v3 v3.3.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A= +modernc.org/cc/v4 v4.20.0 h1:45Or8mQfbUqJOG9WaxvlFYOAQO0lQ5RvqBcFCXngjxk= +modernc.org/cc/v4 v4.20.0/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= +modernc.org/ccgo/v4 v4.16.0 h1:ofwORa6vx2FMm0916/CkZjpFPSR70VwTjUCe2Eg5BnA= +modernc.org/ccgo/v4 v4.16.0/go.mod h1:dkNyWIjFrVIZ68DTo36vHK+6/ShBn4ysU61So6PIqCI= 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/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= -modernc.org/libc v1.41.0 h1:g9YAc6BkKlgORsUWj+JwqoB1wU3o4DE3bM3yvA3k+Gk= -modernc.org/libc v1.41.0/go.mod h1:w0eszPsiXoOnoMJgrXjglgLuDy/bt5RR4y3QzUUeodY= +modernc.org/libc v1.49.3 h1:j2MRCRdwJI2ls/sGbeSk0t2bypOG/uvPZUsGQFDulqg= +modernc.org/libc v1.49.3/go.mod h1:yMZuGkn7pXbKfoT/M35gFJOAEdSKdxL0q64sF7KqCDo= 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.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E= -modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E= -modernc.org/sqlite v1.29.5 h1:8l/SQKAjDtZFo9lkJLdk8g9JEOeYRG4/ghStDCCTiTE= -modernc.org/sqlite v1.29.5/go.mod h1:S02dvcmm7TnTRvGhv8IGYyLnIt7AS2KPaB1F/71p75U= +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.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.29.8 h1:nGKglNx9K5v0As+zF0/Gcl1kMkmaU1XynYyq92PbsC8= +modernc.org/sqlite v1.29.8/go.mod h1:lQPm27iqa4UNZpmr4Aor0MH0HkCLbt1huYDfWylLZFk= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= From fe8784aa0cd66183214cc1cca5a4017aa8b376ad Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 25 Apr 2024 16:30:47 -0700 Subject: [PATCH 056/109] channeldb: fix race in TestPackager by removing global test var In this commit, we fix a race in the `TestPackager` series on channeldb. A few tests were sharing the same global variable of the set of log updates, which includes a pointer to an HTLC. The `ExtraData` value of the HTLC would then be mutated once we go to encode the message on disk. To fix this, we the global with a function that returns a new instance of all the test data. ``` ================== WARNING: DATA RACE Write at 0x0000021b0a48 by goroutine 2896: github.com/lightningnetwork/lnd/lnwire.(*ExtraOpaqueData).PackRecords() /home/runner/work/lnd/lnd/lnwire/extra_bytes.go:74 +0x546 github.com/lightningnetwork/lnd/lnwire.EncodeMessageExtraData() /home/runner/work/lnd/lnd/lnwire/extra_bytes.go:121 +0x4d github.com/lightningnetwork/lnd/lnwire.(*UpdateAddHTLC).Encode() /home/runner/work/lnd/lnd/lnwire/update_add_htlc.go:164 +0x5af github.com/lightningnetwork/lnd/lnwire.WriteMessage() /home/runner/work/lnd/lnd/lnwire/message.go:330 +0x351 github.com/lightningnetwork/lnd/channeldb.WriteElement() /home/runner/work/lnd/lnd/channeldb/codec.go:186 +0x1975 github.com/lightningnetwork/lnd/channeldb.WriteElements() /home/runner/work/lnd/lnd/channeldb/codec.go:247 +0x14f github.com/lightningnetwork/lnd/channeldb.serializeLogUpdate() /home/runner/work/lnd/lnd/channeldb/channel.go:2529 +0x3c github.com/lightningnetwork/lnd/channeldb.putLogUpdate() /home/runner/work/lnd/lnd/channeldb/forwarding_package.go:525 +0xae github.com/lightningnetwork/lnd/channeldb.(*ChannelPackager).AddFwdPkg() /home/runner/work/lnd/lnd/channeldb/forwarding_package.go:489 +0x684 github.com/lightningnetwork/lnd/channeldb_test.TestPackagerOnlyAdds.func1() /home/runner/work/lnd/lnd/channeldb/forwarding_package_test.go:283 +0x4c github.com/btcsuite/btcwallet/walletdb/bdb.(*db).Update() /home/runner/go/pkg/mod/github.com/btcsuite/btcwallet/walletdb@v1.4.2/bdb/db.go:429 +0xe5 github.com/lightningnetwork/lnd/kvdb.Update() /home/runner/go/pkg/mod/github.com/lightningnetwork/lnd/kvdb@v1.4.6/interface.go:16 +0x258 github.com/lightningnetwork/lnd/channeldb_test.TestPackagerOnlyAdds() /home/runner/work/lnd/lnd/channeldb/forwarding_package_test.go:282 +0x17b testing.tRunner() /home/runner/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.21.4.linux-amd64/src/testing/testing.go:1595 +0x238 testing.(*T).Run.func1() /home/runner/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.21.4.linux-amd64/src/testing/testing.go:1648 +0x44 Previous write at 0x0000021b0a48 by goroutine 2898: github.com/lightningnetwork/lnd/lnwire.(*ExtraOpaqueData).PackRecords() /home/runner/work/lnd/lnd/lnwire/extra_bytes.go:74 +0x546 github.com/lightningnetwork/lnd/lnwire.EncodeMessageExtraData() /home/runner/work/lnd/lnd/lnwire/extra_bytes.go:121 +0x4d github.com/lightningnetwork/lnd/lnwire.(*UpdateAddHTLC).Encode() /home/runner/work/lnd/lnd/lnwire/update_add_htlc.go:164 +0x5af github.com/lightningnetwork/lnd/lnwire.WriteMessage() /home/runner/work/lnd/lnd/lnwire/message.go:330 +0x351 github.com/lightningnetwork/lnd/channeldb.WriteElement() /home/runner/work/lnd/lnd/channeldb/codec.go:186 +0x1975 github.com/lightningnetwork/lnd/channeldb.WriteElements() /home/runner/work/lnd/lnd/channeldb/codec.go:247 +0x14f github.com/lightningnetwork/lnd/channeldb.serializeLogUpdate() /home/runner/work/lnd/lnd/channeldb/channel.go:2529 +0x3c github.com/lightningnetwork/lnd/channeldb.putLogUpdate() /home/runner/work/lnd/lnd/channeldb/forwarding_package.go:525 +0xae github.com/lightningnetwork/lnd/channeldb.(*ChannelPackager).AddFwdPkg() /home/runner/work/lnd/lnd/channeldb/forwarding_package.go:489 +0x684 github.com/lightningnetwork/lnd/channeldb_test.TestPackagerAddsThenSettleFails.func1() /home/runner/work/lnd/lnd/channeldb/forwarding_package_test.go:490 +0x4c github.com/btcsuite/btcwallet/walletdb/bdb.(*db).Update() /home/runner/go/pkg/mod/github.com/btcsuite/btcwallet/walletdb@v1.4.2/bdb/db.go:429 +0xe5 github.com/lightningnetwork/lnd/kvdb.Update() /home/runner/go/pkg/mod/github.com/lightningnetwork/lnd/kvdb@v1.4.6/interface.go:16 +0x2cd github.com/lightningnetwork/lnd/channeldb_test.TestPackagerAddsThenSettleFails() /home/runner/work/lnd/lnd/channeldb/forwarding_package_test.go:489 +0x1e7 testing.tRunner() /home/runner/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.21.4.linux-amd64/src/testing/testing.go:1595 +0x238 testing.(*T).Run.func1() /home/runner/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.21.4.linux-amd64/src/testing/testing.go:1648 +0x44 Goroutine 2896 (running) created at: testing.(*T).Run() /home/runner/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.21.4.linux-amd64/src/testing/testing.go:1648 +0x82a testing.runTests.func1() /home/runner/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.21.4.linux-amd64/src/testing/testing.go:2054 +0x84 testing.tRunner() /home/runner/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.21.4.linux-amd64/src/testing/testing.go:1595 +0x238 testing.runTests() /home/runner/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.21.4.linux-amd64/src/testing/testing.go:2052 +0x896 testing.(*M).Run() /home/runner/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.21.4.linux-amd64/src/testing/testing.go:1925 +0xb57 github.com/lightningnetwork/lnd/kvdb.RunTests() /home/runner/go/pkg/mod/github.com/lightningnetwork/lnd/kvdb@v1.4.6/test_utils.go:23 +0x26 github.com/lightningnetwork/lnd/channeldb.TestMain() /home/runner/work/lnd/lnd/channeldb/setup_test.go:10 +0x308 main.main() _testmain.go:321 +0x303 Goroutine 2898 (running) created at: testing.(*T).Run() /home/runner/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.21.4.linux-amd64/src/testing/testing.go:1648 +0x82a testing.runTests.func1() /home/runner/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.21.4.linux-amd64/src/testing/testing.go:2054 +0x84 testing.tRunner() /home/runner/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.21.4.linux-amd64/src/testing/testing.go:1595 +0x238 testing.runTests() /home/runner/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.21.4.linux-amd64/src/testing/testing.go:2052 +0x896 testing.(*M).Run() /home/runner/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.21.4.linux-amd64/src/testing/testing.go:1925 +0xb57 github.com/lightningnetwork/lnd/kvdb.RunTests() /home/runner/go/pkg/mod/github.com/lightningnetwork/lnd/kvdb@v1.4.6/test_utils.go:23 +0x26 github.com/lightningnetwork/lnd/channeldb.TestMain() /home/runner/work/lnd/lnd/channeldb/setup_test.go:10 +0x308 main.main() _testmain.go:321 +0x303 ================== ``` --- channeldb/forwarding_package_test.go | 55 +++++++++++++++++----------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/channeldb/forwarding_package_test.go b/channeldb/forwarding_package_test.go index d796c6d51..c113d13d5 100644 --- a/channeldb/forwarding_package_test.go +++ b/channeldb/forwarding_package_test.go @@ -142,8 +142,31 @@ func checkPkgFilterEncodeDecode(t *testing.T, i uint16, f *channeldb.PkgFilter) var ( chanID = lnwire.NewChanIDFromOutPoint(wire.OutPoint{}) +) - adds = []channeldb.LogUpdate{ +func testSettleFails() []channeldb.LogUpdate { + return []channeldb.LogUpdate{ + { + LogIndex: 2, + UpdateMsg: &lnwire.UpdateFulfillHTLC{ + ChanID: chanID, + ID: 0, + PaymentPreimage: [32]byte{0}, + }, + }, + { + LogIndex: 3, + UpdateMsg: &lnwire.UpdateFailHTLC{ + ChanID: chanID, + ID: 1, + Reason: []byte{}, + }, + }, + } +} + +func testAdds() []channeldb.LogUpdate { + return []channeldb.LogUpdate{ { LogIndex: 0, UpdateMsg: &lnwire.UpdateAddHTLC{ @@ -165,26 +188,7 @@ var ( }, }, } - - settleFails = []channeldb.LogUpdate{ - { - LogIndex: 2, - UpdateMsg: &lnwire.UpdateFulfillHTLC{ - ChanID: chanID, - ID: 0, - PaymentPreimage: [32]byte{0}, - }, - }, - { - LogIndex: 3, - UpdateMsg: &lnwire.UpdateFailHTLC{ - ChanID: chanID, - ID: 1, - Reason: []byte{}, - }, - }, - } -) +} // TestPackagerEmptyFwdPkg checks that the state transitions exhibited by a // forwarding package that contains no adds, fails or settles. We expect that @@ -273,6 +277,8 @@ func TestPackagerOnlyAdds(t *testing.T) { t.Fatalf("no forwarding packages should exist, found %d", len(fwdPkgs)) } + adds := testAdds() + // Next, create and write a new forwarding package that only has add // htlcs. fwdPkg := channeldb.NewFwdPkg(shortChanID, 0, adds, nil) @@ -377,6 +383,7 @@ func TestPackagerOnlySettleFails(t *testing.T) { // Next, create and write a new forwarding package that only has add // htlcs. + settleFails := testSettleFails() fwdPkg := channeldb.NewFwdPkg(shortChanID, 0, nil, settleFails) nSettleFails := len(settleFails) @@ -479,8 +486,11 @@ func TestPackagerAddsThenSettleFails(t *testing.T) { t.Fatalf("no forwarding packages should exist, found %d", len(fwdPkgs)) } + adds := testAdds() + // Next, create and write a new forwarding package that only has add // htlcs. + settleFails := testSettleFails() fwdPkg := channeldb.NewFwdPkg(shortChanID, 0, adds, settleFails) nAdds := len(adds) @@ -612,8 +622,11 @@ func TestPackagerSettleFailsThenAdds(t *testing.T) { t.Fatalf("no forwarding packages should exist, found %d", len(fwdPkgs)) } + adds := testAdds() + // Next, create and write a new forwarding package that has both add // and settle/fail htlcs. + settleFails := testSettleFails() fwdPkg := channeldb.NewFwdPkg(shortChanID, 0, adds, settleFails) nAdds := len(adds) From 7302051f447d1d599063913e7b7456139b97674b Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 26 Apr 2024 15:29:21 -0700 Subject: [PATCH 057/109] build: update to sqldb v1.0.2 In this commit, we update the project and relevant sub-modules to sqldb v1.0.2. The next step is to tag a new version of kvdb, then update the main module to use that. --- go.mod | 12 ++++++------ go.sum | 40 +++++++++++++++++++++++++--------------- kvdb/go.mod | 2 +- kvdb/go.sum | 4 ++-- 4 files changed, 34 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index 5dd778818..68983d0f2 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( github.com/lightningnetwork/lnd/healthcheck v1.2.4 github.com/lightningnetwork/lnd/kvdb v1.4.6 github.com/lightningnetwork/lnd/queue v1.1.1 - github.com/lightningnetwork/lnd/sqldb v1.0.1 + github.com/lightningnetwork/lnd/sqldb v1.0.2 github.com/lightningnetwork/lnd/ticker v1.1.1 github.com/lightningnetwork/lnd/tlv v1.2.3 github.com/lightningnetwork/lnd/tor v1.1.2 @@ -98,7 +98,7 @@ require ( github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.0.1 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/google/uuid v1.4.0 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect @@ -119,7 +119,7 @@ require ( github.com/juju/testing v0.0.0-20220203020004-a0ff61f03494 // indirect github.com/lib/pq v1.10.9 // indirect github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf // indirect - github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/mitchellh/mapstructure v1.4.1 // indirect @@ -183,10 +183,10 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect - modernc.org/libc v1.41.0 // indirect + modernc.org/libc v1.49.3 // indirect modernc.org/mathutil v1.6.0 // indirect - modernc.org/memory v1.7.2 // indirect - modernc.org/sqlite v1.29.5 // indirect + modernc.org/memory v1.8.0 // indirect + modernc.org/sqlite v1.29.8 // indirect modernc.org/strutil v1.2.0 // indirect modernc.org/token v1.1.0 // indirect sigs.k8s.io/yaml v1.2.0 // indirect diff --git a/go.sum b/go.sum index e6f6245ff..6670c3125 100644 --- a/go.sum +++ b/go.sum @@ -286,14 +286,14 @@ 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-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= -github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= +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.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.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/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= @@ -456,8 +456,8 @@ github.com/lightningnetwork/lnd/kvdb v1.4.6 h1:2pkouBCXW2LHYanvNCXz8Pau16NTsTI8c github.com/lightningnetwork/lnd/kvdb v1.4.6/go.mod h1:sBwBi8uofKqgzWkSe9bPoTZKmanASPFANFTCWa0/iYo= github.com/lightningnetwork/lnd/queue v1.1.1 h1:99ovBlpM9B0FRCGYJo6RSFDlt8/vOkQQZznVb18iNMI= github.com/lightningnetwork/lnd/queue v1.1.1/go.mod h1:7A6nC1Qrm32FHuhx/mi1cieAiBZo5O6l8IBIoQxvkz4= -github.com/lightningnetwork/lnd/sqldb v1.0.1 h1:lpNoJ6qRh3D02oeIUsKQLZUzjcgZ9ppMZNZnwrpBBmY= -github.com/lightningnetwork/lnd/sqldb v1.0.1/go.mod h1:nSovU1U+gTPDWhfwmXu/kW8l8EJpwbvZQ05ijnkQzkA= +github.com/lightningnetwork/lnd/sqldb v1.0.2 h1:PfuYzScYMD9/QonKo/QvgsbXfTnH5DfldIimkfdW4Bk= +github.com/lightningnetwork/lnd/sqldb v1.0.2/go.mod h1:V2Xl6JNWLTKE97WJnwfs0d0TYJdIQTqK8/3aAwkd3qI= github.com/lightningnetwork/lnd/ticker v1.1.1 h1:J/b6N2hibFtC7JLV77ULQp++QLtCwT6ijJlbdiZFbSM= github.com/lightningnetwork/lnd/ticker v1.1.1/go.mod h1:waPTRAAcwtu7Ji3+3k+u/xH5GHovTsCoSVpho0KDvdA= github.com/lightningnetwork/lnd/tlv v1.2.3 h1:If5ibokA/UoCBGuCKaY6Vn2SJU0l9uAbehCnhTZjEP8= @@ -475,8 +475,8 @@ github.com/mattn/go-isatty v0.0.0-20160806122752-66b8e73f3f5c/go.mod h1:M+lRXTBq github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= -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-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= @@ -842,7 +842,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/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-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -1044,18 +1044,28 @@ 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= +modernc.org/cc/v4 v4.20.0 h1:45Or8mQfbUqJOG9WaxvlFYOAQO0lQ5RvqBcFCXngjxk= +modernc.org/cc/v4 v4.20.0/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= +modernc.org/ccgo/v4 v4.16.0 h1:ofwORa6vx2FMm0916/CkZjpFPSR70VwTjUCe2Eg5BnA= +modernc.org/ccgo/v4 v4.16.0/go.mod h1:dkNyWIjFrVIZ68DTo36vHK+6/ShBn4ysU61So6PIqCI= 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/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= -modernc.org/libc v1.41.0 h1:g9YAc6BkKlgORsUWj+JwqoB1wU3o4DE3bM3yvA3k+Gk= -modernc.org/libc v1.41.0/go.mod h1:w0eszPsiXoOnoMJgrXjglgLuDy/bt5RR4y3QzUUeodY= +modernc.org/libc v1.49.3 h1:j2MRCRdwJI2ls/sGbeSk0t2bypOG/uvPZUsGQFDulqg= +modernc.org/libc v1.49.3/go.mod h1:yMZuGkn7pXbKfoT/M35gFJOAEdSKdxL0q64sF7KqCDo= 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.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E= -modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E= -modernc.org/sqlite v1.29.5 h1:8l/SQKAjDtZFo9lkJLdk8g9JEOeYRG4/ghStDCCTiTE= -modernc.org/sqlite v1.29.5/go.mod h1:S02dvcmm7TnTRvGhv8IGYyLnIt7AS2KPaB1F/71p75U= +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.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.29.8 h1:nGKglNx9K5v0As+zF0/Gcl1kMkmaU1XynYyq92PbsC8= +modernc.org/sqlite v1.29.8/go.mod h1:lQPm27iqa4UNZpmr4Aor0MH0HkCLbt1huYDfWylLZFk= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= diff --git a/kvdb/go.mod b/kvdb/go.mod index 017c4c6f0..df0b62a13 100644 --- a/kvdb/go.mod +++ b/kvdb/go.mod @@ -8,7 +8,7 @@ require ( github.com/google/btree v1.0.1 github.com/jackc/pgx/v4 v4.18.1 github.com/lightningnetwork/lnd/healthcheck v1.2.4 - github.com/lightningnetwork/lnd/sqldb v1.0.1 + github.com/lightningnetwork/lnd/sqldb v1.0.2 github.com/stretchr/testify v1.9.0 go.etcd.io/bbolt v1.3.7 go.etcd.io/etcd/api/v3 v3.5.7 diff --git a/kvdb/go.sum b/kvdb/go.sum index 9ecf1542a..c7fda8448 100644 --- a/kvdb/go.sum +++ b/kvdb/go.sum @@ -294,8 +294,8 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lightningnetwork/lnd/healthcheck v1.2.4 h1:lLPLac+p/TllByxGSlkCwkJlkddqMP5UCoawCj3mgFQ= github.com/lightningnetwork/lnd/healthcheck v1.2.4/go.mod h1:G7Tst2tVvWo7cx6mSBEToQC5L1XOGxzZTPB29g9Rv2I= -github.com/lightningnetwork/lnd/sqldb v1.0.1 h1:lpNoJ6qRh3D02oeIUsKQLZUzjcgZ9ppMZNZnwrpBBmY= -github.com/lightningnetwork/lnd/sqldb v1.0.1/go.mod h1:nSovU1U+gTPDWhfwmXu/kW8l8EJpwbvZQ05ijnkQzkA= +github.com/lightningnetwork/lnd/sqldb v1.0.2 h1:PfuYzScYMD9/QonKo/QvgsbXfTnH5DfldIimkfdW4Bk= +github.com/lightningnetwork/lnd/sqldb v1.0.2/go.mod h1:V2Xl6JNWLTKE97WJnwfs0d0TYJdIQTqK8/3aAwkd3qI= github.com/lightningnetwork/lnd/ticker v1.1.0 h1:ShoBiRP3pIxZHaETndfQ5kEe+S4NdAY1hiX7YbZ4QE4= github.com/lightningnetwork/lnd/ticker v1.1.0/go.mod h1:ubqbSVCn6RlE0LazXuBr7/Zi6QT0uQo++OgIRBxQUrk= github.com/lightningnetwork/lnd/tor v1.0.0 h1:wvEc7I+Y7IOtPglVP3cVBbYhiVhc7uTd7cMF9gQRzwA= From f536c9b6080c9f86bdac052a8958c777a8a54f60 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 26 Apr 2024 16:17:19 -0700 Subject: [PATCH 058/109] build: update to kvdb v1.4.8 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 68983d0f2..55898d79a 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( github.com/lightningnetwork/lnd/clock v1.1.1 github.com/lightningnetwork/lnd/fn v1.0.5 github.com/lightningnetwork/lnd/healthcheck v1.2.4 - github.com/lightningnetwork/lnd/kvdb v1.4.6 + github.com/lightningnetwork/lnd/kvdb v1.4.8 github.com/lightningnetwork/lnd/queue v1.1.1 github.com/lightningnetwork/lnd/sqldb v1.0.2 github.com/lightningnetwork/lnd/ticker v1.1.1 diff --git a/go.sum b/go.sum index 6670c3125..5a21d5439 100644 --- a/go.sum +++ b/go.sum @@ -452,8 +452,8 @@ github.com/lightningnetwork/lnd/fn v1.0.5 h1:ffDgMSn83avw6rNzxhbt6w5/2oIrwQKTPGf github.com/lightningnetwork/lnd/fn v1.0.5/go.mod h1:P027+0CyELd92H9gnReUkGGAqbFA1HwjHWdfaDFD51U= github.com/lightningnetwork/lnd/healthcheck v1.2.4 h1:lLPLac+p/TllByxGSlkCwkJlkddqMP5UCoawCj3mgFQ= github.com/lightningnetwork/lnd/healthcheck v1.2.4/go.mod h1:G7Tst2tVvWo7cx6mSBEToQC5L1XOGxzZTPB29g9Rv2I= -github.com/lightningnetwork/lnd/kvdb v1.4.6 h1:2pkouBCXW2LHYanvNCXz8Pau16NTsTI8cO6JmBIBjVM= -github.com/lightningnetwork/lnd/kvdb v1.4.6/go.mod h1:sBwBi8uofKqgzWkSe9bPoTZKmanASPFANFTCWa0/iYo= +github.com/lightningnetwork/lnd/kvdb v1.4.8 h1:xH0a5Vi1yrcZ5BEeF2ba3vlKBRxrL9uYXlWTjOjbNTY= +github.com/lightningnetwork/lnd/kvdb v1.4.8/go.mod h1:J2diNABOoII9UrMnxXS5w7vZwP7CA1CStrl8MnIrb3A= github.com/lightningnetwork/lnd/queue v1.1.1 h1:99ovBlpM9B0FRCGYJo6RSFDlt8/vOkQQZznVb18iNMI= github.com/lightningnetwork/lnd/queue v1.1.1/go.mod h1:7A6nC1Qrm32FHuhx/mi1cieAiBZo5O6l8IBIoQxvkz4= github.com/lightningnetwork/lnd/sqldb v1.0.2 h1:PfuYzScYMD9/QonKo/QvgsbXfTnH5DfldIimkfdW4Bk= From 3b6103d29f45700194647888131a430b4551ff3d Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 26 Apr 2024 19:19:23 -0700 Subject: [PATCH 059/109] build: bump version to v0.18.0-beta.rc1 --- build/version.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build/version.go b/build/version.go index 77d62d22c..62aece381 100644 --- a/build/version.go +++ b/build/version.go @@ -40,14 +40,14 @@ const ( AppMajor uint = 0 // AppMinor defines the minor version of this binary. - AppMinor uint = 17 + AppMinor uint = 18 // AppPatch defines the application patch for this binary. - AppPatch uint = 99 + AppPatch uint = 00 // AppPreRelease MUST only contain characters from semanticAlphabet per // the semantic versioning spec. - AppPreRelease = "beta" + AppPreRelease = "beta.rc1" ) func init() { From 6e3a46ee9116797752d14592f31d3fa85221cb42 Mon Sep 17 00:00:00 2001 From: Carla Kirk-Cohen Date: Sat, 27 Apr 2024 11:28:42 -0400 Subject: [PATCH 060/109] itest: add more comprehensive assertions before HTLC cleared check We mine quite a few blocks in this test to trigger a htlc timeout, so it can be pretty slow. This fix adds assertions for additional "state steps" that happen in between the failing of the htlc on-chain and asserting that we're fully cleared out so that slower running machines won't timeout. --- itest/lnd_route_blinding_test.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/itest/lnd_route_blinding_test.go b/itest/lnd_route_blinding_test.go index 1cae46a0c..4b0eef859 100644 --- a/itest/lnd_route_blinding_test.go +++ b/itest/lnd_route_blinding_test.go @@ -1018,10 +1018,14 @@ func testErrorHandlingOnChainFailure(ht *lntest.HarnessTest) { // suspended Carol we don't need to account for her commitment output // claim. ht.Miner.MineBlocksAndAssertNumTxes(1, 1) + ht.AssertNumPendingSweeps(ht.Bob, 0) // Assert that the HTLC has cleared. - ht.AssertHTLCNotActive(ht.Alice, testCase.channels[0], hash[:]) + ht.WaitForBlockchainSync(ht.Bob) + ht.WaitForBlockchainSync(ht.Alice) + ht.AssertHTLCNotActive(ht.Bob, testCase.channels[0], hash[:]) + ht.AssertHTLCNotActive(ht.Alice, testCase.channels[0], hash[:]) // Wait for the HTLC to reflect as failed for Alice. paymentStream := ht.Alice.RPC.TrackPaymentV2(hash[:]) From 9f2995251eaa8e43a19f0930458c19ed8433755f Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Mon, 29 Apr 2024 19:14:27 +0800 Subject: [PATCH 061/109] lnrpc: fix typo --- lnrpc/walletrpc/walletkit.pb.go | 2 +- lnrpc/walletrpc/walletkit.proto | 4 ++-- lnrpc/walletrpc/walletkit.swagger.json | 4 ++-- lnrpc/walletrpc/walletkit_grpc.pb.go | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lnrpc/walletrpc/walletkit.pb.go b/lnrpc/walletrpc/walletkit.pb.go index 554b27dd5..bc01442e5 100644 --- a/lnrpc/walletrpc/walletkit.pb.go +++ b/lnrpc/walletrpc/walletkit.pb.go @@ -3068,7 +3068,7 @@ type BumpFeeRequest struct { Outpoint *lnrpc.OutPoint `protobuf:"bytes,1,opt,name=outpoint,proto3" json:"outpoint,omitempty"` // Optional. The deadline in number of blocks that the input should be spent // within. When not set, for new inputs, the default value (1008) is used; - // for exiting inputs, their current values will be retained. + // for existing inputs, their current values will be retained. TargetConf uint32 `protobuf:"varint,2,opt,name=target_conf,json=targetConf,proto3" json:"target_conf,omitempty"` // Deprecated, use sat_per_vbyte. // The fee rate, expressed in sat/vbyte, that should be used to spend the input diff --git a/lnrpc/walletrpc/walletkit.proto b/lnrpc/walletrpc/walletkit.proto index b6d09c64b..b86180344 100644 --- a/lnrpc/walletrpc/walletkit.proto +++ b/lnrpc/walletrpc/walletkit.proto @@ -283,7 +283,7 @@ service WalletKit { /* lncli: `wallet labeltx` LabelTransaction adds a label to a transaction. If the transaction already has a label the call will fail unless the overwrite bool is set. This will - overwrite the exiting transaction label. Labels must not be empty, and + overwrite the existing transaction label. Labels must not be empty, and cannot exceed 500 characters. */ rpc LabelTransaction (LabelTransactionRequest) @@ -1176,7 +1176,7 @@ message BumpFeeRequest { // Optional. The deadline in number of blocks that the input should be spent // within. When not set, for new inputs, the default value (1008) is used; - // for exiting inputs, their current values will be retained. + // for existing inputs, their current values will be retained. uint32 target_conf = 2; /* diff --git a/lnrpc/walletrpc/walletkit.swagger.json b/lnrpc/walletrpc/walletkit.swagger.json index f21894dd2..1e8286b1b 100644 --- a/lnrpc/walletrpc/walletkit.swagger.json +++ b/lnrpc/walletrpc/walletkit.swagger.json @@ -768,7 +768,7 @@ }, "/v2/wallet/tx/label": { "post": { - "summary": "lncli: `wallet labeltx`\nLabelTransaction adds a label to a transaction. If the transaction already\nhas a label the call will fail unless the overwrite bool is set. This will\noverwrite the exiting transaction label. Labels must not be empty, and\ncannot exceed 500 characters.", + "summary": "lncli: `wallet labeltx`\nLabelTransaction adds a label to a transaction. If the transaction already\nhas a label the call will fail unless the overwrite bool is set. This will\noverwrite the existing transaction label. Labels must not be empty, and\ncannot exceed 500 characters.", "operationId": "WalletKit_LabelTransaction", "responses": { "200": { @@ -1360,7 +1360,7 @@ "target_conf": { "type": "integer", "format": "int64", - "description": "Optional. The deadline in number of blocks that the input should be spent\nwithin. When not set, for new inputs, the default value (1008) is used;\nfor exiting inputs, their current values will be retained." + "description": "Optional. The deadline in number of blocks that the input should be spent\nwithin. When not set, for new inputs, the default value (1008) is used;\nfor existing inputs, their current values will be retained." }, "sat_per_byte": { "type": "integer", diff --git a/lnrpc/walletrpc/walletkit_grpc.pb.go b/lnrpc/walletrpc/walletkit_grpc.pb.go index 148457162..c49e2bdb7 100644 --- a/lnrpc/walletrpc/walletkit_grpc.pb.go +++ b/lnrpc/walletrpc/walletkit_grpc.pb.go @@ -216,7 +216,7 @@ type WalletKitClient interface { // lncli: `wallet labeltx` // LabelTransaction adds a label to a transaction. If the transaction already // has a label the call will fail unless the overwrite bool is set. This will - // overwrite the exiting transaction label. Labels must not be empty, and + // overwrite the existing transaction label. Labels must not be empty, and // cannot exceed 500 characters. LabelTransaction(ctx context.Context, in *LabelTransactionRequest, opts ...grpc.CallOption) (*LabelTransactionResponse, error) // lncli: `wallet psbt fund` @@ -727,7 +727,7 @@ type WalletKitServer interface { // lncli: `wallet labeltx` // LabelTransaction adds a label to a transaction. If the transaction already // has a label the call will fail unless the overwrite bool is set. This will - // overwrite the exiting transaction label. Labels must not be empty, and + // overwrite the existing transaction label. Labels must not be empty, and // cannot exceed 500 characters. LabelTransaction(context.Context, *LabelTransactionRequest) (*LabelTransactionResponse, error) // lncli: `wallet psbt fund` From be6b9b4b4722c53b67c7b5d16b089fd0b43abd33 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 29 Apr 2024 13:42:33 +0200 Subject: [PATCH 062/109] docs: update contributor list from git log This commit adds contributors that didn't add themselves to the release notes by extracting their GitHub username (or, if available their name and surname from GitHub) from the git log manually. --- docs/release-notes/release-notes-0.18.0.md | 33 +++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/release-notes-0.18.0.md b/docs/release-notes/release-notes-0.18.0.md index 67d0a3bc8..c413f95d7 100644 --- a/docs/release-notes/release-notes-0.18.0.md +++ b/docs/release-notes/release-notes-0.18.0.md @@ -530,25 +530,56 @@ bitcoin peers' feefilter values into account](https://github.com/lightningnetwor # Contributors (Alphabetical Order) * Alex Akselrod +* Alex Sears * Amin Bashiri * Andras Banki-Horvath +* AtomicInnovation321 +* bartoli * BitcoinerCoderBob +* bitromortac +* bota87 +* Calvin Zachman * Carla Kirk-Cohen +* cristiantroy +* cuinix +* davisv7 * Elle Mouton * ErikEk +* Eugene Siegel * Feelancer21 +* ffranr +* Hao Wang +* hidewrong * Jesse de Wit +* João Thallis +* Jonathan Harvey-Buschel * Joost Jager +* Jordi Montes * Keagan McClelland +* kilrau +* mani2310 * Marcos Fernandez Perez * Matt Morehouse +* Michael Rooke * Mohamed Awnallah * Olaoluwa Osuntokun +* Oliver Gugger * Ononiwu Maureen Chiamaka +* Sam Korn +* saubyk +* Simone Ragonesi * Slyghtning +* tdb3 * Tee8z +* testwill +* Thabokani +* threewebcode * Turtle -* Hao Wang +* twofaktor +* vuittont60 * w3irdrobot +* weiliy +* xiaoxianBoy * Yong Yu +* zhiqiangxu * Ziggie From 9dbf7e213302ba51b9c4dbd0185686cfcd0fbd20 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 29 Apr 2024 13:55:22 +0200 Subject: [PATCH 063/109] docs: cleanup release notes This commit removes a duplicate, fixes some typos and grammar issues and removes an empty section/heading. --- docs/release-notes/release-notes-0.18.0.md | 38 ++++++++++------------ 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/docs/release-notes/release-notes-0.18.0.md b/docs/release-notes/release-notes-0.18.0.md index c413f95d7..56ac7cac0 100644 --- a/docs/release-notes/release-notes-0.18.0.md +++ b/docs/release-notes/release-notes-0.18.0.md @@ -107,7 +107,8 @@ which with the default fee allocation in place will eventually lead to the downsizing to the fee floor (1 sat/vByte) in the worst case. -* [Removed](https://github.com/lightningnetwork/lnd/pull/8577) some unreachable code +* [Removed](https://github.com/lightningnetwork/lnd/pull/8577) some unreachable + code. * [Fixed](https://github.com/lightningnetwork/lnd/pull/8609) a function call where arguments were swapped. @@ -118,20 +119,17 @@ * [Fixed a bug in `btcd` that caused an incompatibility with `bitcoind v27.0`](https://github.com/lightningnetwork/lnd/pull/8573). - -* [Fixed](https://github.com/lightningnetwork/lnd/pull/8609) a function call - where arguments were swapped. -* [Fixed](https://github.com/lightningnetwork/lnd/pull/8545) utxo selection +* [Fixed](https://github.com/lightningnetwork/lnd/pull/8545) UTXO selection for the internal channel funding flow (Single and Batch Funding Flow). Now - utxos which are unconfirmed and originated from the sweeper subsystem are not + UTXOs which are unconfirmed and originated from the sweeper subsystem are not selected because they bear the risk of being replaced (BIP 125 RBF). -* [Fixed](https://github.com/lightningnetwork/lnd/pull/8685) lncli "bumpfee" +* [Fixed](https://github.com/lightningnetwork/lnd/pull/8685) `lncli bumpfee` parsing of the immediate/force flag. * [Fixed](https://github.com/lightningnetwork/lnd/pull/8621) the behaviour of - neutrino LND nodes which would loose sync in case they had very unstable + neutrino LND nodes which would lose sync in case they had very unstable peer connection. # New Features @@ -151,13 +149,13 @@ can be enabled with the option `accept-positive-inbound-fees`. * A new config value, - [sweeper.maxfeerate](https://github.com/lightningnetwork/lnd/pull/7823), is + [`sweeper.maxfeerate`](https://github.com/lightningnetwork/lnd/pull/7823), is added so users can specify the max allowed fee rate when sweeping on-chain - funds. The default value is 1000 sat/vb. Setting this value below 100 sat/vb + funds. The default value is 1000 sat/vB. Setting this value below 100 sat/vB is not allowed, as low fee rate can cause transactions not confirming in time, which could result in fund loss. Please note that the actual fee rate to be used is determined by the fee - estimator used(for instance `bitcoind`), and this value is a cap on the max + estimator used (for instance `bitcoind`), and this value is a cap on the max allowed value. So it's expected that this cap is rarely hit unless there's mempool congestion. @@ -210,8 +208,9 @@ `lnd.conf`](https://github.com/lightningnetwork/lnd/pull/8310) for the `rpcuser` and `rpcpass` fields to better protect the secrets. -* When computing a minimum fee for transaction construction, `lnd` [now takes our -bitcoin peers' feefilter values into account](https://github.com/lightningnetwork/lnd/pull/8418). +* When computing a minimum fee for transaction construction, `lnd` [now takes + its bitcoin peers' `feefilter` values into + account](https://github.com/lightningnetwork/lnd/pull/8418). * [Preparatory work](https://github.com/lightningnetwork/lnd/pull/8159) for forwarding of blinded routes was added, along with [support](https://github.com/lightningnetwork/lnd/pull/8160) @@ -268,7 +267,7 @@ bitcoin peers' feefilter values into account](https://github.com/lightningnetwor * Deprecate `bumpclosefee` for `bumpforceclosefee` to accommodate for the fact that only force closing transactions can be bumped to avoid confusion. - Moreover allow to specify a max fee rate range when coop closing a channel. + Moreover, allow to specify a max fee rate range when coop closing a channel. [Deprecate bumpclosefee for bumpforceclosefee and add `max_fee_rate` option to `closechannel` cmd](https://github.com/lightningnetwork/lnd/pull/8350). @@ -347,7 +346,8 @@ bitcoin peers' feefilter values into account](https://github.com/lightningnetwor * [Coin Selection Strategy](https://github.com/lightningnetwork/lnd/pull/8515) add coin selection strategy option to the following on-chain RPC calls - `EstimateFee`, `SendMany`, `SendCoins`, `BatchOpenChannel`, `SendOutputs`, and `FundPsbt`. + `EstimateFee`, `SendMany`, `SendCoins`, `BatchOpenChannel`, `SendOutputs`, and + `FundPsbt`. * `BumpFee` has been updated to take advantage of the [new budget-based sweeper](https://github.com/lightningnetwork/lnd/pull/8667). The param @@ -365,7 +365,7 @@ bitcoin peers' feefilter values into account](https://github.com/lightningnetwor * When paying an AMP payment request, [the `--amp` flag is now required](https://github.com/lightningnetwork/lnd/pull/8681) to be consistent - w/ the flow when a payment request isn't used. + with the flow when a payment request isn't used. ## lncli Updates @@ -425,7 +425,7 @@ bitcoin peers' feefilter values into account](https://github.com/lightningnetwor ## Breaking Changes -* Previously when callng `SendCoins`, `SendMany`, `OpenChannel` and +* Previously when calling `SendCoins`, `SendMany`, `OpenChannel` and `CloseChannel` for coop close, it is allowed to specify both an empty `SatPerVbyte` and `TargetConf`, and a default conf target of 6 will be used. This will [no longer be @@ -517,7 +517,7 @@ bitcoin peers' feefilter values into account](https://github.com/lightningnetwor settings between `sqldb` and `kvdb` packages. * [Expanded SweeperStore](https://github.com/lightningnetwork/lnd/pull/8147) to - also store the feerate, fees paid, and whether it's published or not for a + also store the fee rate, fees paid, and whether it's published or not for a given sweeping transaction. ## Code Health @@ -525,8 +525,6 @@ bitcoin peers' feefilter values into account](https://github.com/lightningnetwor * [Remove database pointers](https://github.com/lightningnetwork/lnd/pull/8117) from `channeldb` schema structs. -## Tooling and Documentation - # Contributors (Alphabetical Order) * Alex Akselrod From 6159d41970ffa1ebaa94bf4ceaa6b9b3c65c0acb Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 29 Apr 2024 14:09:05 +0200 Subject: [PATCH 064/109] docs: remove entry for fix within release This commit removes an entry that was fixed in the same release as it was introduced. So nobody should've been running into it yet. --- docs/release-notes/release-notes-0.18.0.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/release-notes/release-notes-0.18.0.md b/docs/release-notes/release-notes-0.18.0.md index 56ac7cac0..7e9f1e616 100644 --- a/docs/release-notes/release-notes-0.18.0.md +++ b/docs/release-notes/release-notes-0.18.0.md @@ -124,9 +124,6 @@ for the internal channel funding flow (Single and Batch Funding Flow). Now UTXOs which are unconfirmed and originated from the sweeper subsystem are not selected because they bear the risk of being replaced (BIP 125 RBF). - -* [Fixed](https://github.com/lightningnetwork/lnd/pull/8685) `lncli bumpfee` - parsing of the immediate/force flag. * [Fixed](https://github.com/lightningnetwork/lnd/pull/8621) the behaviour of neutrino LND nodes which would lose sync in case they had very unstable From 15424247828b0c40f703ae3ff168a869befaf68d Mon Sep 17 00:00:00 2001 From: djkazic Date: Tue, 30 Apr 2024 11:40:44 -0400 Subject: [PATCH 065/109] invoices: if there are no invoices make gc noop --- channeldb/invoices.go | 4 ++-- invoices/invoices_test.go | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/channeldb/invoices.go b/channeldb/invoices.go index a7663cabf..df124b632 100644 --- a/channeldb/invoices.go +++ b/channeldb/invoices.go @@ -2139,14 +2139,14 @@ func (d *DB) DeleteCanceledInvoices(_ context.Context) error { invoiceIndexBucket, ) if invoiceIndex == nil { - return invpkg.ErrNoInvoicesCreated + return nil } invoiceAddIndex := invoices.NestedReadWriteBucket( addIndexBucket, ) if invoiceAddIndex == nil { - return invpkg.ErrNoInvoicesCreated + return nil } payAddrIndex := tx.ReadWriteBucket(payAddrIndexBucket) diff --git a/invoices/invoices_test.go b/invoices/invoices_test.go index 6f3cbd8f2..c9e204571 100644 --- a/invoices/invoices_test.go +++ b/invoices/invoices_test.go @@ -2681,8 +2681,11 @@ func testDeleteCanceledInvoices(t *testing.T, }, nil } - // Add some invoices to the test db. + // Test deletion of canceled invoices when there are none. ctxb := context.Background() + require.NoError(t, db.DeleteCanceledInvoices(ctxb)) + + // Add some invoices to the test db. var invoices []invpkg.Invoice for i := 0; i < 10; i++ { invoice, err := randInvoice(lnwire.MilliSatoshi(i + 1)) From 3f8da16b77ce9759a391033db05b62a15a14c55b Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Wed, 1 May 2024 12:16:54 +0800 Subject: [PATCH 066/109] sweep: make `TxPublisher.currentHeight` atomic --- sweep/fee_bumper.go | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/sweep/fee_bumper.go b/sweep/fee_bumper.go index 61e63cc71..a0e558cbb 100644 --- a/sweep/fee_bumper.go +++ b/sweep/fee_bumper.go @@ -267,7 +267,7 @@ type TxPublisher struct { cfg *TxPublisherConfig // currentHeight is the current block height. - currentHeight int32 + currentHeight atomic.Int32 // records is a map keyed by the requestCounter and the value is the tx // being monitored. @@ -373,7 +373,9 @@ func (t *TxPublisher) initializeFeeFunction( } // Get the initial conf target. - confTarget := calcCurrentConfTarget(t.currentHeight, req.DeadlineHeight) + confTarget := calcCurrentConfTarget( + t.currentHeight.Load(), req.DeadlineHeight, + ) log.Debugf("Initializing fee function with conf target=%v, budget=%v, "+ "maxFeeRateAllowed=%v", confTarget, req.Budget, @@ -542,7 +544,7 @@ func (t *TxPublisher) broadcast(requestID uint64) (*BumpResult, error) { tx := record.tx log.Debugf("Publishing sweep tx %v, num_inputs=%v, height=%v", - txid, len(tx.TxIn), t.currentHeight) + txid, len(tx.TxIn), t.currentHeight.Load()) // Set the event, and change it to TxFailed if the wallet fails to // publish it. @@ -715,7 +717,7 @@ func (t *TxPublisher) monitor(blockEvent *chainntnfs.BlockEpochEvent) { epoch.Height) // Update the best known height for the publisher. - t.currentHeight = epoch.Height + t.currentHeight.Store(epoch.Height) // Check all monitored txns to see if any of them needs // to be bumped. @@ -788,7 +790,7 @@ func (t *TxPublisher) processRecords() { } // Get the current height to be used in the following goroutines. - currentHeight := t.currentHeight + currentHeight := t.currentHeight.Load() // For records that are not confirmed, we perform a fee bump if needed. for requestID, r := range feeBumpRecords { @@ -854,7 +856,7 @@ func (t *TxPublisher) handleFeeBumpTx(requestID uint64, r *monitorRecord, // TODO(yy): send this error back to the sweeper so it can // re-group the inputs? log.Errorf("Failed to increase fee rate for tx %v at "+ - "height=%v: %v", oldTxid, t.currentHeight, err) + "height=%v: %v", oldTxid, t.currentHeight.Load(), err) return } @@ -862,7 +864,7 @@ func (t *TxPublisher) handleFeeBumpTx(requestID uint64, r *monitorRecord, // If the fee rate was not increased, there's no need to bump the fee. if !increased { log.Tracef("Skip bumping tx %v at height=%v", oldTxid, - t.currentHeight) + t.currentHeight.Load()) return } @@ -1122,7 +1124,7 @@ func (t *TxPublisher) createSweepTx(inputs []input.Input, changePkScript []byte, // Validate and calculate the fee and change amount. txFee, changeAmtOpt, locktimeOpt, err := prepareSweepTx( - inputs, changePkScript, feeRate, t.currentHeight, + inputs, changePkScript, feeRate, t.currentHeight.Load(), ) if err != nil { return nil, 0, err @@ -1178,7 +1180,7 @@ func (t *TxPublisher) createSweepTx(inputs []input.Input, changePkScript []byte, // We'll default to using the current block height as locktime, if none // of the inputs commits to a different locktime. - sweepTx.LockTime = uint32(locktimeOpt.UnwrapOr(t.currentHeight)) + sweepTx.LockTime = uint32(locktimeOpt.UnwrapOr(t.currentHeight.Load())) prevInputFetcher, err := input.MultiPrevOutFetcher(inputs) if err != nil { From fa616ee05912adb2f924016dd3e0c2ba93d457a7 Mon Sep 17 00:00:00 2001 From: Tom Kirkpatrick Date: Tue, 23 Apr 2024 09:40:05 +0200 Subject: [PATCH 067/109] config: remove deprecated neutrino.feeurl config option --- chainreg/chainregistry.go | 12 ------------ docs/release-notes/release-notes-0.18.0.md | 3 +++ sample-lnd.conf | 4 ---- 3 files changed, 3 insertions(+), 16 deletions(-) diff --git a/chainreg/chainregistry.go b/chainreg/chainregistry.go index 8b562e87a..eff101e95 100644 --- a/chainreg/chainregistry.go +++ b/chainreg/chainregistry.go @@ -261,18 +261,6 @@ func NewPartialChainControl(cfg *Config) (*PartialChainControl, func(), error) { return nil, nil, err } - // Map the deprecated neutrino feeurl flag to the general fee - // url. - if cfg.NeutrinoMode.FeeURL != "" { - if cfg.FeeURL != "" { - return nil, nil, errors.New("feeurl and " + - "neutrino.feeurl are mutually " + - "exclusive") - } - - cfg.FeeURL = cfg.NeutrinoMode.FeeURL - } - cc.ChainSource = chain.NewNeutrinoClient( cfg.ActiveNetParams.Params, cfg.NeutrinoCS, ) diff --git a/docs/release-notes/release-notes-0.18.0.md b/docs/release-notes/release-notes-0.18.0.md index 7e9f1e616..4d01a5fba 100644 --- a/docs/release-notes/release-notes-0.18.0.md +++ b/docs/release-notes/release-notes-0.18.0.md @@ -433,6 +433,9 @@ logged](https://github.com/lightningnetwork/lnd/pull/8693) when no values are specified. +* Removed deprecated `neutrino.feeurl` option. Please use the newer `fee.url` + option instead. + ## Performance Improvements * Watchtower client DB migration to massively [improve the start-up diff --git a/sample-lnd.conf b/sample-lnd.conf index d6bc83d4b..25833013f 100644 --- a/sample-lnd.conf +++ b/sample-lnd.conf @@ -802,10 +802,6 @@ ; NOTE: This value is currently unused. ; neutrino.banthreshold= -; DEPRECATED: Use top level 'feeurl' option. Optional URL for fee estimation. If -; a URL is not specified, static fees will be used for estimation. -; neutrino.feeurl= - ; Optional filter header in height:hash format to assert the state of neutrino's ; filter header chain on startup. If the assertion does not hold, then the ; filter header chain will be re-synced from the genesis block. From 3837c3f12ec7b698b95758f18ad45a593e4a7dcb Mon Sep 17 00:00:00 2001 From: Tom Kirkpatrick Date: Tue, 23 Apr 2024 09:49:04 +0200 Subject: [PATCH 068/109] lnwallet: add configurable cache for web fee estimator Add fee.min-update-timeout and fee.max-update-timeout config options to allow configuration of the web fee estimator cache. --- chainreg/chainregistry.go | 39 ++++++++++---- config.go | 10 +++- config_builder.go | 5 ++ docs/release-notes/release-notes-0.18.0.md | 11 ++++ htlcswitch/link.go | 16 +++--- htlcswitch/link_test.go | 14 ++--- htlcswitch/test_utils.go | 4 +- lncfg/fee.go | 20 ++++++++ lncfg/neutrino.go | 1 - lntest/fee_service.go | 2 +- lntest/node/config.go | 2 +- lnwallet/chainfee/estimator.go | 59 +++++++++++++++------- lnwallet/chainfee/estimator_test.go | 50 +++++++++++++++++- peer/brontide.go | 4 +- sample-lnd.conf | 20 ++++++-- 15 files changed, 202 insertions(+), 55 deletions(-) create mode 100644 lncfg/fee.go diff --git a/chainreg/chainregistry.go b/chainreg/chainregistry.go index eff101e95..37e72fdee 100644 --- a/chainreg/chainregistry.go +++ b/chainreg/chainregistry.go @@ -77,10 +77,14 @@ type Config struct { // ActiveNetParams details the current chain we are on. ActiveNetParams BitcoinNetParams - // FeeURL defines the URL for fee estimation we will use. This field is - // optional. + // Deprecated: Use Fee.URL. FeeURL defines the URL for fee estimation + // we will use. This field is optional. FeeURL string + // Fee defines settings for the web fee estimator. This field is + // optional. + Fee *lncfg.Fee + // Dialer is a function closure that will be used to establish outbound // TCP connections to Bitcoin peers in the event of a pruned block being // requested. @@ -243,6 +247,16 @@ func NewPartialChainControl(cfg *Config) (*PartialChainControl, func(), error) { "cache: %v", err) } + // Map the deprecated feeurl flag to fee.url. + if cfg.FeeURL != "" { + if cfg.Fee.URL != "" { + return nil, nil, errors.New("fee.url and " + + "feeurl are mutually exclusive") + } + + cfg.Fee.URL = cfg.FeeURL + } + // If spv mode is active, then we'll be using a distinct set of // chainControl interfaces that interface directly with the p2p network // of the selected chain. @@ -682,27 +696,34 @@ func NewPartialChainControl(cfg *Config) (*PartialChainControl, func(), error) { // If the fee URL isn't set, and the user is running mainnet, then // we'll return an error to instruct them to set a proper fee // estimator. - case cfg.FeeURL == "" && cfg.Bitcoin.MainNet && + case cfg.Fee.URL == "" && cfg.Bitcoin.MainNet && cfg.Bitcoin.Node == "neutrino": - return nil, nil, fmt.Errorf("--feeurl parameter required " + + return nil, nil, fmt.Errorf("--fee.url parameter required " + "when running neutrino on mainnet") // Override default fee estimator if an external service is specified. - case cfg.FeeURL != "": + case cfg.Fee.URL != "": // Do not cache fees on regtest to make it easier to execute // manual or automated test cases. cacheFees := !cfg.Bitcoin.RegTest - log.Infof("Using external fee estimator %v: cached=%v", - cfg.FeeURL, cacheFees) + log.Infof("Using external fee estimator %v: cached=%v: "+ + "min update timeout=%v, max update timeout=%v", + cfg.Fee.URL, cacheFees, cfg.Fee.MinUpdateTimeout, + cfg.Fee.MaxUpdateTimeout) - cc.FeeEstimator = chainfee.NewWebAPIEstimator( + cc.FeeEstimator, err = chainfee.NewWebAPIEstimator( chainfee.SparseConfFeeSource{ - URL: cfg.FeeURL, + URL: cfg.Fee.URL, }, !cacheFees, + cfg.Fee.MinUpdateTimeout, + cfg.Fee.MaxUpdateTimeout, ) + if err != nil { + return nil, nil, err + } } ccCleanup := func() { diff --git a/config.go b/config.go index 6c8df62dd..a8b609deb 100644 --- a/config.go +++ b/config.go @@ -350,7 +350,7 @@ type Config struct { MaxPendingChannels int `long:"maxpendingchannels" description:"The maximum number of incoming pending channels permitted per peer."` BackupFilePath string `long:"backupfilepath" description:"The target location of the channel backup file"` - FeeURL string `long:"feeurl" description:"Optional URL for external fee estimation. If no URL is specified, the method for fee estimation will depend on the chosen backend and network. Must be set for neutrino on mainnet."` + FeeURL string `long:"feeurl" description:"DEPRECATED: Use 'fee.url' option. Optional URL for external fee estimation. If no URL is specified, the method for fee estimation will depend on the chosen backend and network. Must be set for neutrino on mainnet." hidden:"true"` Bitcoin *lncfg.Chain `group:"Bitcoin" namespace:"bitcoin"` BtcdMode *lncfg.Btcd `group:"btcd" namespace:"btcd"` @@ -442,6 +442,8 @@ type Config struct { DustThreshold uint64 `long:"dust-threshold" description:"Sets the dust sum threshold in satoshis for a channel after which dust HTLC's will be failed."` + Fee *lncfg.Fee `group:"fee" namespace:"fee"` + Invoices *lncfg.Invoices `group:"invoices" namespace:"invoices"` Routing *lncfg.Routing `group:"routing" namespace:"routing"` @@ -582,6 +584,12 @@ func DefaultConfig() Config { MinBackoff: defaultMinBackoff, MaxBackoff: defaultMaxBackoff, ConnectionTimeout: tor.DefaultConnTimeout, + + Fee: &lncfg.Fee{ + MinUpdateTimeout: lncfg.DefaultMinUpdateTimeout, + MaxUpdateTimeout: lncfg.DefaultMaxUpdateTimeout, + }, + SubRPCServers: &subRPCServerConfigs{ SignRPC: &signrpc.Config{}, RouterRPC: routerrpc.DefaultConfig(), diff --git a/config_builder.go b/config_builder.go index 895f7e4ad..49a0b6c50 100644 --- a/config_builder.go +++ b/config_builder.go @@ -550,6 +550,11 @@ func (d *DefaultWalletImpl) BuildWalletConfig(ctx context.Context, NeutrinoCS: neutrinoCS, ActiveNetParams: d.cfg.ActiveNetParams, FeeURL: d.cfg.FeeURL, + Fee: &lncfg.Fee{ + URL: d.cfg.Fee.URL, + MinUpdateTimeout: d.cfg.Fee.MinUpdateTimeout, + MaxUpdateTimeout: d.cfg.Fee.MaxUpdateTimeout, + }, Dialer: func(addr string) (net.Conn, error) { return d.cfg.net.Dial( "tcp", addr, d.cfg.ConnectionTimeout, diff --git a/docs/release-notes/release-notes-0.18.0.md b/docs/release-notes/release-notes-0.18.0.md index 4d01a5fba..5aec2d0da 100644 --- a/docs/release-notes/release-notes-0.18.0.md +++ b/docs/release-notes/release-notes-0.18.0.md @@ -209,6 +209,17 @@ its bitcoin peers' `feefilter` values into account](https://github.com/lightningnetwork/lnd/pull/8418). +* Web fee estimator settings have been moved into a new `fee` config group. + A new `fee.url` option has been added within this group that replaces the old + `feeurl` option, which is now deprecated. Additionally, [two new config values, + fee.min-update-timeout and fee.max-update-timeout](https://github.com/lightningnetwork/lnd/pull/8484) + are added to allow users to specify the minimum and maximum time between fee + updates from the web fee estimator. The default values are 5 minutes and 20 + minutes respectively. These values are used to prevent the fee estimator from + being queried too frequently. This replaces previously hardcoded values that + were set to the same values as the new defaults. The previously deprecated + `neutrino.feeurl` option has been removed. + * [Preparatory work](https://github.com/lightningnetwork/lnd/pull/8159) for forwarding of blinded routes was added, along with [support](https://github.com/lightningnetwork/lnd/pull/8160) for forwarding blinded payments and [error handling](https://github.com/lightningnetwork/lnd/pull/8485). diff --git a/htlcswitch/link.go b/htlcswitch/link.go index ed3151728..c0c828f83 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -202,15 +202,15 @@ type ChannelLinkConfig struct { // receiving node is persistent. UnsafeReplay bool - // MinFeeUpdateTimeout represents the minimum interval in which a link + // MinUpdateTimeout represents the minimum interval in which a link // will propose to update its commitment fee rate. A random timeout will - // be selected between this and MaxFeeUpdateTimeout. - MinFeeUpdateTimeout time.Duration + // be selected between this and MaxUpdateTimeout. + MinUpdateTimeout time.Duration - // MaxFeeUpdateTimeout represents the maximum interval in which a link + // MaxUpdateTimeout represents the maximum interval in which a link // will propose to update its commitment fee rate. A random timeout will - // be selected between this and MinFeeUpdateTimeout. - MaxFeeUpdateTimeout time.Duration + // be selected between this and MinUpdateTimeout. + MaxUpdateTimeout time.Duration // OutgoingCltvRejectDelta defines the number of blocks before expiry of // an htlc where we don't offer an htlc anymore. This should be at least @@ -1558,8 +1558,8 @@ func getResolutionFailure(resolution *invoices.HtlcFailResolution, // within the link's configuration that will be used to determine when the link // should propose an update to its commitment fee rate. func (l *channelLink) randomFeeUpdateTimeout() time.Duration { - lower := int64(l.cfg.MinFeeUpdateTimeout) - upper := int64(l.cfg.MaxFeeUpdateTimeout) + lower := int64(l.cfg.MinUpdateTimeout) + upper := int64(l.cfg.MaxUpdateTimeout) return time.Duration(prand.Int63n(upper-lower) + lower) } diff --git a/htlcswitch/link_test.go b/htlcswitch/link_test.go index 4db22d173..6963bf708 100644 --- a/htlcswitch/link_test.go +++ b/htlcswitch/link_test.go @@ -2220,11 +2220,11 @@ func newSingleLinkTestHarness(t *testing.T, chanAmt, BatchTicker: bticker, FwdPkgGCTicker: ticker.NewForce(15 * time.Second), PendingCommitTicker: ticker.New(time.Minute), - // Make the BatchSize and Min/MaxFeeUpdateTimeout large enough + // Make the BatchSize and Min/MaxUpdateTimeout large enough // to not trigger commit updates automatically during tests. BatchSize: 10000, - MinFeeUpdateTimeout: 30 * time.Minute, - MaxFeeUpdateTimeout: 40 * time.Minute, + MinUpdateTimeout: 30 * time.Minute, + MaxUpdateTimeout: 40 * time.Minute, MaxOutgoingCltvExpiry: DefaultMaxOutgoingCltvExpiry, MaxFeeAllocation: DefaultMaxLinkFeeAllocation, NotifyActiveLink: func(wire.OutPoint) {}, @@ -4881,11 +4881,11 @@ func (h *persistentLinkHarness) restartLink( BatchTicker: bticker, FwdPkgGCTicker: ticker.New(5 * time.Second), PendingCommitTicker: ticker.New(time.Minute), - // Make the BatchSize and Min/MaxFeeUpdateTimeout large enough + // Make the BatchSize and Min/MaxUpdateTimeout large enough // to not trigger commit updates automatically during tests. - BatchSize: 10000, - MinFeeUpdateTimeout: 30 * time.Minute, - MaxFeeUpdateTimeout: 40 * time.Minute, + BatchSize: 10000, + MinUpdateTimeout: 30 * time.Minute, + MaxUpdateTimeout: 40 * time.Minute, // Set any hodl flags requested for the new link. HodlMask: hodl.MaskFromFlags(hodlFlags...), MaxOutgoingCltvExpiry: DefaultMaxOutgoingCltvExpiry, diff --git a/htlcswitch/test_utils.go b/htlcswitch/test_utils.go index 0c98fa4fe..9a72197ec 100644 --- a/htlcswitch/test_utils.go +++ b/htlcswitch/test_utils.go @@ -1155,8 +1155,8 @@ func (h *hopNetwork) createChannelLink(server, peer *mockServer, BatchTicker: ticker.NewForce(testBatchTimeout), FwdPkgGCTicker: ticker.NewForce(fwdPkgTimeout), PendingCommitTicker: ticker.New(2 * time.Minute), - MinFeeUpdateTimeout: minFeeUpdateTimeout, - MaxFeeUpdateTimeout: maxFeeUpdateTimeout, + MinUpdateTimeout: minFeeUpdateTimeout, + MaxUpdateTimeout: maxFeeUpdateTimeout, OnChannelFailure: func(lnwire.ChannelID, lnwire.ShortChannelID, LinkFailureError) {}, OutgoingCltvRejectDelta: 3, MaxOutgoingCltvExpiry: DefaultMaxOutgoingCltvExpiry, diff --git a/lncfg/fee.go b/lncfg/fee.go new file mode 100644 index 000000000..200ae9e81 --- /dev/null +++ b/lncfg/fee.go @@ -0,0 +1,20 @@ +package lncfg + +import "time" + +// DefaultMinUpdateTimeout represents the minimum interval in which a +// WebAPIEstimator will request fresh fees from its API. +const DefaultMinUpdateTimeout = 5 * time.Minute + +// DefaultMaxUpdateTimeout represents the maximum interval in which a +// WebAPIEstimator will request fresh fees from its API. +const DefaultMaxUpdateTimeout = 20 * time.Minute + +// Fee holds the configuration options for fee estimation. +// +//nolint:lll +type Fee struct { + URL string `long:"url" description:"Optional URL for external fee estimation. If no URL is specified, the method for fee estimation will depend on the chosen backend and network. Must be set for neutrino on mainnet."` + MinUpdateTimeout time.Duration `long:"min-update-timeout" description:"The minimum interval in which fees will be updated from the specified fee URL."` + MaxUpdateTimeout time.Duration `long:"max-update-timeout" description:"The maximum interval in which fees will be updated from the specified fee URL."` +} diff --git a/lncfg/neutrino.go b/lncfg/neutrino.go index 09a66312a..e46c292dc 100644 --- a/lncfg/neutrino.go +++ b/lncfg/neutrino.go @@ -12,7 +12,6 @@ type Neutrino struct { MaxPeers int `long:"maxpeers" description:"Max number of inbound and outbound peers"` BanDuration time.Duration `long:"banduration" description:"How long to ban misbehaving peers. Valid time units are {s, m, h}. Minimum 1 second"` BanThreshold uint32 `long:"banthreshold" description:"Maximum allowed ban score before disconnecting and banning misbehaving peers."` - FeeURL string `long:"feeurl" description:"DEPRECATED: Use top level 'feeurl' option. Optional URL for fee estimation. If a URL is not specified, static fees will be used for estimation." hidden:"true"` AssertFilterHeader string `long:"assertfilterheader" description:"Optional filter header in height:hash format to assert the state of neutrino's filter header chain on startup. If the assertion does not hold, then the filter header chain will be re-synced from the genesis block."` UserAgentName string `long:"useragentname" description:"Used to help identify ourselves to other bitcoin peers"` UserAgentVersion string `long:"useragentversion" description:"Used to help identify ourselves to other bitcoin peers"` diff --git a/lntest/fee_service.go b/lntest/fee_service.go index d96bd7588..cee9ae0ab 100644 --- a/lntest/fee_service.go +++ b/lntest/fee_service.go @@ -17,7 +17,7 @@ import ( // WebFeeService defines an interface that's used to provide fee estimation // service used in the integration tests. It must provide an URL so that a lnd -// node can be started with the flag `--feeurl` and uses the customized fee +// node can be started with the flag `--fee.url` and uses the customized fee // estimator. type WebFeeService interface { // Start starts the service. diff --git a/lntest/node/config.go b/lntest/node/config.go index d0de2fdd4..de1ea92ec 100644 --- a/lntest/node/config.go +++ b/lntest/node/config.go @@ -279,7 +279,7 @@ func (cfg *BaseNodeConfig) GenArgs() []string { } if cfg.FeeURL != "" { - args = append(args, "--feeurl="+cfg.FeeURL) + args = append(args, "--fee.url="+cfg.FeeURL) } // Put extra args in the end so the args can be overwritten. diff --git a/lnwallet/chainfee/estimator.go b/lnwallet/chainfee/estimator.go index 76c235d1b..0ce9ae9b8 100644 --- a/lnwallet/chainfee/estimator.go +++ b/lnwallet/chainfee/estimator.go @@ -28,14 +28,6 @@ const ( // less than this will result in an error. minBlockTarget uint32 = 1 - // minFeeUpdateTimeout represents the minimum interval in which a - // WebAPIEstimator will request fresh fees from its API. - minFeeUpdateTimeout = 5 * time.Minute - - // maxFeeUpdateTimeout represents the maximum interval in which a - // WebAPIEstimator will request fresh fees from its API. - maxFeeUpdateTimeout = 20 * time.Minute - // WebAPIConnectionTimeout specifies the timeout value for connecting // to the api source. WebAPIConnectionTimeout = 5 * time.Second @@ -739,19 +731,43 @@ type WebAPIEstimator struct { // estimates. noCache bool + // minFeeUpdateTimeout represents the minimum interval in which the + // web estimator will request fresh fees from its API. + minFeeUpdateTimeout time.Duration + + // minFeeUpdateTimeout represents the maximum interval in which the + // web estimator will request fresh fees from its API. + maxFeeUpdateTimeout time.Duration + quit chan struct{} wg sync.WaitGroup } // NewWebAPIEstimator creates a new WebAPIEstimator from a given URL and a // fallback default fee. The fees are updated whenever a new block is mined. -func NewWebAPIEstimator(api WebAPIFeeSource, noCache bool) *WebAPIEstimator { - return &WebAPIEstimator{ - apiSource: api, - feeByBlockTarget: make(map[uint32]uint32), - noCache: noCache, - quit: make(chan struct{}), +func NewWebAPIEstimator(api WebAPIFeeSource, noCache bool, + minFeeUpdateTimeout time.Duration, + maxFeeUpdateTimeout time.Duration) (*WebAPIEstimator, error) { + + if minFeeUpdateTimeout == 0 || maxFeeUpdateTimeout == 0 { + return nil, fmt.Errorf("minFeeUpdateTimeout and " + + "maxFeeUpdateTimeout must be greater than 0") } + + if minFeeUpdateTimeout >= maxFeeUpdateTimeout { + return nil, fmt.Errorf("minFeeUpdateTimeout target of %v "+ + "cannot be greater than maxFeeUpdateTimeout of %v", + minFeeUpdateTimeout, maxFeeUpdateTimeout) + } + + return &WebAPIEstimator{ + apiSource: api, + feeByBlockTarget: make(map[uint32]uint32), + noCache: noCache, + quit: make(chan struct{}), + minFeeUpdateTimeout: minFeeUpdateTimeout, + maxFeeUpdateTimeout: maxFeeUpdateTimeout, + }, nil } // EstimateFeePerKW takes in a target for the number of blocks until an initial @@ -809,7 +825,12 @@ func (w *WebAPIEstimator) Start() error { w.started.Do(func() { log.Infof("Starting web API fee estimator") - w.updateFeeTicker = time.NewTicker(w.randomFeeUpdateTimeout()) + feeUpdateTimeout := w.randomFeeUpdateTimeout() + + log.Infof("Web API fee estimator using update timeout of %v", + feeUpdateTimeout) + + w.updateFeeTicker = time.NewTicker(feeUpdateTimeout) w.updateFeeEstimates() w.wg.Add(1) @@ -852,9 +873,11 @@ func (w *WebAPIEstimator) RelayFeePerKW() SatPerKWeight { // and maxFeeUpdateTimeout that will be used to determine how often the Estimator // should retrieve fresh fees from its API. func (w *WebAPIEstimator) randomFeeUpdateTimeout() time.Duration { - lower := int64(minFeeUpdateTimeout) - upper := int64(maxFeeUpdateTimeout) - return time.Duration(prand.Int63n(upper-lower) + lower) + lower := int64(w.minFeeUpdateTimeout) + upper := int64(w.maxFeeUpdateTimeout) + return time.Duration( + prand.Int63n(upper-lower) + lower, //nolint:gosec + ).Round(time.Second) } // getCachedFee takes a conf target and returns the cached fee rate. When the diff --git a/lnwallet/chainfee/estimator_test.go b/lnwallet/chainfee/estimator_test.go index fc16c9b12..51ab5bf29 100644 --- a/lnwallet/chainfee/estimator_test.go +++ b/lnwallet/chainfee/estimator_test.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "testing" + "time" "github.com/btcsuite/btcd/btcutil" "github.com/stretchr/testify/require" @@ -142,6 +143,9 @@ func TestWebAPIFeeEstimator(t *testing.T) { // Fee rates are in sat/kb. minFeeRate uint32 = 2000 // 500 sat/kw maxFeeRate uint32 = 4000 // 1000 sat/kw + + minFeeUpdateTimeout = 5 * time.Minute + maxFeeUpdateTimeout = 20 * time.Minute ) testCases := []struct { @@ -199,7 +203,9 @@ func TestWebAPIFeeEstimator(t *testing.T) { feeSource := &mockFeeSource{} feeSource.On("GetFeeMap").Return(feeRateResp, nil) - estimator := NewWebAPIEstimator(feeSource, false) + estimator, _ := NewWebAPIEstimator( + feeSource, false, minFeeUpdateTimeout, maxFeeUpdateTimeout, + ) // Test that requesting a fee when no fees have been cached won't fail. feeRate, err := estimator.EstimateFeePerKW(5) @@ -247,10 +253,15 @@ func TestGetCachedFee(t *testing.T) { minFeeRate uint32 = 100 maxFeeRate uint32 = 1000 + + minFeeUpdateTimeout = 5 * time.Minute + maxFeeUpdateTimeout = 20 * time.Minute ) // Create a dummy estimator without WebAPIFeeSource. - estimator := NewWebAPIEstimator(nil, false) + estimator, _ := NewWebAPIEstimator( + nil, false, minFeeUpdateTimeout, maxFeeUpdateTimeout, + ) // When the cache is empty, an error should be returned. cachedFee, err := estimator.getCachedFee(minTarget) @@ -315,3 +326,38 @@ func TestGetCachedFee(t *testing.T) { }) } } + +func TestRandomFeeUpdateTimeout(t *testing.T) { + t.Parallel() + + var ( + minFeeUpdateTimeout = 1 * time.Minute + maxFeeUpdateTimeout = 2 * time.Minute + ) + + estimator, _ := NewWebAPIEstimator( + nil, false, minFeeUpdateTimeout, maxFeeUpdateTimeout, + ) + + for i := 0; i < 1000; i++ { + timeout := estimator.randomFeeUpdateTimeout() + + require.GreaterOrEqual(t, timeout, minFeeUpdateTimeout) + require.LessOrEqual(t, timeout, maxFeeUpdateTimeout) + } +} + +func TestInvalidFeeUpdateTimeout(t *testing.T) { + t.Parallel() + + var ( + minFeeUpdateTimeout = 2 * time.Minute + maxFeeUpdateTimeout = 1 * time.Minute + ) + + _, err := NewWebAPIEstimator( + nil, false, minFeeUpdateTimeout, maxFeeUpdateTimeout, + ) + require.Error(t, err, "NewWebAPIEstimator should return an error "+ + "when minFeeUpdateTimeout > maxFeeUpdateTimeout") +} diff --git a/peer/brontide.go b/peer/brontide.go index 984a52809..1fa6c1311 100644 --- a/peer/brontide.go +++ b/peer/brontide.go @@ -1146,8 +1146,8 @@ func (p *Brontide) addLink(chanPoint *wire.OutPoint, ), BatchSize: p.cfg.ChannelCommitBatchSize, UnsafeReplay: p.cfg.UnsafeReplay, - MinFeeUpdateTimeout: htlcswitch.DefaultMinLinkFeeUpdateTimeout, - MaxFeeUpdateTimeout: htlcswitch.DefaultMaxLinkFeeUpdateTimeout, + MinUpdateTimeout: htlcswitch.DefaultMinLinkFeeUpdateTimeout, + MaxUpdateTimeout: htlcswitch.DefaultMaxLinkFeeUpdateTimeout, OutgoingCltvRejectDelta: p.cfg.OutgoingCltvRejectDelta, TowerClient: p.cfg.TowerClient, MaxOutgoingCltvExpiry: p.cfg.MaxOutgoingCltvExpiry, diff --git a/sample-lnd.conf b/sample-lnd.conf index 25833013f..8a4ca87a4 100644 --- a/sample-lnd.conf +++ b/sample-lnd.conf @@ -305,14 +305,28 @@ ; The default value below is 20 MB (1024 * 1024 * 20) ; blockcachesize=20971520 -; Optional URL for external fee estimation. If no URL is specified, the method -; for fee estimation will depend on the chosen backend and network. Must be set -; for neutrino on mainnet. +; DEPRECATED: Use 'fee.url' option. Optional URL for external fee estimation. +; If no URL is specified, the method for fee estimation will depend on the +; chosen backend and network. Must be set for neutrino on mainnet. ; Default: ; feeurl= ; Example: ; feeurl=https://nodes.lightning.computer/fees/v1/btc-fee-estimates.json +; Optional URL for external fee estimation. If no URL is specified, the method +; for fee estimation will depend on the chosen backend and network. Must be set +; for neutrino on mainnet. +; Default: +; fee.url= +; Example: +; fee.url=https://nodes.lightning.computer/fees/v1/btc-fee-estimates.json + +; The minimum interval in which fees will be updated from the specified fee URL. +; fee.min-update-timeout=5m + +; The maximum interval in which fees will be updated from the specified fee URL. +; fee.max-update-timeout=20m + ; If true, then automatic network bootstrapping will not be attempted. This ; means that your node won't attempt to automatically seek out peers on the ; network. From 6bbbfd3327f188465a2d97e729e87e9444a668a3 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 3 May 2024 13:39:35 +0800 Subject: [PATCH 069/109] docs: add missing fee section sample-lnd.conf --- sample-lnd.conf | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/sample-lnd.conf b/sample-lnd.conf index 8a4ca87a4..2783c58fd 100644 --- a/sample-lnd.conf +++ b/sample-lnd.conf @@ -313,20 +313,6 @@ ; Example: ; feeurl=https://nodes.lightning.computer/fees/v1/btc-fee-estimates.json -; Optional URL for external fee estimation. If no URL is specified, the method -; for fee estimation will depend on the chosen backend and network. Must be set -; for neutrino on mainnet. -; Default: -; fee.url= -; Example: -; fee.url=https://nodes.lightning.computer/fees/v1/btc-fee-estimates.json - -; The minimum interval in which fees will be updated from the specified fee URL. -; fee.min-update-timeout=5m - -; The maximum interval in which fees will be updated from the specified fee URL. -; fee.max-update-timeout=20m - ; If true, then automatic network bootstrapping will not be attempted. This ; means that your node won't attempt to automatically seek out peers on the ; network. @@ -544,6 +530,24 @@ ; the headers of an HTTP request. ; http-header-timeout=5s + +[fee] + +; Optional URL for external fee estimation. If no URL is specified, the method +; for fee estimation will depend on the chosen backend and network. Must be set +; for neutrino on mainnet. +; Default: +; fee.url= +; Example: +; fee.url=https://nodes.lightning.computer/fees/v1/btc-fee-estimates.json + +; The minimum interval in which fees will be updated from the specified fee URL. +; fee.min-update-timeout=5m + +; The maximum interval in which fees will be updated from the specified fee URL. +; fee.max-update-timeout=20m + + [prometheus] ; If true, lnd will start the Prometheus exporter. Prometheus flags are From c8a40b67e9dbac3808f9d0bde69d36e16ede3264 Mon Sep 17 00:00:00 2001 From: Tom Kirkpatrick Date: Fri, 3 May 2024 08:06:49 +0200 Subject: [PATCH 070/109] docs: add missing release notes credit --- docs/release-notes/release-notes-0.18.0.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/release-notes-0.18.0.md b/docs/release-notes/release-notes-0.18.0.md index 5aec2d0da..ca048b84f 100644 --- a/docs/release-notes/release-notes-0.18.0.md +++ b/docs/release-notes/release-notes-0.18.0.md @@ -583,6 +583,7 @@ * testwill * Thabokani * threewebcode +* Tom Kirkpatrick * Turtle * twofaktor * vuittont60 From 187b0b1f80643ea98947a4a5818f004b0ff58ee0 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Mon, 6 May 2024 16:01:35 +0800 Subject: [PATCH 071/109] cli: add `--amp` to `SendPaymentRequest` in `payinvoice` --- cmd/lncli/cmd_payments.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/lncli/cmd_payments.go b/cmd/lncli/cmd_payments.go index 4288b0f01..a554b9dec 100644 --- a/cmd/lncli/cmd_payments.go +++ b/cmd/lncli/cmd_payments.go @@ -886,6 +886,7 @@ func payInvoice(ctx *cli.Context) error { PaymentRequest: stripPrefix(payReq), Amt: ctx.Int64("amt"), DestCustomRecords: make(map[uint64][]byte), + Amp: ctx.Bool(ampFlag.Name), } return sendPaymentRequest(ctx, req) From d4f63662c1103202aa9d307027f08318402afee7 Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Mon, 6 May 2024 19:01:25 +0200 Subject: [PATCH 072/109] invoices: ensure synchronous access to NewTestSqliteDB Add a temporary mutex around the calls to sqldb.NewTestSqliteDB to ensure that only a single thread can access it at a time. This is a temporary work around that can be removed once this race condition in the sqlite repo has been resolved: https://gitlab.com/cznic/sqlite/-/issues/180 --- invoices/invoiceregistry_test.go | 9 +++++++++ invoices/invoices_test.go | 2 ++ 2 files changed, 11 insertions(+) diff --git a/invoices/invoiceregistry_test.go b/invoices/invoiceregistry_test.go index b0c019522..4a76d58aa 100644 --- a/invoices/invoiceregistry_test.go +++ b/invoices/invoiceregistry_test.go @@ -6,6 +6,7 @@ import ( "database/sql" "fmt" "math" + "sync" "testing" "testing/quick" "time" @@ -23,6 +24,12 @@ import ( "github.com/stretchr/testify/require" ) +// sqliteConstructorMu is used to ensure that only one thread can call the +// sqldb.NewTestSqliteDB constructor at a time. This is a temporary workaround +// that can be removed once this race condition in the sqlite repo is resolved: +// https://gitlab.com/cznic/sqlite/-/issues/180 +var sqliteConstructorMu sync.Mutex + // TestInvoiceRegistry is a master test which encompasses all tests using an // InvoiceDB instance. The purpose of this test is to be able to run all tests // with a custom DB instance, so that we can test the same logic with different @@ -130,7 +137,9 @@ func TestInvoiceRegistry(t *testing.T) { var db *sqldb.BaseDB if sqlite { + sqliteConstructorMu.Lock() db = sqldb.NewTestSqliteDB(t).BaseDB + sqliteConstructorMu.Unlock() } else { db = sqldb.NewTestPostgresDB(t, pgFixture).BaseDB } diff --git a/invoices/invoices_test.go b/invoices/invoices_test.go index c9e204571..71da38571 100644 --- a/invoices/invoices_test.go +++ b/invoices/invoices_test.go @@ -234,7 +234,9 @@ func TestInvoices(t *testing.T) { makeSQLDB := func(t *testing.T, sqlite bool) invpkg.InvoiceDB { var db *sqldb.BaseDB if sqlite { + sqliteConstructorMu.Lock() db = sqldb.NewTestSqliteDB(t).BaseDB + sqliteConstructorMu.Unlock() } else { db = sqldb.NewTestPostgresDB(t, pgFixture).BaseDB } From 954ad4a32999562f22cb4c33c16bc78a7606d273 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 6 May 2024 18:10:52 -0700 Subject: [PATCH 073/109] build: bump version to v0.18.0-beta.rc2 --- build/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/version.go b/build/version.go index 62aece381..9ff734a2b 100644 --- a/build/version.go +++ b/build/version.go @@ -47,7 +47,7 @@ const ( // AppPreRelease MUST only contain characters from semanticAlphabet per // the semantic versioning spec. - AppPreRelease = "beta.rc1" + AppPreRelease = "beta.rc2" ) func init() { From af9858c3ede636eae87b9408442c0ba64c253f7e Mon Sep 17 00:00:00 2001 From: Bufo Date: Tue, 7 May 2024 18:58:25 +0200 Subject: [PATCH 074/109] feat: add inbound fees to channel notifications --- docs/release-notes/release-notes-0.18.0.md | 4 +++ routing/notifications.go | 6 ++++ routing/notifications_test.go | 26 ++++++++++++++--- rpcserver.go | 33 ++++++++++++++++++---- 4 files changed, 59 insertions(+), 10 deletions(-) diff --git a/docs/release-notes/release-notes-0.18.0.md b/docs/release-notes/release-notes-0.18.0.md index 7e9f1e616..12b685662 100644 --- a/docs/release-notes/release-notes-0.18.0.md +++ b/docs/release-notes/release-notes-0.18.0.md @@ -301,6 +301,9 @@ maintain a healthy connection to the network by checking the number of outbound peers if they are below 6. +* [Add inbound fees](https://github.com/lightningnetwork/lnd/pull/8723) to + `subscribeChannelGraph`. + ### Logging * [Add the htlc amount](https://github.com/lightningnetwork/lnd/pull/8156) to contract court logs in case of timed-out HTLCs in order to easily spot dust @@ -533,6 +536,7 @@ * BitcoinerCoderBob * bitromortac * bota87 +* Bufo * Calvin Zachman * Carla Kirk-Cohen * cristiantroy diff --git a/routing/notifications.go b/routing/notifications.go index 9d6c4b51f..3afbb1533 100644 --- a/routing/notifications.go +++ b/routing/notifications.go @@ -301,6 +301,11 @@ type ChannelEdgeUpdate struct { // Disabled, if true, signals that the channel is unavailable to relay // payments. Disabled bool + + // ExtraOpaqueData is the set of data that was appended to this message + // to fill out the full maximum transport message size. These fields can + // be used to specify optional data such as custom TLV fields. + ExtraOpaqueData lnwire.ExtraOpaqueData } // appendTopologyChange appends the passed update message to the passed @@ -379,6 +384,7 @@ func addToTopologyChange(graph *channeldb.ChannelGraph, update *TopologyChange, AdvertisingNode: aNode, ConnectingNode: cNode, Disabled: m.ChannelFlags&lnwire.ChanUpdateDisabled != 0, + ExtraOpaqueData: m.ExtraOpaqueData, } // TODO(roasbeef): add bit to toggle diff --git a/routing/notifications_test.go b/routing/notifications_test.go index 48b0a2766..4e095649b 100644 --- a/routing/notifications_test.go +++ b/routing/notifications_test.go @@ -75,7 +75,18 @@ func createTestNode() (*channeldb.LightningNode, error) { } func randEdgePolicy(chanID *lnwire.ShortChannelID, - node *channeldb.LightningNode) *models.ChannelEdgePolicy { + node *channeldb.LightningNode) (*models.ChannelEdgePolicy, error) { + + InboundFee := models.InboundFee{ + Base: prand.Int31() * -1, + Rate: prand.Int31() * -1, + } + inboundFee := InboundFee.ToWire() + + var extraOpaqueData lnwire.ExtraOpaqueData + if err := extraOpaqueData.PackRecords(&inboundFee); err != nil { + return nil, err + } return &models.ChannelEdgePolicy{ SigBytes: testSig.Serialize(), @@ -87,7 +98,8 @@ func randEdgePolicy(chanID *lnwire.ShortChannelID, FeeBaseMSat: lnwire.MilliSatoshi(prand.Int31()), FeeProportionalMillionths: lnwire.MilliSatoshi(prand.Int31()), ToNode: node.PubKeyBytes, - } + ExtraOpaqueData: extraOpaqueData, + }, nil } func createChannelEdge(ctx *testCtx, bitcoinKey1, bitcoinKey2 []byte, @@ -457,9 +469,12 @@ func TestEdgeUpdateNotification(t *testing.T) { // Create random policy edges that are stemmed to the channel id // created above. - edge1 := randEdgePolicy(chanID, node1) + edge1, err := randEdgePolicy(chanID, node1) + require.NoError(t, err, "unable to create a random chan policy") edge1.ChannelFlags = 0 - edge2 := randEdgePolicy(chanID, node2) + + edge2, err := randEdgePolicy(chanID, node2) + require.NoError(t, err, "unable to create a random chan policy") edge2.ChannelFlags = 1 if err := ctx.router.UpdateEdge(edge1); err != nil { @@ -511,6 +526,9 @@ func TestEdgeUpdateNotification(t *testing.T) { "expected %v, got %v", edgeAnn.TimeLockDelta, edgeUpdate.TimeLockDelta) } + require.Equal( + t, edgeAnn.ExtraOpaqueData, edgeUpdate.ExtraOpaqueData, + ) } // Create lookup map for notifications we are intending to receive. Entries diff --git a/rpcserver.go b/rpcserver.go index e4e8f50ee..1e9f0be08 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -6691,6 +6691,14 @@ func marshallTopologyChange(topChange *routing.TopologyChange) *lnrpc.GraphTopol channelUpdates := make([]*lnrpc.ChannelEdgeUpdate, len(topChange.ChannelEdgeUpdates)) for i, channelUpdate := range topChange.ChannelEdgeUpdates { + + customRecords := marshalExtraOpaqueData( + channelUpdate.ExtraOpaqueData, + ) + inboundFee := extractInboundFeeSafe( + channelUpdate.ExtraOpaqueData, + ) + channelUpdates[i] = &lnrpc.ChannelEdgeUpdate{ ChanId: channelUpdate.ChanID, ChanPoint: &lnrpc.ChannelPoint{ @@ -6701,12 +6709,25 @@ func marshallTopologyChange(topChange *routing.TopologyChange) *lnrpc.GraphTopol }, Capacity: int64(channelUpdate.Capacity), RoutingPolicy: &lnrpc.RoutingPolicy{ - TimeLockDelta: uint32(channelUpdate.TimeLockDelta), - MinHtlc: int64(channelUpdate.MinHTLC), - MaxHtlcMsat: uint64(channelUpdate.MaxHTLC), - FeeBaseMsat: int64(channelUpdate.BaseFee), - FeeRateMilliMsat: int64(channelUpdate.FeeRate), - Disabled: channelUpdate.Disabled, + TimeLockDelta: uint32( + channelUpdate.TimeLockDelta, + ), + MinHtlc: int64( + channelUpdate.MinHTLC, + ), + MaxHtlcMsat: uint64( + channelUpdate.MaxHTLC, + ), + FeeBaseMsat: int64( + channelUpdate.BaseFee, + ), + FeeRateMilliMsat: int64( + channelUpdate.FeeRate, + ), + Disabled: channelUpdate.Disabled, + InboundFeeBaseMsat: inboundFee.BaseFee, + InboundFeeRateMilliMsat: inboundFee.FeeRate, + CustomRecords: customRecords, }, AdvertisingNode: encodeKey(channelUpdate.AdvertisingNode), ConnectingNode: encodeKey(channelUpdate.ConnectingNode), From c577dae372c3f337d9750a60d53a13b2fb4338c8 Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Wed, 8 May 2024 09:25:19 +0200 Subject: [PATCH 075/109] makefile+dev.Dockerfile: add install-all command Add a new `make install-all` command that will perform all `make install` actions along with generating the manpages. The `manpages` command is then removed from the existing `make install` command. The docker build is then updated to use the new `make install-all` command. This is done because some users running `make install` may be doing so in environments where they do not have write access to the directory where the man pages need to be written to. --- Makefile | 9 +++++++-- dev.Dockerfile | 2 +- docs/release-notes/release-notes-0.18.0.md | 4 +++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 33dd4e528..5ea087892 100644 --- a/Makefile +++ b/Makefile @@ -136,8 +136,13 @@ manpages: @$(call print, "Generating man pages lncli.1 and lnd.1.") ./scripts/gen_man_pages.sh $(DESTDIR) $(PREFIX) -#? install: Build and install lnd and lncli binaries, place them in $GOPATH/bin, generate and install man pages -install: install-binaries manpages +#? install: Build and install lnd and lncli binaries and place them in $GOPATH/bin. +install: install-binaries + +#? install-all: Performs all the same tasks as the install command along with generating and +# installing the man pages for the lnd and lncli binaries. This command is useful in an +# environment where a user has root access and so has write access to the man page directory. +install-all: install manpages #? release-install: Build and install lnd and lncli release binaries, place them in $GOPATH/bin release-install: diff --git a/dev.Dockerfile b/dev.Dockerfile index d3ef269de..bb7c67312 100644 --- a/dev.Dockerfile +++ b/dev.Dockerfile @@ -24,7 +24,7 @@ COPY . /go/src/github.com/lightningnetwork/lnd # Install/build lnd. RUN cd /go/src/github.com/lightningnetwork/lnd \ && make \ -&& make install tags="signrpc walletrpc chainrpc invoicesrpc peersrpc" +&& make install-all tags="signrpc walletrpc chainrpc invoicesrpc peersrpc" # Start a new, final image to reduce size. FROM alpine as final diff --git a/docs/release-notes/release-notes-0.18.0.md b/docs/release-notes/release-notes-0.18.0.md index ca048b84f..7628726ef 100644 --- a/docs/release-notes/release-notes-0.18.0.md +++ b/docs/release-notes/release-notes-0.18.0.md @@ -284,7 +284,9 @@ * [Man pages](https://github.com/lightningnetwork/lnd/pull/8525) Generate man pages automatically using `lncli generatemanpage` command for both `lncli` - and `lnd` commands when running `make install` in the Makefile. + and `lnd` commands when running + [`make install-all`](https://github.com/lightningnetwork/lnd/pull/8739) in + the Makefile. # Improvements ## Functional Updates From 389ecb535ba500693ebe4071545ef4dbe531efdc Mon Sep 17 00:00:00 2001 From: Ononiwu Maureen Date: Thu, 14 Mar 2024 14:45:27 +0100 Subject: [PATCH 076/109] peer: Change `createTestPeer` name. In this function `createTestPeer` is changed to `createTestPeerWithChannel`. This is useful in coming commits where we decouple the process of creating test peer from the function. Signed-off-by: Ononiwu Maureen --- peer/brontide_test.go | 36 +++++++++++++++++++----------------- peer/test_utils.go | 15 ++++++++------- 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/peer/brontide_test.go b/peer/brontide_test.go index 8ea8846b2..5772e9679 100644 --- a/peer/brontide_test.go +++ b/peer/brontide_test.go @@ -48,7 +48,7 @@ func TestPeerChannelClosureShutdownResponseLinkRemoved(t *testing.T) { mockSwitch := &mockMessageSwitch{} - alicePeer, bobChan, err := createTestPeer( + alicePeer, bobChan, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(t, err, "unable to create test channels") @@ -96,7 +96,7 @@ func TestPeerChannelClosureAcceptFeeResponder(t *testing.T) { mockSwitch := &mockMessageSwitch{} - alicePeer, bobChan, err := createTestPeer( + alicePeer, bobChan, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(t, err, "unable to create test channels") @@ -201,7 +201,7 @@ func TestPeerChannelClosureAcceptFeeInitiator(t *testing.T) { mockSwitch := &mockMessageSwitch{} - alicePeer, bobChan, err := createTestPeer( + alicePeer, bobChan, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(t, err, "unable to create test channels") @@ -325,7 +325,7 @@ func TestPeerChannelClosureFeeNegotiationsResponder(t *testing.T) { mockSwitch := &mockMessageSwitch{} - alicePeer, bobChan, err := createTestPeer( + alicePeer, bobChan, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(t, err, "unable to create test channels") @@ -512,7 +512,7 @@ func TestPeerChannelClosureFeeNegotiationsInitiator(t *testing.T) { mockSwitch := &mockMessageSwitch{} - alicePeer, bobChan, err := createTestPeer( + alicePeer, bobChan, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(t, err, "unable to create test channels") @@ -840,7 +840,7 @@ func TestCustomShutdownScript(t *testing.T) { mockSwitch := &mockMessageSwitch{} // Open a channel. - alicePeer, bobChan, err := createTestPeer( + alicePeer, bobChan, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, test.update, mockSwitch, ) @@ -1195,7 +1195,7 @@ func TestUpdateNextRevocation(t *testing.T) { broadcastTxChan := make(chan *wire.MsgTx) mockSwitch := &mockMessageSwitch{} - alicePeer, bobChan, err := createTestPeer( + alicePeer, bobChan, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(err, "unable to create test channels") @@ -1412,7 +1412,7 @@ func TestHandleRemovePendingChannel(t *testing.T) { func TestStartupWriteMessageRace(t *testing.T) { t.Parallel() - // Set up parameters for createTestPeer. + // Set up parameters for createTestPeerWithChannel. notifier := &mock.ChainNotifier{ SpendChan: make(chan *chainntnfs.SpendDetail), EpochChan: make(chan *chainntnfs.BlockEpoch), @@ -1421,17 +1421,18 @@ func TestStartupWriteMessageRace(t *testing.T) { broadcastTxChan := make(chan *wire.MsgTx) mockSwitch := &mockMessageSwitch{} - // Use a callback to extract the channel created by createTestPeer, so - // we can mark it borked below. We can't mark it borked within the - // callback, since the channel hasn't been saved to the DB yet when the - // callback executes. + // Use a callback to extract the channel created by + // createTestPeerWithChannel, so we can mark it borked below. + // We can't mark it borked within the callback, since the channel hasn't + // been saved to the DB yet when the callback executes. var channel *channeldb.OpenChannel getChannels := func(a, b *channeldb.OpenChannel) { channel = a } - // createTestPeer creates a peer and a channel with that peer. - peer, _, err := createTestPeer( + // createTestPeerWithChannel creates a peer and a channel with that + // peer. + peer, _, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, getChannels, mockSwitch, ) require.NoError(t, err, "unable to create test channel") @@ -1516,7 +1517,7 @@ func TestStartupWriteMessageRace(t *testing.T) { func TestRemovePendingChannel(t *testing.T) { t.Parallel() - // Set up parameters for createTestPeer. + // Set up parameters for createTestPeerWithChannel. notifier := &mock.ChainNotifier{ SpendChan: make(chan *chainntnfs.SpendDetail), EpochChan: make(chan *chainntnfs.BlockEpoch), @@ -1525,8 +1526,9 @@ func TestRemovePendingChannel(t *testing.T) { broadcastTxChan := make(chan *wire.MsgTx) mockSwitch := &mockMessageSwitch{} - // createTestPeer creates a peer and a channel with that peer. - peer, _, err := createTestPeer( + // createTestPeerWithChannel creates a peer and a channel with that + // peer. + peer, _, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(t, err, "unable to create test channel") diff --git a/peer/test_utils.go b/peer/test_utils.go index 05bfe6ad4..5080043a2 100644 --- a/peer/test_utils.go +++ b/peer/test_utils.go @@ -48,15 +48,16 @@ var ( testKeyLoc = keychain.KeyLocator{Family: keychain.KeyFamilyNodeKey} ) -// noUpdate is a function which can be used as a parameter in createTestPeer to -// call the setup code with no custom values on the channels set up. +// noUpdate is a function which can be used as a parameter in +// createTestPeerWithChannel to call the setup code with no custom values on +// the channels set up. var noUpdate = func(a, b *channeldb.OpenChannel) {} -// createTestPeer creates a channel between two nodes, and returns a peer for -// one of the nodes, together with the channel seen from both nodes. It takes -// an updateChan function which can be used to modify the default values on -// the channel states for each peer. -func createTestPeer(t *testing.T, notifier chainntnfs.ChainNotifier, +// createTestPeerWithChannel creates a channel between two nodes, and returns a +// peer for one of the nodes, together with the channel seen from both nodes. +// It takes an updateChan function which can be used to modify the default +// values on the channel states for each peer. +func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, publTx chan *wire.MsgTx, updateChan func(a, b *channeldb.OpenChannel), mockSwitch *mockMessageSwitch) ( *Brontide, *lnwallet.LightningChannel, error) { From 536c69b7939991b7974c9dcdcf465ade7610019f Mon Sep 17 00:00:00 2001 From: Ononiwu Maureen Date: Thu, 14 Mar 2024 15:43:12 +0100 Subject: [PATCH 077/109] peer: `createTestPeerWithChannel` returns a struct The `createTestPeerWithChannel` function is made to return this newly created struct and error. This is useful because upcoming commits would require us returning more objects from the function. Signed-off-by: Ononiwu Maureen --- peer/brontide_test.go | 47 +++++++++++++++++++++++++++++++++---------- peer/test_utils.go | 46 +++++++++++++++++++++++++----------------- 2 files changed, 63 insertions(+), 30 deletions(-) diff --git a/peer/brontide_test.go b/peer/brontide_test.go index 5772e9679..270085674 100644 --- a/peer/brontide_test.go +++ b/peer/brontide_test.go @@ -48,11 +48,14 @@ func TestPeerChannelClosureShutdownResponseLinkRemoved(t *testing.T) { mockSwitch := &mockMessageSwitch{} - alicePeer, bobChan, err := createTestPeerWithChannel( + harness, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(t, err, "unable to create test channels") + alicePeer := harness.peer + bobChan := harness.channel + chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -96,11 +99,14 @@ func TestPeerChannelClosureAcceptFeeResponder(t *testing.T) { mockSwitch := &mockMessageSwitch{} - alicePeer, bobChan, err := createTestPeerWithChannel( + harness, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(t, err, "unable to create test channels") + alicePeer := harness.peer + bobChan := harness.channel + chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -201,11 +207,14 @@ func TestPeerChannelClosureAcceptFeeInitiator(t *testing.T) { mockSwitch := &mockMessageSwitch{} - alicePeer, bobChan, err := createTestPeerWithChannel( + harness, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(t, err, "unable to create test channels") + bobChan := harness.channel + alicePeer := harness.peer + chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) mockLink := newMockUpdateHandler(chanID) @@ -325,11 +334,14 @@ func TestPeerChannelClosureFeeNegotiationsResponder(t *testing.T) { mockSwitch := &mockMessageSwitch{} - alicePeer, bobChan, err := createTestPeerWithChannel( + harness, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(t, err, "unable to create test channels") + bobChan := harness.channel + alicePeer := harness.peer + chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -512,11 +524,14 @@ func TestPeerChannelClosureFeeNegotiationsInitiator(t *testing.T) { mockSwitch := &mockMessageSwitch{} - alicePeer, bobChan, err := createTestPeerWithChannel( + harness, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(t, err, "unable to create test channels") + alicePeer := harness.peer + bobChan := harness.channel + chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) mockLink := newMockUpdateHandler(chanID) @@ -840,7 +855,7 @@ func TestCustomShutdownScript(t *testing.T) { mockSwitch := &mockMessageSwitch{} // Open a channel. - alicePeer, bobChan, err := createTestPeerWithChannel( + harness, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, test.update, mockSwitch, ) @@ -848,13 +863,16 @@ func TestCustomShutdownScript(t *testing.T) { t.Fatalf("unable to create test channels: %v", err) } + alicePeer := harness.peer + bobChan := harness.channel + chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) mockLink := newMockUpdateHandler(chanID) mockSwitch.links = append(mockSwitch.links, mockLink) - // Request initiator to cooperatively close the channel, with - // a specified delivery address. + // Request initiator to cooperatively close the channel, + // with a specified delivery address. updateChan := make(chan interface{}, 1) errChan := make(chan error, 1) closeCommand := htlcswitch.ChanClose{ @@ -1195,11 +1213,14 @@ func TestUpdateNextRevocation(t *testing.T) { broadcastTxChan := make(chan *wire.MsgTx) mockSwitch := &mockMessageSwitch{} - alicePeer, bobChan, err := createTestPeerWithChannel( + harness, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(err, "unable to create test channels") + bobChan := harness.channel + alicePeer := harness.peer + // testChannel is used to test the updateNextRevocation function. testChannel := bobChan.State() @@ -1432,11 +1453,13 @@ func TestStartupWriteMessageRace(t *testing.T) { // createTestPeerWithChannel creates a peer and a channel with that // peer. - peer, _, err := createTestPeerWithChannel( + harness, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, getChannels, mockSwitch, ) require.NoError(t, err, "unable to create test channel") + peer := harness.peer + // Avoid the need to mock the channel graph by marking the channel // borked. Borked channels still get a reestablish message sent on // reconnect, while skipping channel graph checks and link creation. @@ -1528,11 +1551,13 @@ func TestRemovePendingChannel(t *testing.T) { // createTestPeerWithChannel creates a peer and a channel with that // peer. - peer, _, err := createTestPeerWithChannel( + harness, err := createTestPeerWithChannel( t, notifier, broadcastTxChan, noUpdate, mockSwitch, ) require.NoError(t, err, "unable to create test channel") + peer := harness.peer + // Add a pending channel to the peer Alice. errChan := make(chan error, 1) pendingChanID := lnwire.ChannelID{1} diff --git a/peer/test_utils.go b/peer/test_utils.go index 5080043a2..2f8f17bb7 100644 --- a/peer/test_utils.go +++ b/peer/test_utils.go @@ -53,6 +53,11 @@ var ( // the channels set up. var noUpdate = func(a, b *channeldb.OpenChannel) {} +type peerTestCtx struct { + peer *Brontide + channel *lnwallet.LightningChannel +} + // createTestPeerWithChannel creates a channel between two nodes, and returns a // peer for one of the nodes, together with the channel seen from both nodes. // It takes an updateChan function which can be used to modify the default @@ -60,7 +65,7 @@ var noUpdate = func(a, b *channeldb.OpenChannel) {} func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, publTx chan *wire.MsgTx, updateChan func(a, b *channeldb.OpenChannel), mockSwitch *mockMessageSwitch) ( - *Brontide, *lnwallet.LightningChannel, error) { + *peerTestCtx, error) { nodeKeyLocator := keychain.KeyLocator{ Family: keychain.KeyFamilyNodeKey, @@ -142,23 +147,23 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, bobRoot, err := chainhash.NewHash(bobKeyPriv.Serialize()) if err != nil { - return nil, nil, err + return nil, err } bobPreimageProducer := shachain.NewRevocationProducer(*bobRoot) bobFirstRevoke, err := bobPreimageProducer.AtIndex(0) if err != nil { - return nil, nil, err + return nil, err } bobCommitPoint := input.ComputeCommitmentPoint(bobFirstRevoke[:]) aliceRoot, err := chainhash.NewHash(aliceKeyPriv.Serialize()) if err != nil { - return nil, nil, err + return nil, err } alicePreimageProducer := shachain.NewRevocationProducer(*aliceRoot) aliceFirstRevoke, err := alicePreimageProducer.AtIndex(0) if err != nil { - return nil, nil, err + return nil, err } aliceCommitPoint := input.ComputeCommitmentPoint(aliceFirstRevoke[:]) @@ -168,12 +173,12 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, isAliceInitiator, 0, ) if err != nil { - return nil, nil, err + return nil, err } dbAlice, err := channeldb.Open(t.TempDir()) if err != nil { - return nil, nil, err + return nil, err } t.Cleanup(func() { require.NoError(t, dbAlice.Close()) @@ -181,7 +186,7 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, dbBob, err := channeldb.Open(t.TempDir()) if err != nil { - return nil, nil, err + return nil, err } t.Cleanup(func() { require.NoError(t, dbBob.Close()) @@ -190,7 +195,7 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, estimator := chainfee.NewStaticEstimator(12500, 0) feePerKw, err := estimator.EstimateFeePerKW(1) if err != nil { - return nil, nil, err + return nil, err } // TODO(roasbeef): need to factor in commit fee? @@ -215,7 +220,7 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, var chanIDBytes [8]byte if _, err := io.ReadFull(crand.Reader, chanIDBytes[:]); err != nil { - return nil, nil, err + return nil, err } shortChanID := lnwire.NewShortChanIDFromInt( @@ -266,7 +271,7 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, } if err := aliceChannelState.SyncPending(aliceAddr, 0); err != nil { - return nil, nil, err + return nil, err } bobAddr := &net.TCPAddr{ @@ -275,7 +280,7 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, } if err := bobChannelState.SyncPending(bobAddr, 0); err != nil { - return nil, nil, err + return nil, err } aliceSigner := input.NewMockSigner( @@ -290,7 +295,7 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, aliceSigner, aliceChannelState, alicePool, ) if err != nil { - return nil, nil, err + return nil, err } _ = alicePool.Start() t.Cleanup(func() { @@ -302,7 +307,7 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, bobSigner, bobChannelState, bobPool, ) if err != nil { - return nil, nil, err + return nil, err } _ = bobPool.Start() t.Cleanup(func() { @@ -346,15 +351,15 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, }, }) if err != nil { - return nil, nil, err + return nil, err } if err = chanStatusMgr.Start(); err != nil { - return nil, nil, err + return nil, err } errBuffer, err := queue.NewCircularBuffer(ErrorBufferSize) if err != nil { - return nil, nil, err + return nil, err } var pubKey [33]byte @@ -381,7 +386,7 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, }, ) if err != nil { - return nil, nil, err + return nil, err } // TODO(yy): change ChannelNotifier to be an interface. @@ -419,7 +424,10 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, alicePeer.wg.Add(1) go alicePeer.channelManager() - return alicePeer, channelBob, nil + return &peerTestCtx{ + peer: alicePeer, + channel: channelBob, + }, nil } // mockMessageSwitch is a mock implementation of the messageSwitch interface From 8f76c5eeef1cddf9232e6a5f26df8bd558f0e513 Mon Sep 17 00:00:00 2001 From: Ononiwu Maureen Date: Fri, 15 Mar 2024 10:59:48 +0100 Subject: [PATCH 078/109] peer: Create mockswitch, publTx, notifier in .. test_utils Signed-off-by: Ononiwu Maureen --- peer/brontide_test.go | 133 ++++++++---------------------------------- peer/test_utils.go | 34 ++++++++--- 2 files changed, 48 insertions(+), 119 deletions(-) diff --git a/peer/brontide_test.go b/peer/brontide_test.go index 270085674..11a38e124 100644 --- a/peer/brontide_test.go +++ b/peer/brontide_test.go @@ -39,18 +39,7 @@ var ( func TestPeerChannelClosureShutdownResponseLinkRemoved(t *testing.T) { t.Parallel() - notifier := &mock.ChainNotifier{ - SpendChan: make(chan *chainntnfs.SpendDetail), - EpochChan: make(chan *chainntnfs.BlockEpoch), - ConfChan: make(chan *chainntnfs.TxConfirmation), - } - broadcastTxChan := make(chan *wire.MsgTx) - - mockSwitch := &mockMessageSwitch{} - - harness, err := createTestPeerWithChannel( - t, notifier, broadcastTxChan, noUpdate, mockSwitch, - ) + harness, err := createTestPeerWithChannel(t, noUpdate) require.NoError(t, err, "unable to create test channels") alicePeer := harness.peer @@ -90,22 +79,14 @@ func TestPeerChannelClosureShutdownResponseLinkRemoved(t *testing.T) { func TestPeerChannelClosureAcceptFeeResponder(t *testing.T) { t.Parallel() - notifier := &mock.ChainNotifier{ - SpendChan: make(chan *chainntnfs.SpendDetail), - EpochChan: make(chan *chainntnfs.BlockEpoch), - ConfChan: make(chan *chainntnfs.TxConfirmation), - } - broadcastTxChan := make(chan *wire.MsgTx) - - mockSwitch := &mockMessageSwitch{} - - harness, err := createTestPeerWithChannel( - t, notifier, broadcastTxChan, noUpdate, mockSwitch, - ) + harness, err := createTestPeerWithChannel(t, noUpdate) require.NoError(t, err, "unable to create test channels") alicePeer := harness.peer bobChan := harness.channel + mockSwitch := harness.mockSwitch + broadcastTxChan := harness.publishTx + notifier := harness.notifier chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -198,22 +179,14 @@ func TestPeerChannelClosureAcceptFeeResponder(t *testing.T) { func TestPeerChannelClosureAcceptFeeInitiator(t *testing.T) { t.Parallel() - notifier := &mock.ChainNotifier{ - SpendChan: make(chan *chainntnfs.SpendDetail), - EpochChan: make(chan *chainntnfs.BlockEpoch), - ConfChan: make(chan *chainntnfs.TxConfirmation), - } - broadcastTxChan := make(chan *wire.MsgTx) - - mockSwitch := &mockMessageSwitch{} - - harness, err := createTestPeerWithChannel( - t, notifier, broadcastTxChan, noUpdate, mockSwitch, - ) + harness, err := createTestPeerWithChannel(t, noUpdate) require.NoError(t, err, "unable to create test channels") bobChan := harness.channel alicePeer := harness.peer + mockSwitch := harness.mockSwitch + broadcastTxChan := harness.publishTx + notifier := harness.notifier chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -325,22 +298,14 @@ func TestPeerChannelClosureAcceptFeeInitiator(t *testing.T) { func TestPeerChannelClosureFeeNegotiationsResponder(t *testing.T) { t.Parallel() - notifier := &mock.ChainNotifier{ - SpendChan: make(chan *chainntnfs.SpendDetail), - EpochChan: make(chan *chainntnfs.BlockEpoch), - ConfChan: make(chan *chainntnfs.TxConfirmation), - } - broadcastTxChan := make(chan *wire.MsgTx) - - mockSwitch := &mockMessageSwitch{} - - harness, err := createTestPeerWithChannel( - t, notifier, broadcastTxChan, noUpdate, mockSwitch, - ) + harness, err := createTestPeerWithChannel(t, noUpdate) require.NoError(t, err, "unable to create test channels") bobChan := harness.channel alicePeer := harness.peer + mockSwitch := harness.mockSwitch + broadcastTxChan := harness.publishTx + notifier := harness.notifier chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -515,22 +480,14 @@ func TestPeerChannelClosureFeeNegotiationsResponder(t *testing.T) { func TestPeerChannelClosureFeeNegotiationsInitiator(t *testing.T) { t.Parallel() - notifier := &mock.ChainNotifier{ - SpendChan: make(chan *chainntnfs.SpendDetail), - EpochChan: make(chan *chainntnfs.BlockEpoch), - ConfChan: make(chan *chainntnfs.TxConfirmation), - } - broadcastTxChan := make(chan *wire.MsgTx) - - mockSwitch := &mockMessageSwitch{} - - harness, err := createTestPeerWithChannel( - t, notifier, broadcastTxChan, noUpdate, mockSwitch, - ) + harness, err := createTestPeerWithChannel(t, noUpdate) require.NoError(t, err, "unable to create test channels") alicePeer := harness.peer bobChan := harness.channel + mockSwitch := harness.mockSwitch + broadcastTxChan := harness.publishTx + notifier := harness.notifier chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -845,19 +802,9 @@ func TestCustomShutdownScript(t *testing.T) { test := test t.Run(test.name, func(t *testing.T) { - notifier := &mock.ChainNotifier{ - SpendChan: make(chan *chainntnfs.SpendDetail), - EpochChan: make(chan *chainntnfs.BlockEpoch), - ConfChan: make(chan *chainntnfs.TxConfirmation), - } - broadcastTxChan := make(chan *wire.MsgTx) - - mockSwitch := &mockMessageSwitch{} - // Open a channel. harness, err := createTestPeerWithChannel( - t, notifier, broadcastTxChan, test.update, - mockSwitch, + t, test.update, ) if err != nil { t.Fatalf("unable to create test channels: %v", err) @@ -865,6 +812,7 @@ func TestCustomShutdownScript(t *testing.T) { alicePeer := harness.peer bobChan := harness.channel + mockSwitch := harness.mockSwitch chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -1203,19 +1151,7 @@ func TestUpdateNextRevocation(t *testing.T) { require := require.New(t) - // TODO(yy): create interface for lnwallet.LightningChannel so we can - // easily mock it without the following setups. - notifier := &mock.ChainNotifier{ - SpendChan: make(chan *chainntnfs.SpendDetail), - EpochChan: make(chan *chainntnfs.BlockEpoch), - ConfChan: make(chan *chainntnfs.TxConfirmation), - } - broadcastTxChan := make(chan *wire.MsgTx) - mockSwitch := &mockMessageSwitch{} - - harness, err := createTestPeerWithChannel( - t, notifier, broadcastTxChan, noUpdate, mockSwitch, - ) + harness, err := createTestPeerWithChannel(t, noUpdate) require.NoError(err, "unable to create test channels") bobChan := harness.channel @@ -1433,15 +1369,6 @@ func TestHandleRemovePendingChannel(t *testing.T) { func TestStartupWriteMessageRace(t *testing.T) { t.Parallel() - // Set up parameters for createTestPeerWithChannel. - notifier := &mock.ChainNotifier{ - SpendChan: make(chan *chainntnfs.SpendDetail), - EpochChan: make(chan *chainntnfs.BlockEpoch), - ConfChan: make(chan *chainntnfs.TxConfirmation), - } - broadcastTxChan := make(chan *wire.MsgTx) - mockSwitch := &mockMessageSwitch{} - // Use a callback to extract the channel created by // createTestPeerWithChannel, so we can mark it borked below. // We can't mark it borked within the callback, since the channel hasn't @@ -1453,9 +1380,7 @@ func TestStartupWriteMessageRace(t *testing.T) { // createTestPeerWithChannel creates a peer and a channel with that // peer. - harness, err := createTestPeerWithChannel( - t, notifier, broadcastTxChan, getChannels, mockSwitch, - ) + harness, err := createTestPeerWithChannel(t, getChannels) require.NoError(t, err, "unable to create test channel") peer := harness.peer @@ -1540,20 +1465,8 @@ func TestStartupWriteMessageRace(t *testing.T) { func TestRemovePendingChannel(t *testing.T) { t.Parallel() - // Set up parameters for createTestPeerWithChannel. - notifier := &mock.ChainNotifier{ - SpendChan: make(chan *chainntnfs.SpendDetail), - EpochChan: make(chan *chainntnfs.BlockEpoch), - ConfChan: make(chan *chainntnfs.TxConfirmation), - } - broadcastTxChan := make(chan *wire.MsgTx) - mockSwitch := &mockMessageSwitch{} - - // createTestPeerWithChannel creates a peer and a channel with that - // peer. - harness, err := createTestPeerWithChannel( - t, notifier, broadcastTxChan, noUpdate, mockSwitch, - ) + // createTestPeerWithChannel creates a peer and a channel. + harness, err := createTestPeerWithChannel(t, noUpdate) require.NoError(t, err, "unable to create test channel") peer := harness.peer diff --git a/peer/test_utils.go b/peer/test_utils.go index 2f8f17bb7..c872d0313 100644 --- a/peer/test_utils.go +++ b/peer/test_utils.go @@ -54,18 +54,31 @@ var ( var noUpdate = func(a, b *channeldb.OpenChannel) {} type peerTestCtx struct { - peer *Brontide - channel *lnwallet.LightningChannel + peer *Brontide + channel *lnwallet.LightningChannel + notifier *mock.ChainNotifier + publishTx <-chan *wire.MsgTx + mockSwitch *mockMessageSwitch } // createTestPeerWithChannel creates a channel between two nodes, and returns a // peer for one of the nodes, together with the channel seen from both nodes. // It takes an updateChan function which can be used to modify the default // values on the channel states for each peer. -func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, - publTx chan *wire.MsgTx, updateChan func(a, b *channeldb.OpenChannel), - mockSwitch *mockMessageSwitch) ( - *peerTestCtx, error) { +func createTestPeerWithChannel(t *testing.T, updateChan func(a, + b *channeldb.OpenChannel)) (*peerTestCtx, error) { + + // TODO(yy): create interface for lnwallet.LightningChannel so we can + // easily mock it without the following setups. + notifier := &mock.ChainNotifier{ + SpendChan: make(chan *chainntnfs.SpendDetail), + EpochChan: make(chan *chainntnfs.BlockEpoch), + ConfChan: make(chan *chainntnfs.TxConfirmation), + } + + var mockSwitch *mockMessageSwitch + + publishTx := make(chan *wire.MsgTx) nodeKeyLocator := keychain.KeyLocator{ Family: keychain.KeyFamilyNodeKey, @@ -320,7 +333,7 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, wallet := &lnwallet.LightningWallet{ WalletController: &mock.WalletController{ RootKey: aliceKeyPriv, - PublishedTransactions: publTx, + PublishedTransactions: publishTx, }, } @@ -425,8 +438,11 @@ func createTestPeerWithChannel(t *testing.T, notifier chainntnfs.ChainNotifier, go alicePeer.channelManager() return &peerTestCtx{ - peer: alicePeer, - channel: channelBob, + peer: alicePeer, + channel: channelBob, + notifier: notifier, + publishTx: publishTx, + mockSwitch: mockSwitch, }, nil } From 2ec0fe07173a2e41652d04e2f778e5ec3d6a7b83 Mon Sep 17 00:00:00 2001 From: Ononiwu Maureen Date: Fri, 15 Mar 2024 12:21:49 +0100 Subject: [PATCH 079/109] peer: Add new function to create test peer. Signed-off-by: Ononiwu Maureen --- peer/brontide_test.go | 199 +++++++---------------- peer/test_utils.go | 365 ++++++++++++++++++++++++++---------------- 2 files changed, 278 insertions(+), 286 deletions(-) diff --git a/peer/brontide_test.go b/peer/brontide_test.go index 11a38e124..3b0ae3ce2 100644 --- a/peer/brontide_test.go +++ b/peer/brontide_test.go @@ -6,22 +6,18 @@ import ( "testing" "time" - "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" - "github.com/lightningnetwork/lnd/channelnotifier" "github.com/lightningnetwork/lnd/contractcourt" "github.com/lightningnetwork/lnd/htlcswitch" - "github.com/lightningnetwork/lnd/lntest/mock" "github.com/lightningnetwork/lnd/lntest/wait" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/chancloser" "github.com/lightningnetwork/lnd/lnwire" - "github.com/lightningnetwork/lnd/pool" "github.com/stretchr/testify/require" ) @@ -42,8 +38,10 @@ func TestPeerChannelClosureShutdownResponseLinkRemoved(t *testing.T) { harness, err := createTestPeerWithChannel(t, noUpdate) require.NoError(t, err, "unable to create test channels") - alicePeer := harness.peer - bobChan := harness.channel + var ( + alicePeer = harness.peer + bobChan = harness.channel + ) chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -82,11 +80,13 @@ func TestPeerChannelClosureAcceptFeeResponder(t *testing.T) { harness, err := createTestPeerWithChannel(t, noUpdate) require.NoError(t, err, "unable to create test channels") - alicePeer := harness.peer - bobChan := harness.channel - mockSwitch := harness.mockSwitch - broadcastTxChan := harness.publishTx - notifier := harness.notifier + var ( + alicePeer = harness.peer + bobChan = harness.channel + mockSwitch = harness.mockSwitch + broadcastTxChan = harness.publishTx + notifier = harness.notifier + ) chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -182,11 +182,13 @@ func TestPeerChannelClosureAcceptFeeInitiator(t *testing.T) { harness, err := createTestPeerWithChannel(t, noUpdate) require.NoError(t, err, "unable to create test channels") - bobChan := harness.channel - alicePeer := harness.peer - mockSwitch := harness.mockSwitch - broadcastTxChan := harness.publishTx - notifier := harness.notifier + var ( + bobChan = harness.channel + alicePeer = harness.peer + mockSwitch = harness.mockSwitch + broadcastTxChan = harness.publishTx + notifier = harness.notifier + ) chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -301,11 +303,13 @@ func TestPeerChannelClosureFeeNegotiationsResponder(t *testing.T) { harness, err := createTestPeerWithChannel(t, noUpdate) require.NoError(t, err, "unable to create test channels") - bobChan := harness.channel - alicePeer := harness.peer - mockSwitch := harness.mockSwitch - broadcastTxChan := harness.publishTx - notifier := harness.notifier + var ( + bobChan = harness.channel + alicePeer = harness.peer + mockSwitch = harness.mockSwitch + broadcastTxChan = harness.publishTx + notifier = harness.notifier + ) chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -483,11 +487,13 @@ func TestPeerChannelClosureFeeNegotiationsInitiator(t *testing.T) { harness, err := createTestPeerWithChannel(t, noUpdate) require.NoError(t, err, "unable to create test channels") - alicePeer := harness.peer - bobChan := harness.channel - mockSwitch := harness.mockSwitch - broadcastTxChan := harness.publishTx - notifier := harness.notifier + var ( + alicePeer = harness.peer + bobChan = harness.channel + mockSwitch = harness.mockSwitch + broadcastTxChan = harness.publishTx + notifier = harness.notifier + ) chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -810,9 +816,11 @@ func TestCustomShutdownScript(t *testing.T) { t.Fatalf("unable to create test channels: %v", err) } - alicePeer := harness.peer - bobChan := harness.channel - mockSwitch := harness.mockSwitch + var ( + alicePeer = harness.peer + bobChan = harness.channel + mockSwitch = harness.mockSwitch + ) chanPoint := bobChan.ChannelPoint() chanID := lnwire.NewChanIDFromOutPoint(chanPoint) @@ -966,35 +974,23 @@ func TestStaticRemoteDowngrade(t *testing.T) { test := test t.Run(test.name, func(t *testing.T) { - writeBufferPool := pool.NewWriteBuffer( - pool.DefaultWriteBufferGCInterval, - pool.DefaultWriteBufferExpiryInterval, + params := createTestPeer(t) + + var ( + p = params.peer + mockConn = params.mockConn + writePool = p.cfg.WritePool ) - - writePool := pool.NewWrite( - writeBufferPool, 1, timeout, - ) - require.NoError(t, writePool.Start()) - - mockConn := newMockConn(t, 1) - - p := Brontide{ - cfg: Config{ - LegacyFeatures: legacy, - Features: test.features, - Conn: mockConn, - WritePool: writePool, - PongBuf: make([]byte, lnwire.MaxPongBytes), - }, - log: peerLog, - } + // Set feature bits. + p.cfg.LegacyFeatures = legacy + p.cfg.Features = test.features var b bytes.Buffer _, err := lnwire.WriteMessage(&b, test.expectedInit, 0) require.NoError(t, err) - // Send our init message, assert that we write our expected message - // and shutdown our write pool. + // Send our init message, assert that we write our + // expected message and shutdown our write pool. require.NoError(t, p.sendInitMsg(test.legacy)) mockConn.assertWrite(b.Bytes()) require.NoError(t, writePool.Stop()) @@ -1022,78 +1018,15 @@ func genScript(t *testing.T, address string) lnwire.DeliveryAddress { func TestPeerCustomMessage(t *testing.T) { t.Parallel() - // Set up node Alice. - dbAlice, err := channeldb.Open(t.TempDir()) - require.NoError(t, err) + params := createTestPeer(t) - aliceKey, err := btcec.NewPrivateKey() - require.NoError(t, err) - - writeBufferPool := pool.NewWriteBuffer( - pool.DefaultWriteBufferGCInterval, - pool.DefaultWriteBufferExpiryInterval, + var ( + mockConn = params.mockConn + alicePeer = params.peer + receivedCustomChan = params.customChan ) - writePool := pool.NewWrite( - writeBufferPool, 1, timeout, - ) - require.NoError(t, writePool.Start()) - - readBufferPool := pool.NewReadBuffer( - pool.DefaultReadBufferGCInterval, - pool.DefaultReadBufferExpiryInterval, - ) - - readPool := pool.NewRead( - readBufferPool, 1, timeout, - ) - require.NoError(t, readPool.Start()) - - mockConn := newMockConn(t, 1) - - receivedCustomChan := make(chan *customMsg) - - remoteKey := [33]byte{8} - - notifier := &mock.ChainNotifier{ - SpendChan: make(chan *chainntnfs.SpendDetail), - EpochChan: make(chan *chainntnfs.BlockEpoch), - ConfChan: make(chan *chainntnfs.TxConfirmation), - } - - // TODO(yy): change ChannelNotifier to be an interface. - channelNotifier := channelnotifier.New(dbAlice.ChannelStateDB()) - require.NoError(t, channelNotifier.Start()) - t.Cleanup(func() { - require.NoError(t, channelNotifier.Stop(), - "stop channel notifier failed") - }) - - alicePeer := NewBrontide(Config{ - PubKeyBytes: remoteKey, - ChannelDB: dbAlice.ChannelStateDB(), - Addr: &lnwire.NetAddress{ - IdentityKey: aliceKey.PubKey(), - }, - PrunePersistentPeerConnection: func([33]byte) {}, - Features: lnwire.EmptyFeatureVector(), - LegacyFeatures: lnwire.EmptyFeatureVector(), - WritePool: writePool, - ReadPool: readPool, - Conn: mockConn, - ChainNotifier: notifier, - HandleCustomMessage: func( - peer [33]byte, msg *lnwire.Custom) error { - - receivedCustomChan <- &customMsg{ - peer: peer, - msg: *msg, - } - return nil - }, - PongBuf: make([]byte, lnwire.MaxPongBytes), - ChannelNotifier: channelNotifier, - }) + remoteKey := alicePeer.PubKey() // Set up the init sequence. go func() { @@ -1108,7 +1041,7 @@ func TestPeerCustomMessage(t *testing.T) { lnwire.NewRawFeatureVector(), ) var b bytes.Buffer - _, err = lnwire.WriteMessage(&b, initReplyMsg, 0) + _, err := lnwire.WriteMessage(&b, initReplyMsg, 0) require.NoError(t, err) mockConn.readMessages <- b.Bytes() @@ -1394,28 +1327,6 @@ func TestStartupWriteMessageRace(t *testing.T) { mockConn := newMockConn(t, 2) peer.cfg.Conn = mockConn - // Set up other configuration necessary to successfully execute - // peer.Start(). - peer.cfg.LegacyFeatures = lnwire.EmptyFeatureVector() - writeBufferPool := pool.NewWriteBuffer( - pool.DefaultWriteBufferGCInterval, - pool.DefaultWriteBufferExpiryInterval, - ) - writePool := pool.NewWrite( - writeBufferPool, 1, timeout, - ) - require.NoError(t, writePool.Start()) - peer.cfg.WritePool = writePool - readBufferPool := pool.NewReadBuffer( - pool.DefaultReadBufferGCInterval, - pool.DefaultReadBufferExpiryInterval, - ) - readPool := pool.NewRead( - readBufferPool, 1, timeout, - ) - require.NoError(t, readPool.Start()) - peer.cfg.ReadPool = readPool - // Send a message while starting the peer. As the peer starts up, it // should not trigger a data race between the sending of this message // and the sending of the channel reestablish message. diff --git a/peer/test_utils.go b/peer/test_utils.go index c872d0313..9a01e35ad 100644 --- a/peer/test_utils.go +++ b/peer/test_utils.go @@ -27,6 +27,7 @@ import ( "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/netann" + "github.com/lightningnetwork/lnd/pool" "github.com/lightningnetwork/lnd/queue" "github.com/lightningnetwork/lnd/shachain" "github.com/stretchr/testify/require" @@ -54,11 +55,16 @@ var ( var noUpdate = func(a, b *channeldb.OpenChannel) {} type peerTestCtx struct { - peer *Brontide - channel *lnwallet.LightningChannel - notifier *mock.ChainNotifier - publishTx <-chan *wire.MsgTx - mockSwitch *mockMessageSwitch + peer *Brontide + channel *lnwallet.LightningChannel + notifier *mock.ChainNotifier + publishTx <-chan *wire.MsgTx + mockSwitch *mockMessageSwitch + db *channeldb.DB + privKey *btcec.PrivateKey + mockConn *mockMessageConn + customChan chan *customMsg + chanStatusMgr *netann.ChanStatusManager } // createTestPeerWithChannel creates a channel between two nodes, and returns a @@ -68,30 +74,26 @@ type peerTestCtx struct { func createTestPeerWithChannel(t *testing.T, updateChan func(a, b *channeldb.OpenChannel)) (*peerTestCtx, error) { - // TODO(yy): create interface for lnwallet.LightningChannel so we can - // easily mock it without the following setups. - notifier := &mock.ChainNotifier{ - SpendChan: make(chan *chainntnfs.SpendDetail), - EpochChan: make(chan *chainntnfs.BlockEpoch), - ConfChan: make(chan *chainntnfs.TxConfirmation), - } + params := createTestPeer(t) - var mockSwitch *mockMessageSwitch + var ( + publishTx = params.publishTx + mockSwitch = params.mockSwitch + alicePeer = params.peer + notifier = params.notifier + aliceKeyPriv = params.privKey + dbAlice = params.db + chanStatusMgr = params.chanStatusMgr + ) - publishTx := make(chan *wire.MsgTx) + err := chanStatusMgr.Start() + require.NoError(t, err) + t.Cleanup(func() { + require.NoError(t, chanStatusMgr.Stop()) + }) - nodeKeyLocator := keychain.KeyLocator{ - Family: keychain.KeyFamilyNodeKey, - } - aliceKeyPriv, aliceKeyPub := btcec.PrivKeyFromBytes( - channels.AlicesPrivKey, - ) - aliceKeySigner := keychain.NewPrivKeyMessageSigner( - aliceKeyPriv, nodeKeyLocator, - ) - bobKeyPriv, bobKeyPub := btcec.PrivKeyFromBytes( - channels.BobsPrivKey, - ) + aliceKeyPub := alicePeer.IdentityKey() + estimator := alicePeer.cfg.FeeEstimator channelCapacity := btcutil.Amount(10 * 1e8) channelBal := channelCapacity / 2 @@ -107,6 +109,10 @@ func createTestPeerWithChannel(t *testing.T, updateChan func(a, } fundingTxIn := wire.NewTxIn(prevOut, nil, nil) + bobKeyPriv, bobKeyPub := btcec.PrivKeyFromBytes( + channels.BobsPrivKey, + ) + aliceCfg := channeldb.ChannelConfig{ ChannelConstraints: channeldb.ChannelConstraints{ DustLimit: aliceDustLimit, @@ -189,14 +195,6 @@ func createTestPeerWithChannel(t *testing.T, updateChan func(a, return nil, err } - dbAlice, err := channeldb.Open(t.TempDir()) - if err != nil { - return nil, err - } - t.Cleanup(func() { - require.NoError(t, dbAlice.Close()) - }) - dbBob, err := channeldb.Open(t.TempDir()) if err != nil { return nil, err @@ -205,7 +203,6 @@ func createTestPeerWithChannel(t *testing.T, updateChan func(a, require.NoError(t, dbBob.Close()) }) - estimator := chainfee.NewStaticEstimator(12500, 0) feePerKw, err := estimator.EstimateFeePerKW(1) if err != nil { return nil, err @@ -278,11 +275,7 @@ func createTestPeerWithChannel(t *testing.T, updateChan func(a, // Set custom values on the channel states. updateChan(aliceChannelState, bobChannelState) - aliceAddr := &net.TCPAddr{ - IP: net.ParseIP("127.0.0.1"), - Port: 18555, - } - + aliceAddr := alicePeer.cfg.Addr.Address if err := aliceChannelState.SyncPending(aliceAddr, 0); err != nil { return nil, err } @@ -327,109 +320,9 @@ func createTestPeerWithChannel(t *testing.T, updateChan func(a, require.NoError(t, bobPool.Stop()) }) - chainIO := &mock.ChainIO{ - BestHeight: broadcastHeight, - } - wallet := &lnwallet.LightningWallet{ - WalletController: &mock.WalletController{ - RootKey: aliceKeyPriv, - PublishedTransactions: publishTx, - }, - } - - // If mockSwitch is not set by the caller, set it to the default as the - // caller does not need to control it. - if mockSwitch == nil { - mockSwitch = &mockMessageSwitch{} - } - - nodeSignerAlice := netann.NewNodeSigner(aliceKeySigner) - - const chanActiveTimeout = time.Minute - - chanStatusMgr, err := netann.NewChanStatusManager(&netann.ChanStatusConfig{ - ChanStatusSampleInterval: 30 * time.Second, - ChanEnableTimeout: chanActiveTimeout, - ChanDisableTimeout: 2 * time.Minute, - DB: dbAlice.ChannelStateDB(), - Graph: dbAlice.ChannelGraph(), - MessageSigner: nodeSignerAlice, - OurPubKey: aliceKeyPub, - OurKeyLoc: testKeyLoc, - IsChannelActive: func(lnwire.ChannelID) bool { return true }, - ApplyChannelUpdate: func(*lnwire.ChannelUpdate, - *wire.OutPoint, bool) error { - - return nil - }, - }) - if err != nil { - return nil, err - } - if err = chanStatusMgr.Start(); err != nil { - return nil, err - } - - errBuffer, err := queue.NewCircularBuffer(ErrorBufferSize) - if err != nil { - return nil, err - } - - var pubKey [33]byte - copy(pubKey[:], aliceKeyPub.SerializeCompressed()) - - cfgAddr := &lnwire.NetAddress{ - IdentityKey: aliceKeyPub, - Address: aliceAddr, - ChainNet: wire.SimNet, - } - - interceptableSwitchNotifier := &mock.ChainNotifier{ - EpochChan: make(chan *chainntnfs.BlockEpoch, 1), - } - interceptableSwitchNotifier.EpochChan <- &chainntnfs.BlockEpoch{ - Height: 1, - } - - interceptableSwitch, err := htlcswitch.NewInterceptableSwitch( - &htlcswitch.InterceptableSwitchConfig{ - CltvRejectDelta: testCltvRejectDelta, - CltvInterceptDelta: testCltvRejectDelta + 3, - Notifier: interceptableSwitchNotifier, - }, + alicePeer.remoteFeatures = lnwire.NewFeatureVector( + nil, lnwire.Features, ) - if err != nil { - return nil, err - } - - // TODO(yy): change ChannelNotifier to be an interface. - channelNotifier := channelnotifier.New(dbAlice.ChannelStateDB()) - require.NoError(t, channelNotifier.Start()) - t.Cleanup(func() { - require.NoError(t, channelNotifier.Stop(), - "stop channel notifier failed") - }) - - cfg := &Config{ - Addr: cfgAddr, - PubKeyBytes: pubKey, - ErrorBuffer: errBuffer, - ChainIO: chainIO, - Switch: mockSwitch, - ChanActiveTimeout: chanActiveTimeout, - InterceptSwitch: interceptableSwitch, - ChannelDB: dbAlice.ChannelStateDB(), - FeeEstimator: estimator, - Wallet: wallet, - ChainNotifier: notifier, - ChanStatusMgr: chanStatusMgr, - Features: lnwire.NewFeatureVector(nil, lnwire.Features), - DisconnectPeer: func(b *btcec.PublicKey) error { return nil }, - ChannelNotifier: channelNotifier, - } - - alicePeer := NewBrontide(*cfg) - alicePeer.remoteFeatures = lnwire.NewFeatureVector(nil, lnwire.Features) chanID := lnwire.NewChanIDFromOutPoint(channelAlice.ChannelPoint()) alicePeer.activeChannels.Store(chanID, channelAlice) @@ -643,3 +536,191 @@ func (m *mockMessageConn) LocalAddr() net.Addr { func (m *mockMessageConn) Close() error { return nil } + +// createTestPeer creates a new peer for testing and returns a context struct +// containing necessary handles and mock objects for conducting tests on peer +// functionalities. +func createTestPeer(t *testing.T) *peerTestCtx { + nodeKeyLocator := keychain.KeyLocator{ + Family: keychain.KeyFamilyNodeKey, + } + + aliceKeyPriv, aliceKeyPub := btcec.PrivKeyFromBytes( + channels.AlicesPrivKey, + ) + + aliceKeySigner := keychain.NewPrivKeyMessageSigner( + aliceKeyPriv, nodeKeyLocator, + ) + + aliceAddr := &net.TCPAddr{ + IP: net.ParseIP("127.0.0.1"), + Port: 18555, + } + cfgAddr := &lnwire.NetAddress{ + IdentityKey: aliceKeyPub, + Address: aliceAddr, + ChainNet: wire.SimNet, + } + + errBuffer, err := queue.NewCircularBuffer(ErrorBufferSize) + require.NoError(t, err) + + chainIO := &mock.ChainIO{ + BestHeight: broadcastHeight, + } + + publishTx := make(chan *wire.MsgTx) + wallet := &lnwallet.LightningWallet{ + WalletController: &mock.WalletController{ + RootKey: aliceKeyPriv, + PublishedTransactions: publishTx, + }, + } + + const chanActiveTimeout = time.Minute + + dbAlice, err := channeldb.Open(t.TempDir()) + require.NoError(t, err) + t.Cleanup(func() { + require.NoError(t, dbAlice.Close()) + }) + + nodeSignerAlice := netann.NewNodeSigner(aliceKeySigner) + + chanStatusMgr, err := netann.NewChanStatusManager(&netann. + ChanStatusConfig{ + ChanStatusSampleInterval: 30 * time.Second, + ChanEnableTimeout: chanActiveTimeout, + ChanDisableTimeout: 2 * time.Minute, + DB: dbAlice.ChannelStateDB(), + Graph: dbAlice.ChannelGraph(), + MessageSigner: nodeSignerAlice, + OurPubKey: aliceKeyPub, + OurKeyLoc: testKeyLoc, + IsChannelActive: func(lnwire.ChannelID) bool { + return true + }, + ApplyChannelUpdate: func(*lnwire.ChannelUpdate, + *wire.OutPoint, bool) error { + + return nil + }, + }) + require.NoError(t, err) + + interceptableSwitchNotifier := &mock.ChainNotifier{ + EpochChan: make(chan *chainntnfs.BlockEpoch, 1), + } + interceptableSwitchNotifier.EpochChan <- &chainntnfs.BlockEpoch{ + Height: 1, + } + + interceptableSwitch, err := htlcswitch.NewInterceptableSwitch( + &htlcswitch.InterceptableSwitchConfig{ + CltvRejectDelta: testCltvRejectDelta, + CltvInterceptDelta: testCltvRejectDelta + 3, + Notifier: interceptableSwitchNotifier, + }, + ) + require.NoError(t, err) + + // TODO(yy): create interface for lnwallet.LightningChannel so we can + // easily mock it without the following setups. + notifier := &mock.ChainNotifier{ + SpendChan: make(chan *chainntnfs.SpendDetail), + EpochChan: make(chan *chainntnfs.BlockEpoch), + ConfChan: make(chan *chainntnfs.TxConfirmation), + } + + mockSwitch := &mockMessageSwitch{} + + // TODO(yy): change ChannelNotifier to be an interface. + channelNotifier := channelnotifier.New(dbAlice.ChannelStateDB()) + require.NoError(t, channelNotifier.Start()) + t.Cleanup(func() { + require.NoError(t, channelNotifier.Stop(), + "stop channel notifier failed") + }) + + writeBufferPool := pool.NewWriteBuffer( + pool.DefaultWriteBufferGCInterval, + pool.DefaultWriteBufferExpiryInterval, + ) + + writePool := pool.NewWrite( + writeBufferPool, 1, timeout, + ) + require.NoError(t, writePool.Start()) + + readBufferPool := pool.NewReadBuffer( + pool.DefaultReadBufferGCInterval, + pool.DefaultReadBufferExpiryInterval, + ) + + readPool := pool.NewRead( + readBufferPool, 1, timeout, + ) + require.NoError(t, readPool.Start()) + + mockConn := newMockConn(t, 1) + + receivedCustomChan := make(chan *customMsg) + + var pubKey [33]byte + copy(pubKey[:], aliceKeyPub.SerializeCompressed()) + + estimator := chainfee.NewStaticEstimator(12500, 0) + + cfg := &Config{ + Addr: cfgAddr, + PubKeyBytes: pubKey, + ErrorBuffer: errBuffer, + ChainIO: chainIO, + Switch: mockSwitch, + ChanActiveTimeout: chanActiveTimeout, + InterceptSwitch: interceptableSwitch, + ChannelDB: dbAlice.ChannelStateDB(), + FeeEstimator: estimator, + Wallet: wallet, + ChainNotifier: notifier, + ChanStatusMgr: chanStatusMgr, + Features: lnwire.NewFeatureVector( + nil, lnwire.Features, + ), + DisconnectPeer: func(b *btcec.PublicKey) error { + return nil + }, + ChannelNotifier: channelNotifier, + PrunePersistentPeerConnection: func([33]byte) {}, + LegacyFeatures: lnwire.EmptyFeatureVector(), + WritePool: writePool, + ReadPool: readPool, + Conn: mockConn, + HandleCustomMessage: func( + peer [33]byte, msg *lnwire.Custom) error { + + receivedCustomChan <- &customMsg{ + peer: peer, + msg: *msg, + } + + return nil + }, + PongBuf: make([]byte, lnwire.MaxPongBytes), + } + + alicePeer := NewBrontide(*cfg) + + return &peerTestCtx{ + publishTx: publishTx, + mockSwitch: mockSwitch, + peer: alicePeer, + notifier: notifier, + db: dbAlice, + privKey: aliceKeyPriv, + mockConn: mockConn, + customChan: receivedCustomChan, + chanStatusMgr: chanStatusMgr, + } +} From a585833fb5245ed6588b7b905b05c3913394bc0f Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 9 May 2024 15:23:48 -0700 Subject: [PATCH 080/109] build: update release builds and CI to Go 1.22.3 --- .github/workflows/main.yml | 2 +- .github/workflows/release.yaml | 2 +- Dockerfile | 2 +- dev.Dockerfile | 2 +- make/builder.Dockerfile | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6d23cf8d9..c025f0d2d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -29,7 +29,7 @@ env: # /dev.Dockerfile # /make/builder.Dockerfile # /.github/workflows/release.yml - GO_VERSION: 1.21.0 + GO_VERSION: 1.22.3 jobs: ######################## diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index e565611c5..4c4cc5d60 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -16,7 +16,7 @@ env: # /dev.Dockerfile # /make/builder.Dockerfile # /.github/workflows/main.yml - GO_VERSION: 1.21.0 + GO_VERSION: 1.22.3 jobs: main: diff --git a/Dockerfile b/Dockerfile index c35ed81bf..d6e8a82c6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ # /make/builder.Dockerfile # /.github/workflows/main.yml # /.github/workflows/release.yml -FROM golang:1.21.0-alpine as builder +FROM golang:1.22.3-alpine as builder # Force Go to use the cgo based DNS resolver. This is required to ensure DNS # queries required to connect to linked containers succeed. diff --git a/dev.Dockerfile b/dev.Dockerfile index bb7c67312..624c1bc3a 100644 --- a/dev.Dockerfile +++ b/dev.Dockerfile @@ -4,7 +4,7 @@ # /make/builder.Dockerfile # /.github/workflows/main.yml # /.github/workflows/release.yml -FROM golang:1.21.0-alpine as builder +FROM golang:1.22.3-alpine as builder LABEL maintainer="Olaoluwa Osuntokun " diff --git a/make/builder.Dockerfile b/make/builder.Dockerfile index efa3d052a..66946e0a4 100644 --- a/make/builder.Dockerfile +++ b/make/builder.Dockerfile @@ -4,7 +4,7 @@ # /dev.Dockerfile # /.github/workflows/main.yml # /.github/workflows/release.yml -FROM golang:1.21.0-bookworm +FROM golang:1.22.3-bookworm MAINTAINER Olaoluwa Osuntokun From f88f120e9192b262e3fe945310449d7285997edf Mon Sep 17 00:00:00 2001 From: Ononiwu Maureen <59079323+Chinwendu20@users.noreply.github.com> Date: Sun, 5 May 2024 21:05:29 +0100 Subject: [PATCH 081/109] fn: Added map functions Signed-off-by: Ononiwu Maureen <59079323+Chinwendu20@users.noreply.github.com> --- fn/map.go | 44 ++++++++++++++++ fn/map_test.go | 135 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 fn/map.go create mode 100644 fn/map_test.go diff --git a/fn/map.go b/fn/map.go new file mode 100644 index 000000000..071da9872 --- /dev/null +++ b/fn/map.go @@ -0,0 +1,44 @@ +package fn + +import ( + "fmt" + + "golang.org/x/exp/maps" +) + +// KeySet converts a map into a Set containing the keys of the map. +func KeySet[K comparable, V any](m map[K]V) Set[K] { + return NewSet(maps.Keys(m)...) +} + +// NewSubMapIntersect returns a sub-map of `m` containing only the keys found in +// both `m` and the `keys` slice. +func NewSubMapIntersect[K comparable, V any](m map[K]V, keys []K) map[K]V { + result := make(map[K]V) + for _, k := range keys { + v, ok := m[k] + if !ok { + continue + } + + result[k] = v + } + + return result +} + +// NewSubMap creates a sub-map from a given map using specified keys. It errors +// if any of the keys is not found in the map. +func NewSubMap[K comparable, V any](m map[K]V, keys []K) (map[K]V, error) { + result := make(map[K]V, len(keys)) + for _, k := range keys { + v, ok := m[k] + if !ok { + return nil, fmt.Errorf("NewSubMap: missing key %v", k) + } + + result[k] = v + } + + return result, nil +} diff --git a/fn/map_test.go b/fn/map_test.go new file mode 100644 index 000000000..b0694bde6 --- /dev/null +++ b/fn/map_test.go @@ -0,0 +1,135 @@ +package fn + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestKeySet(t *testing.T) { + testMap := map[string]int{"a": 1, "b": 2, "c": 3} + expected := NewSet([]string{"a", "b", "c"}...) + + require.Equal(t, expected, KeySet(testMap)) +} + +// TestNewSubMap tests the NewSubMap function with various input cases. +func TestNewSubMap(t *testing.T) { + tests := []struct { + name string + original map[int]string + keys []int + expected map[int]string + wantErr bool + }{ + { + name: "Successful submap creation", + original: map[int]string{ + 1: "apple", + 2: "banana", + 3: "cherry", + }, + keys: []int{1, 3}, + expected: map[int]string{ + 1: "apple", + 3: "cherry", + }, + wantErr: false, + }, + { + name: "Key not found", + original: map[int]string{ + 1: "apple", + 2: "banana", + }, + keys: []int{1, 4}, + expected: nil, + wantErr: true, + }, + { + name: "Empty keys list", + original: map[int]string{ + 1: "apple", + 2: "banana", + }, + keys: []int{}, + expected: map[int]string{}, + wantErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result, err := NewSubMap(tt.original, tt.keys) + if tt.wantErr { + require.ErrorContains( + t, err, "NewSubMap: missing key", + ) + + require.Nil(t, result) + + return + } + + require.NoError(t, err) + require.Equal(t, tt.expected, result) + }) + } +} + +// TestNewSubMapIntersect tests the NewSubMapIntersect function for correctness. +func TestNewSubMapIntersect(t *testing.T) { + tests := []struct { + name string + original map[int]string + keys []int + expected map[int]string + }{ + { + name: "Successful intersection", + original: map[int]string{ + 1: "apple", + 2: "banana", + 3: "cherry", + 4: "date", + }, + keys: []int{2, 3, 5}, + expected: map[int]string{ + 2: "banana", + 3: "cherry", + }, + }, + { + name: "No intersection", + original: map[int]string{ + 1: "apple", + 2: "banana", + }, + keys: []int{3, 4}, + expected: map[int]string{}, + }, + { + name: "Empty original map", + original: map[int]string{}, + keys: []int{1, 2}, + expected: map[int]string{}, + }, + { + name: "Empty keys list", + original: map[int]string{ + 1: "apple", + 2: "banana", + }, + keys: []int{}, + expected: map[int]string{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + require.Equal( + t, tt.expected, + NewSubMapIntersect(tt.original, tt.keys)) + }) + } +} From 30c9b86d62ffa180679c866bd1ac2e554eb55e2b Mon Sep 17 00:00:00 2001 From: Ononiwu Maureen <59079323+Chinwendu20@users.noreply.github.com> Date: Sun, 5 May 2024 21:05:59 +0100 Subject: [PATCH 082/109] fn: Added new slice functions. Signed-off-by: Ononiwu Maureen <59079323+Chinwendu20@users.noreply.github.com> --- fn/slice.go | 30 ++++++++++++++ fn/slice_test.go | 105 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+) diff --git a/fn/slice.go b/fn/slice.go index fe821bff7..2e27acc45 100644 --- a/fn/slice.go +++ b/fn/slice.go @@ -1,5 +1,13 @@ package fn +import "golang.org/x/exp/constraints" + +// Number is a type constraint for all numeric types in Go (integers, +// float and complex numbers) +type Number interface { + constraints.Integer | constraints.Float | constraints.Complex +} + // All returns true when the supplied predicate evaluates to true for all of // the values in the slice. func All[A any](pred func(A) bool, s []A) bool { @@ -168,3 +176,25 @@ func ZipWith[A, B, C any](f func(A, B) C, a []A, b []B) []C { return res } + +// SliceToMap converts a slice to a map using the provided key and value +// functions. +func SliceToMap[A any, K comparable, V any](s []A, keyFunc func(A) K, + valueFunc func(A) V) map[K]V { + + res := make(map[K]V, len(s)) + for _, val := range s { + key := keyFunc(val) + value := valueFunc(val) + res[key] = value + } + + return res +} + +// Sum calculates the sum of a slice of numbers, `items`. +func Sum[B Number](items []B) B { + return Foldl(func(a, b B) B { + return a + b + }, 0, items) +} diff --git a/fn/slice_test.go b/fn/slice_test.go index 0178cc946..de02be836 100644 --- a/fn/slice_test.go +++ b/fn/slice_test.go @@ -1,6 +1,7 @@ package fn import ( + "fmt" "slices" "testing" @@ -136,3 +137,107 @@ func TestZipWith(t *testing.T) { z, []bool{false, true, false, false, false}, )) } + +// TestSum checks if the Sum function correctly calculates the sum of the +// numbers in the slice. +func TestSum(t *testing.T) { + tests := []struct { + name string + items interface{} + result interface{} + }{ + { + name: "Sum of positive integers", + items: []int{1, 2, 3}, + result: 6, + }, + { + name: "Sum of negative integers", + items: []int{-1, -2, -3}, + result: -6, + }, + { + name: "Sum of float numbers", + items: []float64{1.1, 2.2, 3.3}, + result: 6.6, + }, + { + name: "Sum of complex numbers", + items: []complex128{ + complex(1, 1), + complex(2, 2), + complex(3, 3), + }, + result: complex(6, 6), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + switch v := tt.items.(type) { + case []int: + require.Equal(t, tt.result, Sum(v)) + case []float64: + require.Equal(t, tt.result, Sum(v)) + case []complex128: + require.Equal(t, tt.result, Sum(v)) + } + }) + } +} + +// TestSliceToMap tests the SliceToMap function. +func TestSliceToMap(t *testing.T) { + tests := []struct { + name string + slice []int + keyFunc func(int) int + valueFunc func(int) string + expected map[int]string + }{ + { + name: "Integers to string map", + slice: []int{1, 2, 3}, + keyFunc: func(a int) int { return a }, + valueFunc: func(a int) string { + return fmt.Sprintf("Value%d", a) + }, + expected: map[int]string{ + 1: "Value1", + 2: "Value2", + 3: "Value3", + }, + }, + { + name: "Duplicates in slice", + slice: []int{1, 2, 2, 3}, + keyFunc: func(a int) int { return a }, + valueFunc: func(a int) string { + return fmt.Sprintf("Value%d", a) + }, + expected: map[int]string{ + 1: "Value1", + 2: "Value2", + 3: "Value3", + }, + }, + { + name: "Empty slice", + slice: []int{}, + keyFunc: func(a int) int { return a }, + valueFunc: func(a int) string { + return fmt.Sprintf("Value%d", a) + }, + expected: map[int]string{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + require.Equal( + t, tt.expected, + SliceToMap(tt.slice, tt.keyFunc, tt.valueFunc), + ) + }) + } +} From b741132a81ab1412f005aefdc9467f31bf2e5754 Mon Sep 17 00:00:00 2001 From: Ononiwu Maureen Date: Fri, 15 Mar 2024 15:56:48 +0100 Subject: [PATCH 083/109] peer: Add `startPeer` test function Signed-off-by: Ononiwu Maureen --- peer/brontide_test.go | 56 ++++++++++--------------------------------- peer/test_utils.go | 50 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 44 deletions(-) diff --git a/peer/brontide_test.go b/peer/brontide_test.go index 3b0ae3ce2..d2f3fc7bc 100644 --- a/peer/brontide_test.go +++ b/peer/brontide_test.go @@ -13,6 +13,7 @@ import ( "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/contractcourt" + "github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/lntest/wait" "github.com/lightningnetwork/lnd/lnwallet" @@ -1024,31 +1025,13 @@ func TestPeerCustomMessage(t *testing.T) { mockConn = params.mockConn alicePeer = params.peer receivedCustomChan = params.customChan + remoteKey = alicePeer.PubKey() ) - remoteKey := alicePeer.PubKey() - - // Set up the init sequence. - go func() { - // Read init message. - <-mockConn.writtenMessages - - // Write the init reply message. - initReplyMsg := lnwire.NewInitMessage( - lnwire.NewRawFeatureVector( - lnwire.DataLossProtectRequired, - ), - lnwire.NewRawFeatureVector(), - ) - var b bytes.Buffer - _, err := lnwire.WriteMessage(&b, initReplyMsg, 0) - require.NoError(t, err) - - mockConn.readMessages <- b.Bytes() - }() - - // Start the peer. - require.NoError(t, alicePeer.Start()) + // Start peer. + startPeerDone := startPeer(t, mockConn, alicePeer) + _, err := fn.RecvOrTimeout(startPeerDone, 2*timeout) + require.NoError(t, err) // Send a custom message. customMsg, err := lnwire.NewCustom( @@ -1330,33 +1313,18 @@ func TestStartupWriteMessageRace(t *testing.T) { // Send a message while starting the peer. As the peer starts up, it // should not trigger a data race between the sending of this message // and the sending of the channel reestablish message. - sendPingDone := make(chan struct{}) + var sendPingDone = make(chan struct{}) go func() { require.NoError(t, peer.SendMessage(true, lnwire.NewPing(0))) close(sendPingDone) }() - // Handle init messages. - go func() { - // Read init message. - <-mockConn.writtenMessages - - // Write the init reply message. - initReplyMsg := lnwire.NewInitMessage( - lnwire.NewRawFeatureVector( - lnwire.DataLossProtectRequired, - ), - lnwire.NewRawFeatureVector(), - ) - var b bytes.Buffer - _, err = lnwire.WriteMessage(&b, initReplyMsg, 0) - require.NoError(t, err) - - mockConn.readMessages <- b.Bytes() - }() - // Start the peer. No data race should occur. - require.NoError(t, peer.Start()) + startPeerDone := startPeer(t, mockConn, peer) + + // Ensure startup is complete. + _, err = fn.RecvOrTimeout(startPeerDone, 2*timeout) + require.NoError(t, err) // Ensure messages were sent during startup. <-sendPingDone diff --git a/peer/test_utils.go b/peer/test_utils.go index 9a01e35ad..8667b04cd 100644 --- a/peer/test_utils.go +++ b/peer/test_utils.go @@ -18,6 +18,7 @@ import ( "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channelnotifier" + "github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/keychain" @@ -724,3 +725,52 @@ func createTestPeer(t *testing.T) *peerTestCtx { chanStatusMgr: chanStatusMgr, } } + +// startPeer invokes the `Start` method on the specified peer and handles any +// initial startup messages for testing. +func startPeer(t *testing.T, mockConn *mockMessageConn, + peer *Brontide) <-chan struct{} { + + // Start the peer in a goroutine so that we can handle and test for + // startup messages. Successfully sending and receiving init message, + // indicates a successful startup. + done := make(chan struct{}) + go func() { + require.NoError(t, peer.Start()) + close(done) + }() + + // Receive the init message that should be the first message received on + // startup. + rawMsg, err := fn.RecvOrTimeout[[]byte]( + mockConn.writtenMessages, timeout, + ) + require.NoError(t, err) + + msgReader := bytes.NewReader(rawMsg) + nextMsg, err := lnwire.ReadMessage(msgReader, 0) + require.NoError(t, err) + + _, ok := nextMsg.(*lnwire.Init) + require.True(t, ok) + + // Write the reply for the init message to complete the startup. + initReplyMsg := lnwire.NewInitMessage( + lnwire.NewRawFeatureVector( + lnwire.DataLossProtectRequired, + lnwire.GossipQueriesOptional, + ), + lnwire.NewRawFeatureVector(), + ) + + var b bytes.Buffer + _, err = lnwire.WriteMessage(&b, initReplyMsg, 0) + require.NoError(t, err) + + ok = fn.SendOrQuit[[]byte, struct{}]( + mockConn.readMessages, b.Bytes(), make(chan struct{}), + ) + require.True(t, ok) + + return done +} From 593a5643323bebc6de118c4a95d5e498d84cac04 Mon Sep 17 00:00:00 2001 From: Filiprogrammer <44641787+Filiprogrammer@users.noreply.github.com> Date: Thu, 18 Apr 2024 21:57:47 +0200 Subject: [PATCH 084/109] funding: enhance error logs for failed inbound funding requests For failed inbound funding requests, add missing error logs and make sparse error logs more descriptive. --- funding/manager.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/funding/manager.go b/funding/manager.go index e110269a7..158e22e23 100644 --- a/funding/manager.go +++ b/funding/manager.go @@ -1550,6 +1550,8 @@ func (f *Manager) fundeeProcessOpenChannel(peer lnpeer.Peer, // Fail the funding flow. flowErr := fmt.Errorf("channel acceptor blocked " + "zero-conf channel negotiation") + log.Errorf("Cancelling funding flow for %v based on "+ + "channel acceptor response: %v", cid, flowErr) f.failFundingFlow(peer, cid, flowErr) return } @@ -1564,6 +1566,9 @@ func (f *Manager) fundeeProcessOpenChannel(peer lnpeer.Peer, // Fail the funding flow. flowErr := fmt.Errorf("scid-alias feature " + "must be negotiated for zero-conf") + log.Errorf("Cancelling funding flow for "+ + "zero-conf channel %v: %v", cid, + flowErr) f.failFundingFlow(peer, cid, flowErr) return } @@ -1580,7 +1585,8 @@ func (f *Manager) fundeeProcessOpenChannel(peer lnpeer.Peer, case public && scid: err = fmt.Errorf("option-scid-alias chantype for public " + "channel") - log.Error(err) + log.Errorf("Cancelling funding flow for public channel %v "+ + "with scid-alias: %v", cid, err) f.failFundingFlow(peer, cid, err) return @@ -1589,7 +1595,8 @@ func (f *Manager) fundeeProcessOpenChannel(peer lnpeer.Peer, // unadvertised channels for now. case commitType.IsTaproot() && public: err = fmt.Errorf("taproot channel type for public channel") - log.Error(err) + log.Errorf("Cancelling funding flow for public taproot "+ + "channel %v: %v", cid, err) f.failFundingFlow(peer, cid, err) return From 454f56d4a849aad278937846ed94cd8644becf79 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 13 May 2024 16:44:39 +0200 Subject: [PATCH 085/109] tlv: generate TLV types for custom ranges --- tlv/internal/gen/gen_tlv_types.go | 23 +- tlv/tlv_types_generated.go | 1010 +++++++++++++++++++++++++++++ 2 files changed, 1028 insertions(+), 5 deletions(-) diff --git a/tlv/internal/gen/gen_tlv_types.go b/tlv/internal/gen/gen_tlv_types.go index da2d4572e..331d10b64 100644 --- a/tlv/internal/gen/gen_tlv_types.go +++ b/tlv/internal/gen/gen_tlv_types.go @@ -8,8 +8,12 @@ import ( ) const ( - numberOfTypes = 100 - defaultOutputFile = "tlv_types_generated.go" + numberOfTypes uint32 = 100 + + // customTypeStart defines the beginning of the custom TLV type range as + // defined in BOLT-01. + customTypeStart uint32 = 65536 + defaultOutputFile = "tlv_types_generated.go" ) const typeCodeTemplate = `// Code generated by tlv/internal/gen; DO NOT EDIT. @@ -32,9 +36,18 @@ type TlvType{{ $index }} = *tlvType{{ $index }} func main() { // Create a slice of items that the template can range over. - var items []struct{} - for i := uint16(0); i <= numberOfTypes; i++ { - items = append(items, struct{}{}) + // + // We'll generate 100 elements from the lower end of the TLV range + // first. + items := make(map[uint32]struct{}) + for i := uint32(0); i <= numberOfTypes; i++ { + items[i] = struct{}{} + } + + // With the lower end generated, we'll now generate 100 records in the + // upper end of the range. + for i := customTypeStart; i <= customTypeStart+numberOfTypes; i++ { + items[i] = struct{}{} } tpl, err := template.New("tlv").Parse(typeCodeTemplate) diff --git a/tlv/tlv_types_generated.go b/tlv/tlv_types_generated.go index f2e0420fd..c75a86232 100644 --- a/tlv/tlv_types_generated.go +++ b/tlv/tlv_types_generated.go @@ -1011,3 +1011,1013 @@ func (t *tlvType100) TypeVal() Type { func (t *tlvType100) tlv() {} type TlvType100 = *tlvType100 + +type tlvType65536 struct{} + +func (t *tlvType65536) TypeVal() Type { + return 65536 +} + +func (t *tlvType65536) tlv() {} + +type TlvType65536 = *tlvType65536 + +type tlvType65537 struct{} + +func (t *tlvType65537) TypeVal() Type { + return 65537 +} + +func (t *tlvType65537) tlv() {} + +type TlvType65537 = *tlvType65537 + +type tlvType65538 struct{} + +func (t *tlvType65538) TypeVal() Type { + return 65538 +} + +func (t *tlvType65538) tlv() {} + +type TlvType65538 = *tlvType65538 + +type tlvType65539 struct{} + +func (t *tlvType65539) TypeVal() Type { + return 65539 +} + +func (t *tlvType65539) tlv() {} + +type TlvType65539 = *tlvType65539 + +type tlvType65540 struct{} + +func (t *tlvType65540) TypeVal() Type { + return 65540 +} + +func (t *tlvType65540) tlv() {} + +type TlvType65540 = *tlvType65540 + +type tlvType65541 struct{} + +func (t *tlvType65541) TypeVal() Type { + return 65541 +} + +func (t *tlvType65541) tlv() {} + +type TlvType65541 = *tlvType65541 + +type tlvType65542 struct{} + +func (t *tlvType65542) TypeVal() Type { + return 65542 +} + +func (t *tlvType65542) tlv() {} + +type TlvType65542 = *tlvType65542 + +type tlvType65543 struct{} + +func (t *tlvType65543) TypeVal() Type { + return 65543 +} + +func (t *tlvType65543) tlv() {} + +type TlvType65543 = *tlvType65543 + +type tlvType65544 struct{} + +func (t *tlvType65544) TypeVal() Type { + return 65544 +} + +func (t *tlvType65544) tlv() {} + +type TlvType65544 = *tlvType65544 + +type tlvType65545 struct{} + +func (t *tlvType65545) TypeVal() Type { + return 65545 +} + +func (t *tlvType65545) tlv() {} + +type TlvType65545 = *tlvType65545 + +type tlvType65546 struct{} + +func (t *tlvType65546) TypeVal() Type { + return 65546 +} + +func (t *tlvType65546) tlv() {} + +type TlvType65546 = *tlvType65546 + +type tlvType65547 struct{} + +func (t *tlvType65547) TypeVal() Type { + return 65547 +} + +func (t *tlvType65547) tlv() {} + +type TlvType65547 = *tlvType65547 + +type tlvType65548 struct{} + +func (t *tlvType65548) TypeVal() Type { + return 65548 +} + +func (t *tlvType65548) tlv() {} + +type TlvType65548 = *tlvType65548 + +type tlvType65549 struct{} + +func (t *tlvType65549) TypeVal() Type { + return 65549 +} + +func (t *tlvType65549) tlv() {} + +type TlvType65549 = *tlvType65549 + +type tlvType65550 struct{} + +func (t *tlvType65550) TypeVal() Type { + return 65550 +} + +func (t *tlvType65550) tlv() {} + +type TlvType65550 = *tlvType65550 + +type tlvType65551 struct{} + +func (t *tlvType65551) TypeVal() Type { + return 65551 +} + +func (t *tlvType65551) tlv() {} + +type TlvType65551 = *tlvType65551 + +type tlvType65552 struct{} + +func (t *tlvType65552) TypeVal() Type { + return 65552 +} + +func (t *tlvType65552) tlv() {} + +type TlvType65552 = *tlvType65552 + +type tlvType65553 struct{} + +func (t *tlvType65553) TypeVal() Type { + return 65553 +} + +func (t *tlvType65553) tlv() {} + +type TlvType65553 = *tlvType65553 + +type tlvType65554 struct{} + +func (t *tlvType65554) TypeVal() Type { + return 65554 +} + +func (t *tlvType65554) tlv() {} + +type TlvType65554 = *tlvType65554 + +type tlvType65555 struct{} + +func (t *tlvType65555) TypeVal() Type { + return 65555 +} + +func (t *tlvType65555) tlv() {} + +type TlvType65555 = *tlvType65555 + +type tlvType65556 struct{} + +func (t *tlvType65556) TypeVal() Type { + return 65556 +} + +func (t *tlvType65556) tlv() {} + +type TlvType65556 = *tlvType65556 + +type tlvType65557 struct{} + +func (t *tlvType65557) TypeVal() Type { + return 65557 +} + +func (t *tlvType65557) tlv() {} + +type TlvType65557 = *tlvType65557 + +type tlvType65558 struct{} + +func (t *tlvType65558) TypeVal() Type { + return 65558 +} + +func (t *tlvType65558) tlv() {} + +type TlvType65558 = *tlvType65558 + +type tlvType65559 struct{} + +func (t *tlvType65559) TypeVal() Type { + return 65559 +} + +func (t *tlvType65559) tlv() {} + +type TlvType65559 = *tlvType65559 + +type tlvType65560 struct{} + +func (t *tlvType65560) TypeVal() Type { + return 65560 +} + +func (t *tlvType65560) tlv() {} + +type TlvType65560 = *tlvType65560 + +type tlvType65561 struct{} + +func (t *tlvType65561) TypeVal() Type { + return 65561 +} + +func (t *tlvType65561) tlv() {} + +type TlvType65561 = *tlvType65561 + +type tlvType65562 struct{} + +func (t *tlvType65562) TypeVal() Type { + return 65562 +} + +func (t *tlvType65562) tlv() {} + +type TlvType65562 = *tlvType65562 + +type tlvType65563 struct{} + +func (t *tlvType65563) TypeVal() Type { + return 65563 +} + +func (t *tlvType65563) tlv() {} + +type TlvType65563 = *tlvType65563 + +type tlvType65564 struct{} + +func (t *tlvType65564) TypeVal() Type { + return 65564 +} + +func (t *tlvType65564) tlv() {} + +type TlvType65564 = *tlvType65564 + +type tlvType65565 struct{} + +func (t *tlvType65565) TypeVal() Type { + return 65565 +} + +func (t *tlvType65565) tlv() {} + +type TlvType65565 = *tlvType65565 + +type tlvType65566 struct{} + +func (t *tlvType65566) TypeVal() Type { + return 65566 +} + +func (t *tlvType65566) tlv() {} + +type TlvType65566 = *tlvType65566 + +type tlvType65567 struct{} + +func (t *tlvType65567) TypeVal() Type { + return 65567 +} + +func (t *tlvType65567) tlv() {} + +type TlvType65567 = *tlvType65567 + +type tlvType65568 struct{} + +func (t *tlvType65568) TypeVal() Type { + return 65568 +} + +func (t *tlvType65568) tlv() {} + +type TlvType65568 = *tlvType65568 + +type tlvType65569 struct{} + +func (t *tlvType65569) TypeVal() Type { + return 65569 +} + +func (t *tlvType65569) tlv() {} + +type TlvType65569 = *tlvType65569 + +type tlvType65570 struct{} + +func (t *tlvType65570) TypeVal() Type { + return 65570 +} + +func (t *tlvType65570) tlv() {} + +type TlvType65570 = *tlvType65570 + +type tlvType65571 struct{} + +func (t *tlvType65571) TypeVal() Type { + return 65571 +} + +func (t *tlvType65571) tlv() {} + +type TlvType65571 = *tlvType65571 + +type tlvType65572 struct{} + +func (t *tlvType65572) TypeVal() Type { + return 65572 +} + +func (t *tlvType65572) tlv() {} + +type TlvType65572 = *tlvType65572 + +type tlvType65573 struct{} + +func (t *tlvType65573) TypeVal() Type { + return 65573 +} + +func (t *tlvType65573) tlv() {} + +type TlvType65573 = *tlvType65573 + +type tlvType65574 struct{} + +func (t *tlvType65574) TypeVal() Type { + return 65574 +} + +func (t *tlvType65574) tlv() {} + +type TlvType65574 = *tlvType65574 + +type tlvType65575 struct{} + +func (t *tlvType65575) TypeVal() Type { + return 65575 +} + +func (t *tlvType65575) tlv() {} + +type TlvType65575 = *tlvType65575 + +type tlvType65576 struct{} + +func (t *tlvType65576) TypeVal() Type { + return 65576 +} + +func (t *tlvType65576) tlv() {} + +type TlvType65576 = *tlvType65576 + +type tlvType65577 struct{} + +func (t *tlvType65577) TypeVal() Type { + return 65577 +} + +func (t *tlvType65577) tlv() {} + +type TlvType65577 = *tlvType65577 + +type tlvType65578 struct{} + +func (t *tlvType65578) TypeVal() Type { + return 65578 +} + +func (t *tlvType65578) tlv() {} + +type TlvType65578 = *tlvType65578 + +type tlvType65579 struct{} + +func (t *tlvType65579) TypeVal() Type { + return 65579 +} + +func (t *tlvType65579) tlv() {} + +type TlvType65579 = *tlvType65579 + +type tlvType65580 struct{} + +func (t *tlvType65580) TypeVal() Type { + return 65580 +} + +func (t *tlvType65580) tlv() {} + +type TlvType65580 = *tlvType65580 + +type tlvType65581 struct{} + +func (t *tlvType65581) TypeVal() Type { + return 65581 +} + +func (t *tlvType65581) tlv() {} + +type TlvType65581 = *tlvType65581 + +type tlvType65582 struct{} + +func (t *tlvType65582) TypeVal() Type { + return 65582 +} + +func (t *tlvType65582) tlv() {} + +type TlvType65582 = *tlvType65582 + +type tlvType65583 struct{} + +func (t *tlvType65583) TypeVal() Type { + return 65583 +} + +func (t *tlvType65583) tlv() {} + +type TlvType65583 = *tlvType65583 + +type tlvType65584 struct{} + +func (t *tlvType65584) TypeVal() Type { + return 65584 +} + +func (t *tlvType65584) tlv() {} + +type TlvType65584 = *tlvType65584 + +type tlvType65585 struct{} + +func (t *tlvType65585) TypeVal() Type { + return 65585 +} + +func (t *tlvType65585) tlv() {} + +type TlvType65585 = *tlvType65585 + +type tlvType65586 struct{} + +func (t *tlvType65586) TypeVal() Type { + return 65586 +} + +func (t *tlvType65586) tlv() {} + +type TlvType65586 = *tlvType65586 + +type tlvType65587 struct{} + +func (t *tlvType65587) TypeVal() Type { + return 65587 +} + +func (t *tlvType65587) tlv() {} + +type TlvType65587 = *tlvType65587 + +type tlvType65588 struct{} + +func (t *tlvType65588) TypeVal() Type { + return 65588 +} + +func (t *tlvType65588) tlv() {} + +type TlvType65588 = *tlvType65588 + +type tlvType65589 struct{} + +func (t *tlvType65589) TypeVal() Type { + return 65589 +} + +func (t *tlvType65589) tlv() {} + +type TlvType65589 = *tlvType65589 + +type tlvType65590 struct{} + +func (t *tlvType65590) TypeVal() Type { + return 65590 +} + +func (t *tlvType65590) tlv() {} + +type TlvType65590 = *tlvType65590 + +type tlvType65591 struct{} + +func (t *tlvType65591) TypeVal() Type { + return 65591 +} + +func (t *tlvType65591) tlv() {} + +type TlvType65591 = *tlvType65591 + +type tlvType65592 struct{} + +func (t *tlvType65592) TypeVal() Type { + return 65592 +} + +func (t *tlvType65592) tlv() {} + +type TlvType65592 = *tlvType65592 + +type tlvType65593 struct{} + +func (t *tlvType65593) TypeVal() Type { + return 65593 +} + +func (t *tlvType65593) tlv() {} + +type TlvType65593 = *tlvType65593 + +type tlvType65594 struct{} + +func (t *tlvType65594) TypeVal() Type { + return 65594 +} + +func (t *tlvType65594) tlv() {} + +type TlvType65594 = *tlvType65594 + +type tlvType65595 struct{} + +func (t *tlvType65595) TypeVal() Type { + return 65595 +} + +func (t *tlvType65595) tlv() {} + +type TlvType65595 = *tlvType65595 + +type tlvType65596 struct{} + +func (t *tlvType65596) TypeVal() Type { + return 65596 +} + +func (t *tlvType65596) tlv() {} + +type TlvType65596 = *tlvType65596 + +type tlvType65597 struct{} + +func (t *tlvType65597) TypeVal() Type { + return 65597 +} + +func (t *tlvType65597) tlv() {} + +type TlvType65597 = *tlvType65597 + +type tlvType65598 struct{} + +func (t *tlvType65598) TypeVal() Type { + return 65598 +} + +func (t *tlvType65598) tlv() {} + +type TlvType65598 = *tlvType65598 + +type tlvType65599 struct{} + +func (t *tlvType65599) TypeVal() Type { + return 65599 +} + +func (t *tlvType65599) tlv() {} + +type TlvType65599 = *tlvType65599 + +type tlvType65600 struct{} + +func (t *tlvType65600) TypeVal() Type { + return 65600 +} + +func (t *tlvType65600) tlv() {} + +type TlvType65600 = *tlvType65600 + +type tlvType65601 struct{} + +func (t *tlvType65601) TypeVal() Type { + return 65601 +} + +func (t *tlvType65601) tlv() {} + +type TlvType65601 = *tlvType65601 + +type tlvType65602 struct{} + +func (t *tlvType65602) TypeVal() Type { + return 65602 +} + +func (t *tlvType65602) tlv() {} + +type TlvType65602 = *tlvType65602 + +type tlvType65603 struct{} + +func (t *tlvType65603) TypeVal() Type { + return 65603 +} + +func (t *tlvType65603) tlv() {} + +type TlvType65603 = *tlvType65603 + +type tlvType65604 struct{} + +func (t *tlvType65604) TypeVal() Type { + return 65604 +} + +func (t *tlvType65604) tlv() {} + +type TlvType65604 = *tlvType65604 + +type tlvType65605 struct{} + +func (t *tlvType65605) TypeVal() Type { + return 65605 +} + +func (t *tlvType65605) tlv() {} + +type TlvType65605 = *tlvType65605 + +type tlvType65606 struct{} + +func (t *tlvType65606) TypeVal() Type { + return 65606 +} + +func (t *tlvType65606) tlv() {} + +type TlvType65606 = *tlvType65606 + +type tlvType65607 struct{} + +func (t *tlvType65607) TypeVal() Type { + return 65607 +} + +func (t *tlvType65607) tlv() {} + +type TlvType65607 = *tlvType65607 + +type tlvType65608 struct{} + +func (t *tlvType65608) TypeVal() Type { + return 65608 +} + +func (t *tlvType65608) tlv() {} + +type TlvType65608 = *tlvType65608 + +type tlvType65609 struct{} + +func (t *tlvType65609) TypeVal() Type { + return 65609 +} + +func (t *tlvType65609) tlv() {} + +type TlvType65609 = *tlvType65609 + +type tlvType65610 struct{} + +func (t *tlvType65610) TypeVal() Type { + return 65610 +} + +func (t *tlvType65610) tlv() {} + +type TlvType65610 = *tlvType65610 + +type tlvType65611 struct{} + +func (t *tlvType65611) TypeVal() Type { + return 65611 +} + +func (t *tlvType65611) tlv() {} + +type TlvType65611 = *tlvType65611 + +type tlvType65612 struct{} + +func (t *tlvType65612) TypeVal() Type { + return 65612 +} + +func (t *tlvType65612) tlv() {} + +type TlvType65612 = *tlvType65612 + +type tlvType65613 struct{} + +func (t *tlvType65613) TypeVal() Type { + return 65613 +} + +func (t *tlvType65613) tlv() {} + +type TlvType65613 = *tlvType65613 + +type tlvType65614 struct{} + +func (t *tlvType65614) TypeVal() Type { + return 65614 +} + +func (t *tlvType65614) tlv() {} + +type TlvType65614 = *tlvType65614 + +type tlvType65615 struct{} + +func (t *tlvType65615) TypeVal() Type { + return 65615 +} + +func (t *tlvType65615) tlv() {} + +type TlvType65615 = *tlvType65615 + +type tlvType65616 struct{} + +func (t *tlvType65616) TypeVal() Type { + return 65616 +} + +func (t *tlvType65616) tlv() {} + +type TlvType65616 = *tlvType65616 + +type tlvType65617 struct{} + +func (t *tlvType65617) TypeVal() Type { + return 65617 +} + +func (t *tlvType65617) tlv() {} + +type TlvType65617 = *tlvType65617 + +type tlvType65618 struct{} + +func (t *tlvType65618) TypeVal() Type { + return 65618 +} + +func (t *tlvType65618) tlv() {} + +type TlvType65618 = *tlvType65618 + +type tlvType65619 struct{} + +func (t *tlvType65619) TypeVal() Type { + return 65619 +} + +func (t *tlvType65619) tlv() {} + +type TlvType65619 = *tlvType65619 + +type tlvType65620 struct{} + +func (t *tlvType65620) TypeVal() Type { + return 65620 +} + +func (t *tlvType65620) tlv() {} + +type TlvType65620 = *tlvType65620 + +type tlvType65621 struct{} + +func (t *tlvType65621) TypeVal() Type { + return 65621 +} + +func (t *tlvType65621) tlv() {} + +type TlvType65621 = *tlvType65621 + +type tlvType65622 struct{} + +func (t *tlvType65622) TypeVal() Type { + return 65622 +} + +func (t *tlvType65622) tlv() {} + +type TlvType65622 = *tlvType65622 + +type tlvType65623 struct{} + +func (t *tlvType65623) TypeVal() Type { + return 65623 +} + +func (t *tlvType65623) tlv() {} + +type TlvType65623 = *tlvType65623 + +type tlvType65624 struct{} + +func (t *tlvType65624) TypeVal() Type { + return 65624 +} + +func (t *tlvType65624) tlv() {} + +type TlvType65624 = *tlvType65624 + +type tlvType65625 struct{} + +func (t *tlvType65625) TypeVal() Type { + return 65625 +} + +func (t *tlvType65625) tlv() {} + +type TlvType65625 = *tlvType65625 + +type tlvType65626 struct{} + +func (t *tlvType65626) TypeVal() Type { + return 65626 +} + +func (t *tlvType65626) tlv() {} + +type TlvType65626 = *tlvType65626 + +type tlvType65627 struct{} + +func (t *tlvType65627) TypeVal() Type { + return 65627 +} + +func (t *tlvType65627) tlv() {} + +type TlvType65627 = *tlvType65627 + +type tlvType65628 struct{} + +func (t *tlvType65628) TypeVal() Type { + return 65628 +} + +func (t *tlvType65628) tlv() {} + +type TlvType65628 = *tlvType65628 + +type tlvType65629 struct{} + +func (t *tlvType65629) TypeVal() Type { + return 65629 +} + +func (t *tlvType65629) tlv() {} + +type TlvType65629 = *tlvType65629 + +type tlvType65630 struct{} + +func (t *tlvType65630) TypeVal() Type { + return 65630 +} + +func (t *tlvType65630) tlv() {} + +type TlvType65630 = *tlvType65630 + +type tlvType65631 struct{} + +func (t *tlvType65631) TypeVal() Type { + return 65631 +} + +func (t *tlvType65631) tlv() {} + +type TlvType65631 = *tlvType65631 + +type tlvType65632 struct{} + +func (t *tlvType65632) TypeVal() Type { + return 65632 +} + +func (t *tlvType65632) tlv() {} + +type TlvType65632 = *tlvType65632 + +type tlvType65633 struct{} + +func (t *tlvType65633) TypeVal() Type { + return 65633 +} + +func (t *tlvType65633) tlv() {} + +type TlvType65633 = *tlvType65633 + +type tlvType65634 struct{} + +func (t *tlvType65634) TypeVal() Type { + return 65634 +} + +func (t *tlvType65634) tlv() {} + +type TlvType65634 = *tlvType65634 + +type tlvType65635 struct{} + +func (t *tlvType65635) TypeVal() Type { + return 65635 +} + +func (t *tlvType65635) tlv() {} + +type TlvType65635 = *tlvType65635 + +type tlvType65636 struct{} + +func (t *tlvType65636) TypeVal() Type { + return 65636 +} + +func (t *tlvType65636) tlv() {} + +type TlvType65636 = *tlvType65636 From c9713e0ddb0f144163883d8631a014a12aa8c708 Mon Sep 17 00:00:00 2001 From: Slyghtning Date: Thu, 16 May 2024 13:51:47 +0200 Subject: [PATCH 086/109] routing: log edge when skipping it --- routing/unified_edges.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/routing/unified_edges.go b/routing/unified_edges.go index 44efc6314..232c92e1c 100644 --- a/routing/unified_edges.go +++ b/routing/unified_edges.go @@ -279,14 +279,13 @@ func (u *edgeUnifier) getEdgeLocal(netAmtReceived lnwire.MilliSatoshi, } // We pick the local channel with the highest available - // bandwidth, to maximize the success probability. It - // can be that the channel state changes between - // querying the bandwidth hints and sending out the - // htlc. + // bandwidth, to maximize the success probability. It can be + // that the channel state changes between querying the bandwidth + // hints and sending out the htlc. if bandwidth < maxBandwidth { log.Debugf("Skipped edge %v: not max bandwidth, "+ "bandwidth=%v, maxBandwidth=%v", - bandwidth, maxBandwidth) + edge.policy.ChannelID, bandwidth, maxBandwidth) continue } From e8196c6feb0a7720c3e1f54deb46685f4651b311 Mon Sep 17 00:00:00 2001 From: Orbital Date: Tue, 14 May 2024 08:40:05 -0500 Subject: [PATCH 087/109] cfg: move experimental options to main protocol cfg --- config.go | 3 +- docs/release-notes/release-notes-0.18.0.md | 4 ++ lncfg/protocol.go | 48 ++++++++++++++++++++++ lncfg/protocol_experimental_off.go | 16 -------- lncfg/protocol_experimental_on.go | 42 ------------------- lncfg/protocol_integration.go | 48 ++++++++++++++++++++++ sample-lnd.conf | 33 +++++++++++++++ server.go | 2 +- 8 files changed, 135 insertions(+), 61 deletions(-) diff --git a/config.go b/config.go index a8b609deb..13fd2c832 100644 --- a/config.go +++ b/config.go @@ -1667,8 +1667,7 @@ func ValidateConfig(cfg Config, interceptor signal.Interceptor, fileParser, // If the experimental protocol options specify any protocol messages // that we want to handle as custom messages, set them now. - //nolint:lll - customMsg := cfg.ProtocolOptions.ExperimentalProtocol.CustomMessageOverrides() + customMsg := cfg.ProtocolOptions.CustomMessageOverrides() // We can safely set our custom override values during startup because // startup is blocked on config parsing. diff --git a/docs/release-notes/release-notes-0.18.0.md b/docs/release-notes/release-notes-0.18.0.md index 3b130b983..745535f9d 100644 --- a/docs/release-notes/release-notes-0.18.0.md +++ b/docs/release-notes/release-notes-0.18.0.md @@ -317,6 +317,10 @@ * [Add inbound fees](https://github.com/lightningnetwork/lnd/pull/8723) to `subscribeChannelGraph`. +* [Moved](https://github.com/lightningnetwork/lnd/pull/8744) the experimental + "custom" options to the main protocol config so that they can be used without + the dev build flag set. + ### Logging * [Add the htlc amount](https://github.com/lightningnetwork/lnd/pull/8156) to contract court logs in case of timed-out HTLCs in order to easily spot dust diff --git a/lncfg/protocol.go b/lncfg/protocol.go index e98b4dcf8..d86613188 100644 --- a/lncfg/protocol.go +++ b/lncfg/protocol.go @@ -2,6 +2,11 @@ package lncfg +import ( + "github.com/lightningnetwork/lnd/feature" + "github.com/lightningnetwork/lnd/lnwire" +) + // ProtocolOptions is a struct that we use to be able to test backwards // compatibility of protocol additions, while defaulting to the latest within // lnd, or to enable experimental protocol changes. @@ -57,6 +62,23 @@ type ProtocolOptions struct { // NoRouteBlindingOption disables forwarding of payments in blinded routes. NoRouteBlindingOption bool `long:"no-route-blinding" description:"do not forward payments that are a part of a blinded route"` + + // CustomMessage allows the custom message APIs to handle messages with + // the provided protocol numbers, which fall outside the custom message + // number range. + CustomMessage []uint16 `long:"custom-message" description:"allows the custom message apis to send and report messages with the protocol number provided that fall outside of the custom message number range."` + + // CustomInit specifies feature bits to advertise in the node's init + // message. + CustomInit []uint16 `long:"custom-init" description:"custom feature bits — numbers defined in BOLT 9 — to advertise in the node's init message"` + + // CustomNodeAnn specifies custom feature bits to advertise in the + // node's announcement message. + CustomNodeAnn []uint16 `long:"custom-nodeann" description:"custom feature bits — numbers defined in BOLT 9 — to advertise in the node's announcement message"` + + // CustomInvoice specifies custom feature bits to advertise in the + // node's invoices. + CustomInvoice []uint16 `long:"custom-invoice" description:"custom feature bits — numbers defined in BOLT 9 — to advertise in the node's invoices"` } // Wumbo returns true if lnd should permit the creation and acceptance of wumbo @@ -105,3 +127,29 @@ func (l *ProtocolOptions) NoTimestampsQuery() bool { func (l *ProtocolOptions) NoRouteBlinding() bool { return l.NoRouteBlindingOption } + +// CustomMessageOverrides returns the set of protocol messages that we override +// to allow custom handling. +func (p ProtocolOptions) CustomMessageOverrides() []uint16 { + return p.CustomMessage +} + +// CustomFeatures returns a custom set of feature bits to advertise. +func (p ProtocolOptions) CustomFeatures() map[feature.Set][]lnwire.FeatureBit { + customFeatures := make(map[feature.Set][]lnwire.FeatureBit) + + setFeatures := func(set feature.Set, bits []uint16) { + for _, customFeature := range bits { + customFeatures[set] = append( + customFeatures[set], + lnwire.FeatureBit(customFeature), + ) + } + } + + setFeatures(feature.SetInit, p.CustomInit) + setFeatures(feature.SetNodeAnn, p.CustomNodeAnn) + setFeatures(feature.SetInvoice, p.CustomInvoice) + + return customFeatures +} diff --git a/lncfg/protocol_experimental_off.go b/lncfg/protocol_experimental_off.go index 51c90ec38..34143a224 100644 --- a/lncfg/protocol_experimental_off.go +++ b/lncfg/protocol_experimental_off.go @@ -3,23 +3,7 @@ package lncfg -import ( - "github.com/lightningnetwork/lnd/feature" - "github.com/lightningnetwork/lnd/lnwire" -) - // ExperimentalProtocol is a sub-config that houses any experimental protocol // features that also require a build-tag to activate. type ExperimentalProtocol struct { } - -// CustomMessageOverrides returns the set of protocol messages that we override -// to allow custom handling. -func (p ExperimentalProtocol) CustomMessageOverrides() []uint16 { - return nil -} - -// CustomFeatures returns a custom set of feature bits to advertise. -func (p ExperimentalProtocol) CustomFeatures() map[feature.Set][]lnwire.FeatureBit { - return map[feature.Set][]lnwire.FeatureBit{} -} diff --git a/lncfg/protocol_experimental_on.go b/lncfg/protocol_experimental_on.go index bb23e83c2..b7d74acfe 100644 --- a/lncfg/protocol_experimental_on.go +++ b/lncfg/protocol_experimental_on.go @@ -3,49 +3,7 @@ package lncfg -import ( - "github.com/lightningnetwork/lnd/feature" - "github.com/lightningnetwork/lnd/lnwire" -) - // ExperimentalProtocol is a sub-config that houses any experimental protocol // features that also require a build-tag to activate. -// -//nolint:lll type ExperimentalProtocol struct { - CustomMessage []uint16 `long:"custom-message" description:"allows the custom message apis to send and report messages with the protocol number provided that fall outside of the custom message number range."` - - CustomInit []uint16 `long:"custom-init" description:"custom feature bits to advertise in the node's init message"` - - CustomNodeAnn []uint16 `long:"custom-nodeann" description:"custom feature bits to advertise in the node's announcement message"` - - CustomInvoice []uint16 `long:"custom-invoice" description:"custom feature bits to advertise in the node's invoices"` -} - -// CustomMessageOverrides returns the set of protocol messages that we override -// to allow custom handling. -func (p ExperimentalProtocol) CustomMessageOverrides() []uint16 { - return p.CustomMessage -} - -// CustomFeatures returns a custom set of feature bits to advertise. -// -//nolint:lll -func (p ExperimentalProtocol) CustomFeatures() map[feature.Set][]lnwire.FeatureBit { - customFeatures := make(map[feature.Set][]lnwire.FeatureBit) - - setFeatures := func(set feature.Set, bits []uint16) { - for _, customFeature := range bits { - customFeatures[set] = append( - customFeatures[set], - lnwire.FeatureBit(customFeature), - ) - } - } - - setFeatures(feature.SetInit, p.CustomInit) - setFeatures(feature.SetNodeAnn, p.CustomNodeAnn) - setFeatures(feature.SetInvoice, p.CustomInvoice) - - return customFeatures } diff --git a/lncfg/protocol_integration.go b/lncfg/protocol_integration.go index 841f8e9eb..e568b6b9a 100644 --- a/lncfg/protocol_integration.go +++ b/lncfg/protocol_integration.go @@ -2,6 +2,11 @@ package lncfg +import ( + "github.com/lightningnetwork/lnd/feature" + "github.com/lightningnetwork/lnd/lnwire" +) + // ProtocolOptions is a struct that we use to be able to test backwards // compatibility of protocol additions, while defaulting to the latest within // lnd, or to enable experimental protocol changes. @@ -60,6 +65,23 @@ type ProtocolOptions struct { // NoRouteBlindingOption disables forwarding of payments in blinded routes. NoRouteBlindingOption bool `long:"no-route-blinding" description:"do not forward payments that are a part of a blinded route"` + + // CustomMessage allows the custom message APIs to handle messages with + // the provided protocol numbers, which fall outside the custom message + // number range. + CustomMessage []uint16 `long:"custom-message" description:"allows the custom message apis to send and report messages with the protocol number provided that fall outside of the custom message number range."` + + // CustomInit specifies feature bits to advertise in the node's init + // message. + CustomInit []uint16 `long:"custom-init" description:"custom feature bits to advertise in the node's init message"` + + // CustomNodeAnn specifies custom feature bits to advertise in the + // node's announcement message. + CustomNodeAnn []uint16 `long:"custom-nodeann" description:"custom feature bits to advertise in the node's announcement message"` + + // CustomInvoice specifies custom feature bits to advertise in the + // node's invoices. + CustomInvoice []uint16 `long:"custom-invoice" description:"custom feature bits to advertise in the node's invoices"` } // Wumbo returns true if lnd should permit the creation and acceptance of wumbo @@ -100,3 +122,29 @@ func (l *ProtocolOptions) NoAnySegwit() bool { func (l *ProtocolOptions) NoRouteBlinding() bool { return l.NoRouteBlindingOption } + +// CustomMessageOverrides returns the set of protocol messages that we override +// to allow custom handling. +func (l ProtocolOptions) CustomMessageOverrides() []uint16 { + return l.CustomMessage +} + +// CustomFeatures returns a custom set of feature bits to advertise. +func (l ProtocolOptions) CustomFeatures() map[feature.Set][]lnwire.FeatureBit { + customFeatures := make(map[feature.Set][]lnwire.FeatureBit) + + setFeatures := func(set feature.Set, bits []uint16) { + for _, customFeature := range bits { + customFeatures[set] = append( + customFeatures[set], + lnwire.FeatureBit(customFeature), + ) + } + } + + setFeatures(feature.SetInit, l.CustomInit) + setFeatures(feature.SetNodeAnn, l.CustomNodeAnn) + setFeatures(feature.SetInvoice, l.CustomInvoice) + + return customFeatures +} diff --git a/sample-lnd.conf b/sample-lnd.conf index 2783c58fd..d133adfd3 100644 --- a/sample-lnd.conf +++ b/sample-lnd.conf @@ -1306,6 +1306,39 @@ ; Set to disable blinded route forwarding. ; protocol.no-route-blinding=false +; Set to handle messages of a particular type that falls outside of the +; custom message number range (i.e. 513 is onion messages). Note that you can +; set this option as many times as you want to support more than one custom +; message type. +; Default: +; protocol.custom-message= +; Example: +; protocol.custom-message=513 + +; Specifies feature bits — numbers defined in BOLT 9 — to advertise in the +; node's init message. Note that you can set this option as many times as you +; want to support more than one feature bit. +; Default: +; protocol.custom-init= +; Example: +; protocol.custom-init=39 + +; Specifies custom feature bits — numbers defined in BOLT 9 — to advertise in +; the node's announcement message. Note that you can set this option as many +; times as you want to support more than one feature bit. +; Default: +; protocol.custom-nodeann= +; Example: +; protocol.custom-nodeann=39 + +; Specifies custom feature bits — numbers defined in BOLT 9 — to advertise in +; the node's invoices. Note that you can set this option as many times as you +; want to support more than one feature bit. +; Default: +; protocol.custom-invoice= +; Example: +; protocol.custom-invoice=39 + [db] ; The selected database backend. The current default backend is "bolt". lnd diff --git a/server.go b/server.go index 627f0c0f3..2b54f81d6 100644 --- a/server.go +++ b/server.go @@ -547,7 +547,7 @@ func newServer(cfg *Config, listenAddrs []net.Addr, NoOptionScidAlias: !cfg.ProtocolOptions.ScidAlias(), NoZeroConf: !cfg.ProtocolOptions.ZeroConf(), NoAnySegwit: cfg.ProtocolOptions.NoAnySegwit(), - CustomFeatures: cfg.ProtocolOptions.ExperimentalProtocol.CustomFeatures(), + CustomFeatures: cfg.ProtocolOptions.CustomFeatures(), NoTaprootChans: !cfg.ProtocolOptions.TaprootChans, NoRouteBlinding: cfg.ProtocolOptions.NoRouteBlinding(), }) From 2906b8b20c16a74ad164b57267628775af2eb075 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Tue, 14 May 2024 01:55:38 +0800 Subject: [PATCH 088/109] sweep: update and fix README --- sweep/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sweep/README.md b/sweep/README.md index 487ebdcdd..279725474 100644 --- a/sweep/README.md +++ b/sweep/README.md @@ -82,7 +82,8 @@ flowchart LR deadline together. Inputs with the same deadline express the same time sensitivity so it makes sense to sweep them in the same transaction. Once grouped, inputs in each batch are sorted based on their budgets. The only -exception is inputs with `ExclusiveGroup` flag set, which will be swept alone. +exception is inputs with the `ExclusiveGroup` flag set, which will be swept +alone. Once the batching is finished, an `InputSet` is returned, which is an interface used to decide whether a wallet UTXO is needed or not when creating the @@ -91,11 +92,10 @@ the sum of the output values from these inputs against the sum of their budgets - if the total budget cannot be covered, one or more wallet UTXOs are needed. -For instance, when anchor output is swept to perform a CPFP, one or more wallet -UTXOs are likely to be used to meet the specified budget, which is also the -case when sweeping second-level HTLC transactions. However, if the sweeping -transaction also contains other to-be-swept inputs, a wallet UTXO is no longer -needed if their values can cover the total budget. +For instance, commitment and HTLC transactions usually have some proportion of +their outputs timelocked, preventing them from being used to pay fees +immediately. For these transactions, wallet UTXOs are often needed to get them +confirmed in a timely manner. #### `Bumper` @@ -144,7 +144,7 @@ initialized with: - a starting fee rate of 10 sat/vB, which is the result from calling `estimatesmartfee 1000`. - an ending fee rate of 400 sat/vB, which is the result of `200,000/500`. -- a fee rate delta of 390 sat/kvB, which is the result of `(400 - 10) / 500 * +- a fee rate delta of 390 sat/kvB, which is the result of `(400 - 10) / 1000 * 1000`. ## Sweeping Outputs from a Force Close Transaction From 1470adbed241f5c24cb367da79a841f1c9eb79a3 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Tue, 14 May 2024 16:55:45 +0800 Subject: [PATCH 089/109] contractcourt: share deadlines between CPFP anchors and HTLCs This commit changes how the deadline is calculated for CPFP anchor sweeping. In order to sweep the second-level HTLCs, we need to first get the FC tx confirmed. If we use a larger conf target for CPFP, we'd end up having few blocks to sweep the HTLCs, as these two sweeping txns share the deadline of the HTLC, as shown below, ``` More aggressive on the CPFP part. |-CPFP-|-----HTLC-----| Share the deadlines evenly. |---CPFP---|---HTLC---| More aggressive on the HTLC part. |-----CPFP-----|-HTLC-| ``` In this commit, we decide to share the deadlines evenly as a starting point so neither side will have a short of deadlines. --- contractcourt/channel_arbitrator.go | 39 ++++++-- contractcourt/channel_arbitrator_test.go | 118 +++++++++++++++++------ 2 files changed, 120 insertions(+), 37 deletions(-) diff --git a/contractcourt/channel_arbitrator.go b/contractcourt/channel_arbitrator.go index 64d062e99..f9df71c19 100644 --- a/contractcourt/channel_arbitrator.go +++ b/contractcourt/channel_arbitrator.go @@ -1436,9 +1436,13 @@ func (c *ChannelArbitrator) sweepAnchors(anchors *lnwallet.AnchorResolutions, // findCommitmentDeadlineAndValue finds the deadline (relative block height) // for a commitment transaction by extracting the minimum CLTV from its HTLCs. -// From our PoV, the deadline is defined to be the smaller of, -// - the least CLTV from outgoing HTLCs, or, -// - the least CLTV from incoming HTLCs if the preimage is available. +// From our PoV, the deadline delta is defined to be the smaller of, +// - half of the least CLTV from outgoing HTLCs' corresponding incoming +// HTLCs, or, +// - half of the least CLTV from incoming HTLCs if the preimage is available. +// +// We use half of the CTLV value to ensure that we have enough time to sweep +// the second-level HTLCs. // // It also finds the total value that are time-sensitive, which is the sum of // all the outgoing HTLCs plus incoming HTLCs whose preimages are known. It @@ -1468,10 +1472,24 @@ func (c *ChannelArbitrator) findCommitmentDeadlineAndValue(heightHint uint32, } value := htlc.Amt.ToSatoshis() - totalValue += value - if htlc.RefundTimeout < deadlineMinHeight { - deadlineMinHeight = htlc.RefundTimeout + // Find the expiry height for this outgoing HTLC's incoming + // HTLC. + deadlineOpt := c.cfg.FindOutgoingHTLCDeadline(htlc) + + // The deadline is default to the current deadlineMinHeight, + // and it's overwritten when it's not none. + deadline := deadlineMinHeight + deadlineOpt.WhenSome(func(d int32) { + deadline = uint32(d) + + // We only consider the value is under protection when + // it's time-sensitive. + totalValue += value + }) + + if deadline < deadlineMinHeight { + deadlineMinHeight = deadline log.Tracef("ChannelArbitrator(%v): outgoing HTLC has "+ "deadline=%v, value=%v", c.cfg.ChanPoint, @@ -1521,7 +1539,7 @@ func (c *ChannelArbitrator) findCommitmentDeadlineAndValue(heightHint uint32, // * none of the HTLCs are preimageAvailable. // - when our deadlineMinHeight is no greater than the heightHint, // which means we are behind our schedule. - deadline := deadlineMinHeight - heightHint + var deadline uint32 switch { // When we couldn't find a deadline height from our HTLCs, we will fall // back to the default value as there's no time pressure here. @@ -1535,6 +1553,11 @@ func (c *ChannelArbitrator) findCommitmentDeadlineAndValue(heightHint uint32, "deadlineMinHeight=%d, heightHint=%d", c.cfg.ChanPoint, deadlineMinHeight, heightHint) deadline = 1 + + // Use half of the deadline delta, and leave the other half to be used + // to sweep the HTLCs. + default: + deadline = (deadlineMinHeight - heightHint) / 2 } // Calculate the value left after subtracting the budget used for @@ -2800,7 +2823,7 @@ func (c *ChannelArbitrator) channelAttendant(bestHeight int32) { // state, so we'll get the most up to date signals to we can // properly do our job. case signalUpdate := <-c.signalUpdates: - log.Tracef("ChannelArbitrator(%v) got new signal "+ + log.Tracef("ChannelArbitrator(%v): got new signal "+ "update!", c.cfg.ChanPoint) // We'll update the ShortChannelID. diff --git a/contractcourt/channel_arbitrator_test.go b/contractcourt/channel_arbitrator_test.go index 77c9597c0..43238494e 100644 --- a/contractcourt/channel_arbitrator_test.go +++ b/contractcourt/channel_arbitrator_test.go @@ -2305,20 +2305,22 @@ func TestFindCommitmentDeadlineAndValue(t *testing.T) { } testCases := []struct { - name string - htlcs htlcSet - err error - deadline fn.Option[int32] - expectedBudget btcutil.Amount + name string + htlcs htlcSet + err error + deadline fn.Option[int32] + mockFindOutgoingHTLCDeadline func() + expectedBudget btcutil.Amount }{ { // When we have no HTLCs, the default value should be // used. - name: "use default conf target", - htlcs: htlcSet{}, - err: nil, - deadline: fn.None[int32](), - expectedBudget: 0, + name: "use default conf target", + htlcs: htlcSet{}, + err: nil, + deadline: fn.None[int32](), + mockFindOutgoingHTLCDeadline: func() {}, + expectedBudget: 0, }, { // When we have a preimage available in the local HTLC @@ -2329,8 +2331,17 @@ func TestFindCommitmentDeadlineAndValue(t *testing.T) { htlcs: makeHTLCSet(htlcPreimage, htlcLargeExpiry), err: nil, deadline: fn.Some(int32( - htlcPreimage.RefundTimeout - heightHint, + (htlcPreimage.RefundTimeout - heightHint) / 2, )), + mockFindOutgoingHTLCDeadline: func() { + chanArb.cfg.FindOutgoingHTLCDeadline = func( + htlc channeldb.HTLC) fn.Option[int32] { + + return fn.Some(int32( + htlcLargeExpiry.RefundTimeout, + )) + } + }, expectedBudget: htlcAmt.ToSatoshis(), }, { @@ -2342,8 +2353,18 @@ func TestFindCommitmentDeadlineAndValue(t *testing.T) { htlcs: makeHTLCSet(htlcSmallExipry, htlcLargeExpiry), err: nil, deadline: fn.Some(int32( - htlcLargeExpiry.RefundTimeout - heightHint, + (htlcLargeExpiry.RefundTimeout - + heightHint) / 2, )), + mockFindOutgoingHTLCDeadline: func() { + chanArb.cfg.FindOutgoingHTLCDeadline = func( + htlc channeldb.HTLC) fn.Option[int32] { + + return fn.Some(int32( + htlcLargeExpiry.RefundTimeout, + )) + } + }, expectedBudget: htlcAmt.ToSatoshis() / 2, }, { @@ -2354,18 +2375,36 @@ func TestFindCommitmentDeadlineAndValue(t *testing.T) { htlcs: makeHTLCSet(htlcPreimage, htlcDust), err: nil, deadline: fn.Some(int32( - htlcPreimage.RefundTimeout - heightHint, + (htlcPreimage.RefundTimeout - heightHint) / 2, )), + mockFindOutgoingHTLCDeadline: func() { + chanArb.cfg.FindOutgoingHTLCDeadline = func( + htlc channeldb.HTLC) fn.Option[int32] { + + return fn.Some(int32( + htlcDust.RefundTimeout, + )) + } + }, expectedBudget: htlcAmt.ToSatoshis() / 2, }, { // When we've reached our deadline, use conf target of // 1 as our deadline. And the value left should be // htlcAmt. - name: "use conf target 1", - htlcs: makeHTLCSet(htlcPreimage, htlcExpired), - err: nil, - deadline: fn.Some(int32(1)), + name: "use conf target 1", + htlcs: makeHTLCSet(htlcPreimage, htlcExpired), + err: nil, + deadline: fn.Some(int32(1)), + mockFindOutgoingHTLCDeadline: func() { + chanArb.cfg.FindOutgoingHTLCDeadline = func( + htlc channeldb.HTLC) fn.Option[int32] { + + return fn.Some(int32( + htlcExpired.RefundTimeout, + )) + } + }, expectedBudget: htlcAmt.ToSatoshis(), }, } @@ -2373,7 +2412,9 @@ func TestFindCommitmentDeadlineAndValue(t *testing.T) { for _, tc := range testCases { tc := tc t.Run(tc.name, func(t *testing.T) { - t.Parallel() + // Mock the method `FindOutgoingHTLCDeadline`. + tc.mockFindOutgoingHTLCDeadline() + deadline, budget, err := chanArb. findCommitmentDeadlineAndValue( heightHint, tc.htlcs, @@ -2412,31 +2453,35 @@ func TestSweepAnchors(t *testing.T) { chanArbCtx.chanArb.blocks <- int32(heightHint) htlcIndexBase := uint64(99) - htlcExpiryBase := heightHint + uint32(10) + deadlineDelta := uint32(10) htlcAmt := lnwire.MilliSatoshi(1_000_000) // Create three testing HTLCs. htlcDust := channeldb.HTLC{ HtlcIndex: htlcIndexBase + 1, - RefundTimeout: htlcExpiryBase + 1, + RefundTimeout: heightHint + 1, OutputIndex: -1, } + + deadlinePreimageDelta := deadlineDelta + 2 htlcWithPreimage := channeldb.HTLC{ HtlcIndex: htlcIndexBase + 2, - RefundTimeout: htlcExpiryBase + 2, + RefundTimeout: heightHint + deadlinePreimageDelta, RHash: rHash, Amt: htlcAmt, } + + deadlineSmallDelta := deadlineDelta + 4 htlcSmallExipry := channeldb.HTLC{ HtlcIndex: htlcIndexBase + 3, - RefundTimeout: htlcExpiryBase + 3, + RefundTimeout: heightHint + deadlineSmallDelta, Amt: htlcAmt, } // Setup our local HTLC set such that we will use the HTLC's CLTV from // the incoming HTLC set. - expectedLocalDeadline := htlcWithPreimage.RefundTimeout + expectedLocalDeadline := heightHint + deadlinePreimageDelta/2 chanArb.activeHTLCs[LocalHtlcSet] = htlcSet{ incomingHTLCs: map[uint64]channeldb.HTLC{ htlcWithPreimage.HtlcIndex: htlcWithPreimage, @@ -2475,7 +2520,7 @@ func TestSweepAnchors(t *testing.T) { // Setup out pending remote HTLC set such that we will use the HTLC's // CLTV from the outgoing HTLC set. - expectedPendingDeadline := htlcSmallExipry.RefundTimeout + expectedPendingDeadline := heightHint + deadlineSmallDelta/2 chanArb.activeHTLCs[RemotePendingHtlcSet] = htlcSet{ incomingHTLCs: map[uint64]channeldb.HTLC{ htlcDust.HtlcIndex: htlcDust, @@ -2493,6 +2538,18 @@ func TestSweepAnchors(t *testing.T) { }, } + // Mock FindOutgoingHTLCDeadline so the pending remote's outgoing HTLC + // returns the small expiry value. + chanArb.cfg.FindOutgoingHTLCDeadline = func( + htlc channeldb.HTLC) fn.Option[int32] { + + if htlc.RHash != htlcSmallExipry.RHash { + return fn.None[int32]() + } + + return fn.Some(int32(htlcSmallExipry.RefundTimeout)) + } + // Create AnchorResolutions. anchors := &lnwallet.AnchorResolutions{ Local: &lnwallet.AnchorResolution{ @@ -2599,17 +2656,20 @@ func TestChannelArbitratorAnchors(t *testing.T) { htlcAmt := lnwire.MilliSatoshi(1_000_000) // Create testing HTLCs. - htlcExpiryBase := heightHint + uint32(10) + deadlineDelta := uint32(10) + deadlinePreimageDelta := deadlineDelta + 2 htlcWithPreimage := channeldb.HTLC{ HtlcIndex: 99, - RefundTimeout: htlcExpiryBase + 2, + RefundTimeout: heightHint + deadlinePreimageDelta, RHash: rHash, Incoming: true, Amt: htlcAmt, } + + deadlineHTLCdelta := deadlineDelta + 3 htlc := channeldb.HTLC{ HtlcIndex: 100, - RefundTimeout: htlcExpiryBase + 3, + RefundTimeout: heightHint + deadlineHTLCdelta, Amt: htlcAmt, } @@ -2755,11 +2815,11 @@ func TestChannelArbitratorAnchors(t *testing.T) { // to htlcWithPreimage's CLTV. require.Equal(t, 2, len(chanArbCtx.sweeper.deadlines)) require.EqualValues(t, - htlcWithPreimage.RefundTimeout, + heightHint+deadlinePreimageDelta/2, chanArbCtx.sweeper.deadlines[0], ) require.EqualValues(t, - htlcWithPreimage.RefundTimeout, + heightHint+deadlinePreimageDelta/2, chanArbCtx.sweeper.deadlines[1], ) } From ac5af483194cfcb565d0f7cadfb24e7b0f1e150a Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 17 May 2024 05:07:29 +0800 Subject: [PATCH 090/109] sweep: make sure the budget is used up at deadlineHeight-1 --- sweep/fee_function.go | 37 ++++---- sweep/fee_function_test.go | 173 +++++++++++++++++++++++++++---------- 2 files changed, 149 insertions(+), 61 deletions(-) diff --git a/sweep/fee_function.go b/sweep/fee_function.go index 1c783304c..cbf283e37 100644 --- a/sweep/fee_function.go +++ b/sweep/fee_function.go @@ -86,11 +86,14 @@ type LinearFeeFunction struct { currentFeeRate chainfee.SatPerKWeight // width is the number of blocks between the starting block height - // and the deadline block height. + // and the deadline block height minus one. + // + // NOTE: We do minus one from the conf target here because we want to + // max out the budget before the deadline height is reached. width uint32 - // position is the number of blocks between the starting block height - // and the current block height. + // position is the fee function's current position, given a width of w, + // a valid position should lie in range [0, w]. position uint32 // deltaFeeRate is the fee rate (msat/kw) increase per block. @@ -116,10 +119,10 @@ func NewLinearFeeFunction(maxFeeRate chainfee.SatPerKWeight, startingFeeRate fn.Option[chainfee.SatPerKWeight]) ( *LinearFeeFunction, error) { - // If the deadline has already been reached, there's nothing the fee - // function can do. In this case, we'll use the max fee rate - // immediately. - if confTarget == 0 { + // If the deadline is one block away or has already been reached, + // there's nothing the fee function can do. In this case, we'll use the + // max fee rate immediately. + if confTarget <= 1 { return &LinearFeeFunction{ startingFeeRate: maxFeeRate, endingFeeRate: maxFeeRate, @@ -129,7 +132,7 @@ func NewLinearFeeFunction(maxFeeRate chainfee.SatPerKWeight, l := &LinearFeeFunction{ endingFeeRate: maxFeeRate, - width: confTarget, + width: confTarget - 1, estimator: estimator, } @@ -153,18 +156,18 @@ func NewLinearFeeFunction(maxFeeRate chainfee.SatPerKWeight, // The starting and ending fee rates are in sat/kw, so we need to // convert them to msat/kw by multiplying by 1000. - delta := btcutil.Amount(end - start).MulF64(1000 / float64(confTarget)) + delta := btcutil.Amount(end - start).MulF64(1000 / float64(l.width)) l.deltaFeeRate = mSatPerKWeight(delta) // We only allow the delta to be zero if the width is one - when the // delta is zero, it means the starting and ending fee rates are the // same, which means there's nothing to increase, so any width greater // than 1 doesn't provide any utility. This could happen when the - // sweeper is offered to sweep an input that has passed its deadline. + // budget is too small. if l.deltaFeeRate == 0 && l.width != 1 { log.Errorf("Failed to init fee function: startingFeeRate=%v, "+ "endingFeeRate=%v, width=%v, delta=%v", start, end, - confTarget, l.deltaFeeRate) + l.width, l.deltaFeeRate) return nil, fmt.Errorf("fee rate delta is zero") } @@ -175,7 +178,7 @@ func NewLinearFeeFunction(maxFeeRate chainfee.SatPerKWeight, log.Debugf("Linear fee function initialized with startingFeeRate=%v, "+ "endingFeeRate=%v, width=%v, delta=%v", start, end, - confTarget, l.deltaFeeRate) + l.width, l.deltaFeeRate) return l, nil } @@ -211,12 +214,12 @@ func (l *LinearFeeFunction) IncreaseFeeRate(confTarget uint32) (bool, error) { newPosition := uint32(0) // Only calculate the new position when the conf target is less than - // the function's width - the width is the initial conf target, and we - // expect the current conf target to decrease over time. However, we + // the function's width - the width is the initial conf target-1, and + // we expect the current conf target to decrease over time. However, we // still allow the supplied conf target to be greater than the width, // and we won't increase the fee rate in that case. - if confTarget < l.width { - newPosition = l.width - confTarget + if confTarget < l.width+1 { + newPosition = l.width + 1 - confTarget log.Tracef("Increasing position from %v to %v", l.position, newPosition) } @@ -290,7 +293,7 @@ func (l *LinearFeeFunction) estimateFeeRate( // (1008), we will use the min relay fee instead. if confTarget >= chainfee.MaxBlockTarget { minFeeRate := l.estimator.RelayFeePerKW() - log.Debugf("Conf target %v is greater than max block target, "+ + log.Infof("Conf target %v is greater than max block target, "+ "using min relay fee rate %v", confTarget, minFeeRate) return minFeeRate, nil diff --git a/sweep/fee_function_test.go b/sweep/fee_function_test.go index 3b0832946..c278bb7f0 100644 --- a/sweep/fee_function_test.go +++ b/sweep/fee_function_test.go @@ -8,22 +8,20 @@ import ( "github.com/stretchr/testify/require" ) -// TestLinearFeeFunctionNew tests the NewLinearFeeFunction function. -func TestLinearFeeFunctionNew(t *testing.T) { +// TestLinearFeeFunctionNewMaxFeeRateUsed tests when the conf target is <= 1, +// the max fee rate is used. +func TestLinearFeeFunctionNewMaxFeeRateUsed(t *testing.T) { t.Parallel() rt := require.New(t) // Create a mock fee estimator. estimator := &chainfee.MockEstimator{} + defer estimator.AssertExpectations(t) // Create testing params. maxFeeRate := chainfee.SatPerKWeight(10000) - estimatedFeeRate := chainfee.SatPerKWeight(500) - minRelayFeeRate := chainfee.SatPerKWeight(100) - confTarget := uint32(6) noStartFeeRate := fn.None[chainfee.SatPerKWeight]() - startFeeRate := chainfee.SatPerKWeight(1000) // Assert init fee function with zero conf value will end up using the // max fee rate. @@ -36,23 +34,56 @@ func TestLinearFeeFunctionNew(t *testing.T) { rt.Equal(maxFeeRate, f.endingFeeRate) rt.Equal(maxFeeRate, f.currentFeeRate) - // When the fee estimator returns an error, it's returned. - // - // Mock the fee estimator to return an error. - estimator.On("EstimateFeePerKW", confTarget).Return( - chainfee.SatPerKWeight(0), errDummy).Once() + // Assert init fee function with conf of one will end up using the max + // fee rate. + f, err = NewLinearFeeFunction(maxFeeRate, 1, estimator, noStartFeeRate) + rt.NoError(err) + rt.NotNil(f) - f, err = NewLinearFeeFunction( - maxFeeRate, confTarget, estimator, noStartFeeRate, - ) - rt.ErrorIs(err, errDummy) - rt.Nil(f) + // Assert the internal state. + rt.Equal(maxFeeRate, f.startingFeeRate) + rt.Equal(maxFeeRate, f.endingFeeRate) + rt.Equal(maxFeeRate, f.currentFeeRate) +} - // When the starting feerate is greater than the ending feerate, the - // starting feerate is capped. +// TestLinearFeeFunctionNewZeroFeeRateDelta tests when the fee rate delta is +// zero, it will return an error except when the width is one. +func TestLinearFeeFunctionNewZeroFeeRateDelta(t *testing.T) { + t.Parallel() + + rt := require.New(t) + + // Create a mock fee estimator. + estimator := &chainfee.MockEstimator{} + defer estimator.AssertExpectations(t) + + // Create testing params. + maxFeeRate := chainfee.SatPerKWeight(10000) + estimatedFeeRate := chainfee.SatPerKWeight(500) + confTarget := uint32(6) + noStartFeeRate := fn.None[chainfee.SatPerKWeight]() + + // When the calculated fee rate delta is 0, an error should be returned + // when the width is not one. // // Mock the fee estimator to return the fee rate. - smallConf := uint32(1) + estimator.On("EstimateFeePerKW", confTarget).Return( + // The starting fee rate is the max fee rate. + maxFeeRate, nil).Once() + estimator.On("RelayFeePerKW").Return(estimatedFeeRate).Once() + + f, err := NewLinearFeeFunction( + maxFeeRate, confTarget, estimator, noStartFeeRate, + ) + rt.ErrorContains(err, "fee rate delta is zero") + rt.Nil(f) + + // When the calculated fee rate delta is 0, an error should NOT be + // returned when the width is one, and the starting feerate is capped + // at the max fee rate. + // + // Mock the fee estimator to return the fee rate. + smallConf := uint32(2) estimator.On("EstimateFeePerKW", smallConf).Return( // The fee rate is greater than the max fee rate. maxFeeRate+1, nil).Once() @@ -64,18 +95,41 @@ func TestLinearFeeFunctionNew(t *testing.T) { rt.NoError(err) rt.NotNil(f) - // When the calculated fee rate delta is 0, an error should be returned. - // - // Mock the fee estimator to return the fee rate. - estimator.On("EstimateFeePerKW", confTarget).Return( - // The starting fee rate is the max fee rate. - maxFeeRate, nil).Once() - estimator.On("RelayFeePerKW").Return(estimatedFeeRate).Once() + // Assert the internal state. + rt.Equal(maxFeeRate, f.startingFeeRate) + rt.Equal(maxFeeRate, f.endingFeeRate) + rt.Equal(maxFeeRate, f.currentFeeRate) + rt.Zero(f.deltaFeeRate) + rt.Equal(smallConf-1, f.width) +} - f, err = NewLinearFeeFunction( +// TestLinearFeeFunctionNewEsimator tests the NewLinearFeeFunction function +// properly reacts to the response or error returned from the fee estimator. +func TestLinearFeeFunctionNewEsimator(t *testing.T) { + t.Parallel() + + rt := require.New(t) + + // Create a mock fee estimator. + estimator := &chainfee.MockEstimator{} + defer estimator.AssertExpectations(t) + + // Create testing params. + maxFeeRate := chainfee.SatPerKWeight(10000) + minRelayFeeRate := chainfee.SatPerKWeight(100) + confTarget := uint32(6) + noStartFeeRate := fn.None[chainfee.SatPerKWeight]() + + // When the fee estimator returns an error, it's returned. + // + // Mock the fee estimator to return an error. + estimator.On("EstimateFeePerKW", confTarget).Return( + chainfee.SatPerKWeight(0), errDummy).Once() + + f, err := NewLinearFeeFunction( maxFeeRate, confTarget, estimator, noStartFeeRate, ) - rt.ErrorContains(err, "fee rate delta is zero") + rt.ErrorIs(err, errDummy) rt.Nil(f) // When the conf target is >= 1008, the min relay fee should be used. @@ -95,16 +149,36 @@ func TestLinearFeeFunctionNew(t *testing.T) { rt.Equal(maxFeeRate, f.endingFeeRate) rt.Equal(minRelayFeeRate, f.currentFeeRate) rt.NotZero(f.deltaFeeRate) - rt.Equal(largeConf, f.width) + rt.Equal(largeConf-1, f.width) +} + +// TestLinearFeeFunctionNewSuccess tests we can create the fee function +// successfully. +func TestLinearFeeFunctionNewSuccess(t *testing.T) { + t.Parallel() + + rt := require.New(t) + + // Create a mock fee estimator. + estimator := &chainfee.MockEstimator{} + defer estimator.AssertExpectations(t) + + // Create testing params. + maxFeeRate := chainfee.SatPerKWeight(10000) + estimatedFeeRate := chainfee.SatPerKWeight(500) + minRelayFeeRate := chainfee.SatPerKWeight(100) + confTarget := uint32(6) + noStartFeeRate := fn.None[chainfee.SatPerKWeight]() + startFeeRate := chainfee.SatPerKWeight(1000) // Check a successfully created fee function. // // Mock the fee estimator to return the fee rate. estimator.On("EstimateFeePerKW", confTarget).Return( estimatedFeeRate, nil).Once() - estimator.On("RelayFeePerKW").Return(estimatedFeeRate).Once() + estimator.On("RelayFeePerKW").Return(minRelayFeeRate).Once() - f, err = NewLinearFeeFunction( + f, err := NewLinearFeeFunction( maxFeeRate, confTarget, estimator, noStartFeeRate, ) rt.NoError(err) @@ -115,7 +189,7 @@ func TestLinearFeeFunctionNew(t *testing.T) { rt.Equal(maxFeeRate, f.endingFeeRate) rt.Equal(estimatedFeeRate, f.currentFeeRate) rt.NotZero(f.deltaFeeRate) - rt.Equal(confTarget, f.width) + rt.Equal(confTarget-1, f.width) // Check a successfully created fee function using the specified // starting fee rate. @@ -131,7 +205,10 @@ func TestLinearFeeFunctionNew(t *testing.T) { // Assert the customized starting fee rate is used. rt.Equal(startFeeRate, f.startingFeeRate) + rt.Equal(maxFeeRate, f.endingFeeRate) rt.Equal(startFeeRate, f.currentFeeRate) + rt.NotZero(f.deltaFeeRate) + rt.Equal(confTarget-1, f.width) } // TestLinearFeeFunctionFeeRateAtPosition checks the expected feerate is @@ -201,12 +278,13 @@ func TestLinearFeeFunctionIncrement(t *testing.T) { // Create a mock fee estimator. estimator := &chainfee.MockEstimator{} + defer estimator.AssertExpectations(t) // Create testing params. These params are chosen so the delta value is // 100. - maxFeeRate := chainfee.SatPerKWeight(1000) + maxFeeRate := chainfee.SatPerKWeight(900) estimatedFeeRate := chainfee.SatPerKWeight(100) - confTarget := uint32(9) + confTarget := uint32(9) // This means the width is 8. // Mock the fee estimator to return the fee rate. estimator.On("EstimateFeePerKW", confTarget).Return( @@ -219,8 +297,8 @@ func TestLinearFeeFunctionIncrement(t *testing.T) { ) rt.NoError(err) - // We now increase the position from 1 to 9. - for i := uint32(1); i <= confTarget; i++ { + // We now increase the position from 1 to 8. + for i := uint32(1); i <= confTarget-1; i++ { // Increase the fee rate. increased, err := f.Increment() rt.NoError(err) @@ -236,7 +314,7 @@ func TestLinearFeeFunctionIncrement(t *testing.T) { rt.Equal(estimatedFeeRate+delta, f.FeeRate()) } - // Now the position is at 9th, increase it again should give us an + // Now the position is at 8th, increase it again should give us an // error. increased, err := f.Increment() rt.ErrorIs(err, ErrMaxPosition) @@ -252,12 +330,13 @@ func TestLinearFeeFunctionIncreaseFeeRate(t *testing.T) { // Create a mock fee estimator. estimator := &chainfee.MockEstimator{} + defer estimator.AssertExpectations(t) // Create testing params. These params are chosen so the delta value is // 100. - maxFeeRate := chainfee.SatPerKWeight(1000) + maxFeeRate := chainfee.SatPerKWeight(900) estimatedFeeRate := chainfee.SatPerKWeight(100) - confTarget := uint32(9) + confTarget := uint32(9) // This means the width is 8. // Mock the fee estimator to return the fee rate. estimator.On("EstimateFeePerKW", confTarget).Return( @@ -281,9 +360,9 @@ func TestLinearFeeFunctionIncreaseFeeRate(t *testing.T) { rt.NoError(err) rt.False(increased) - // We now increase the fee rate from conf target 8 to 1 and assert we + // We now increase the fee rate from conf target 8 to 2 and assert we // get no error and true. - for i := uint32(1); i < confTarget; i++ { + for i := uint32(1); i < confTarget-1; i++ { // Increase the fee rate. increased, err := f.IncreaseFeeRate(confTarget - i) rt.NoError(err) @@ -299,11 +378,17 @@ func TestLinearFeeFunctionIncreaseFeeRate(t *testing.T) { rt.Equal(estimatedFeeRate+delta, f.FeeRate()) } - // Test that when we use a conf target of 0, we get the ending fee + // Test that when we use a conf target of 1, we get the ending fee // rate. - increased, err = f.IncreaseFeeRate(0) + increased, err = f.IncreaseFeeRate(1) rt.NoError(err) rt.True(increased) - rt.Equal(confTarget, f.position) + rt.Equal(confTarget-1, f.position) rt.Equal(maxFeeRate, f.currentFeeRate) + + // Test that when we use a conf target of 0, ErrMaxPosition is + // returned. + increased, err = f.IncreaseFeeRate(0) + rt.ErrorIs(err, ErrMaxPosition) + rt.False(increased) } From 38184e88c885bc43f03f60d8472645499184cde9 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Tue, 14 May 2024 20:47:57 +0800 Subject: [PATCH 091/109] sweep: check all states in `TestMarkInputsPublishFailed` --- sweep/sweeper_test.go | 63 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/sweep/sweeper_test.go b/sweep/sweeper_test.go index e25864bcb..667906de9 100644 --- a/sweep/sweeper_test.go +++ b/sweep/sweeper_test.go @@ -206,7 +206,7 @@ func TestMarkInputsPublishFailed(t *testing.T) { Store: mockStore, }) - // Create three testing inputs. + // Create testing inputs for each state. // // inputNotExist specifies an input that's not found in the sweeper's // `inputs` map. @@ -240,18 +240,52 @@ func TestMarkInputsPublishFailed(t *testing.T) { state: Published, } + // inputPublishFailed specifies an input that's failed to be published. + inputPublishFailed := &wire.TxIn{ + PreviousOutPoint: wire.OutPoint{Index: 5}, + } + s.inputs[inputPublishFailed.PreviousOutPoint] = &SweeperInput{ + state: PublishFailed, + } + + // inputSwept specifies an input that's swept. + inputSwept := &wire.TxIn{ + PreviousOutPoint: wire.OutPoint{Index: 6}, + } + s.inputs[inputSwept.PreviousOutPoint] = &SweeperInput{ + state: Swept, + } + + // inputExcluded specifies an input that's excluded. + inputExcluded := &wire.TxIn{ + PreviousOutPoint: wire.OutPoint{Index: 7}, + } + s.inputs[inputExcluded.PreviousOutPoint] = &SweeperInput{ + state: Excluded, + } + + // inputFailed specifies an input that's failed. + inputFailed := &wire.TxIn{ + PreviousOutPoint: wire.OutPoint{Index: 8}, + } + s.inputs[inputFailed.PreviousOutPoint] = &SweeperInput{ + state: Failed, + } + + // Gather all inputs' outpoints. + pendingOps := make([]wire.OutPoint, 0, len(s.inputs)+1) + for op := range s.inputs { + pendingOps = append(pendingOps, op) + } + pendingOps = append(pendingOps, inputNotExist.PreviousOutPoint) + // Mark the test inputs. We expect the non-exist input and the // inputInit to be skipped, and the final input to be marked as // published. - s.markInputsPublishFailed([]wire.OutPoint{ - inputNotExist.PreviousOutPoint, - inputInit.PreviousOutPoint, - inputPendingPublish.PreviousOutPoint, - inputPublished.PreviousOutPoint, - }) + s.markInputsPublishFailed(pendingOps) // We expect unchanged number of pending inputs. - require.Len(s.inputs, 3) + require.Len(s.inputs, 7) // We expect the init input's state to stay unchanged. require.Equal(Init, @@ -266,6 +300,19 @@ func TestMarkInputsPublishFailed(t *testing.T) { require.Equal(PublishFailed, s.inputs[inputPublished.PreviousOutPoint].state) + // We expect the publish failed input to stay unchanged. + require.Equal(PublishFailed, + s.inputs[inputPublishFailed.PreviousOutPoint].state) + + // We expect the swept input to stay unchanged. + require.Equal(Swept, s.inputs[inputSwept.PreviousOutPoint].state) + + // We expect the excluded input to stay unchanged. + require.Equal(Excluded, s.inputs[inputExcluded.PreviousOutPoint].state) + + // We expect the failed input to stay unchanged. + require.Equal(Failed, s.inputs[inputFailed.PreviousOutPoint].state) + // Assert mocked statements are executed as expected. mockStore.AssertExpectations(t) } From e68c0235c6a95ba3950d2fdac35507ef100e51d3 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Wed, 15 May 2024 23:15:26 +0800 Subject: [PATCH 092/109] itest: add new itests to check CPFP anchor sweeping behavior Replaced `testSweepAnchorCPFPLocalForceClose` with dedicated tests. --- itest/list_on_test.go | 8 +- itest/lnd_sweep_test.go | 705 ++++++++++++++++++++++++++++++---------- 2 files changed, 547 insertions(+), 166 deletions(-) diff --git a/itest/list_on_test.go b/itest/list_on_test.go index 2434ee92d..1c563aa20 100644 --- a/itest/list_on_test.go +++ b/itest/list_on_test.go @@ -611,8 +611,12 @@ var allTestCases = []*lntest.TestCase{ TestFunc: testNativeSQLNoMigration, }, { - Name: "sweep anchor cpfp local force close", - TestFunc: testSweepAnchorCPFPLocalForceClose, + Name: "sweep cpfp anchor outgoing timeout", + TestFunc: testSweepCPFPAnchorOutgoingTimeout, + }, + { + Name: "sweep cpfp anchor incoming timeout", + TestFunc: testSweepCPFPAnchorIncomingTimeout, }, { Name: "sweep htlcs", diff --git a/itest/lnd_sweep_test.go b/itest/lnd_sweep_test.go index 56d25b4f9..b79dda521 100644 --- a/itest/lnd_sweep_test.go +++ b/itest/lnd_sweep_test.go @@ -24,126 +24,159 @@ import ( "github.com/stretchr/testify/require" ) -// testSweepAnchorCPFPLocalForceClose checks when a channel is force closed by -// a local node with a time-sensitive HTLC, the anchor output is used for -// CPFPing the force close tx. +// testSweepCPFPAnchorOutgoingTimeout checks when a channel is force closed by +// a local node due to the outgoing HTLC times out, the anchor output is used +// for CPFPing the force close tx. // // Setup: -// 1. Fund Alice with 2 UTXOs - she will need two to sweep her anchors from -// the local and remote commitments, with one of them being invalid. -// 2. Fund Bob with no UTXOs - his sweeping txns don't need wallet utxos as he -// doesn't need to sweep any time-sensitive outputs. -// 3. Alice opens a channel with Bob, and sends him an HTLC without being -// settled - we achieve this by letting Bob hold the preimage, which means -// he will consider his incoming HTLC has no preimage. -// 4. Alice force closes the channel. +// 1. Fund Alice with 1 UTXO - she only needs one for the funding process, +// 2. Fund Bob with 1 UTXO - he only needs one for the funding process, and +// the change output will be used for sweeping his anchor on local commit. +// 3. Create a linear network from Alice -> Bob -> Carol. +// 4. Alice pays an invoice to Carol through Bob, with Carol holding the +// settlement. +// 5. Carol goes offline. // // Test: -// 1. Alice's force close tx should be CPFPed using the anchor output. -// 2. Bob attempts to sweep his anchor output and fails due to it's -// uneconomical. -// 3. Alice's RBF attempt is using the fee rates calculated from the deadline -// and budget. -// 4. Wallet UTXOs requirements are met - for Alice she needs at least 2, and -// Bob he needs none. -func testSweepAnchorCPFPLocalForceClose(ht *lntest.HarnessTest) { - // Setup testing params for Alice. +// 1. Bob force closes the channel with Carol, using the anchor output for +// CPFPing the force close tx. +// 2. Bob's anchor output is swept and fee bumped based on its deadline and +// budget. +func testSweepCPFPAnchorOutgoingTimeout(ht *lntest.HarnessTest) { + // Setup testing params. // - // startFeeRate is returned by the fee estimator in sat/kw. This - // will be used as the starting fee rate for the linear fee func used - // by Alice. - startFeeRate := chainfee.SatPerKWeight(2000) + // Invoice is 100k sats. + invoiceAmt := btcutil.Amount(100_000) - // deadline is the expected deadline for the CPFP transaction. - deadline := uint32(10) + // Use the smallest CLTV so we can mine fewer blocks. + cltvDelta := routing.MinCLTVDelta + + // deadlineDeltaAnchor is the expected deadline delta for the CPFP + // anchor sweeping tx. + deadlineDeltaAnchor := uint32(cltvDelta / 2) + + // startFeeRateAnchor is the starting fee rate for the CPFP anchor + // sweeping tx. + startFeeRateAnchor := chainfee.SatPerKWeight(2500) // Set up the fee estimator to return the testing fee rate when the // conf target is the deadline. - ht.SetFeeEstimateWithConf(startFeeRate, deadline) - - // Calculate the final ctlv delta based on the expected deadline. - finalCltvDelta := int32(deadline - uint32(routing.BlockPadding) + 1) - - // toLocalCSV is the CSV delay for Alice's to_local output. This value - // is chosen so the commit sweep happens after the anchor sweep, - // enabling us to focus on checking the fees in CPFP here. - toLocalCSV := deadline * 2 - - // htlcAmt is the amount of the HTLC in sats. With default settings, - // this will give us 25000 sats as the budget to sweep the CPFP anchor - // output. - htlcAmt := btcutil.Amount(100_000) - - // Calculate the budget. Since it's a time-sensitive HTLC, we will use - // its value after subtracting its own budget as the CPFP budget. - valueLeft := htlcAmt.MulF64(1 - contractcourt.DefaultBudgetRatio) - budget := valueLeft.MulF64(1 - contractcourt.DefaultBudgetRatio) - - // We now set up testing params for Bob. // - // bobBalance is the push amount when Alice opens the channel with Bob. - // We will use zero here so we can focus on testing the CPFP logic from - // Alice's side here. - bobBalance := btcutil.Amount(0) + // TODO(yy): switch to conf when `blockbeat` is in place. + // ht.SetFeeEstimateWithConf(startFeeRateAnchor, deadlineDeltaAnchor) + ht.SetFeeEstimate(startFeeRateAnchor) - // Make sure our assumptions and calculations are correct. - require.EqualValues(ht, 25000, budget) + // htlcValue is the outgoing HTLC's value. + htlcValue := invoiceAmt - // We now set up the force close scenario. Alice will open a channel - // with Bob, send an HTLC, and then force close it with a - // time-sensitive outgoing HTLC. + // htlcBudget is the budget used to sweep the outgoing HTLC. + htlcBudget := htlcValue.MulF64(contractcourt.DefaultBudgetRatio) + + // cpfpBudget is the budget used to sweep the CPFP anchor. + cpfpBudget := (htlcValue - htlcBudget).MulF64( + contractcourt.DefaultBudgetRatio, + ) + + // Create a preimage, that will be held by Carol. + var preimage lntypes.Preimage + copy(preimage[:], ht.Random32Bytes()) + payHash := preimage.Hash() + + // We now set up the force close scenario. We will create a network + // from Alice -> Bob -> Carol, where Alice will send a payment to Carol + // via Bob, Carol goes offline. We expect Bob to sweep his anchor and + // outgoing HTLC. // - // Prepare node params. + // Prepare params. cfg := []string{ - "--hodl.exit-settle", "--protocol.anchors", + // Use a small CLTV to mine less blocks. + fmt.Sprintf("--bitcoin.timelockdelta=%d", cltvDelta), // Use a very large CSV, this way to_local outputs are never // swept so we can focus on testing HTLCs. - fmt.Sprintf("--bitcoin.defaultremotedelay=%v", toLocalCSV), + fmt.Sprintf("--bitcoin.defaultremotedelay=%v", cltvDelta*10), } openChannelParams := lntest.OpenChannelParams{ - Amt: htlcAmt * 10, - PushAmt: bobBalance, + Amt: invoiceAmt * 10, } - // Create a two hop network: Alice -> Bob. - chanPoints, nodes := createSimpleNetwork(ht, cfg, 2, openChannelParams) + // Create a three hop network: Alice -> Bob -> Carol. + chanPoints, nodes := createSimpleNetwork(ht, cfg, 3, openChannelParams) // Unwrap the results. - chanPoint := chanPoints[0] - alice, bob := nodes[0], nodes[1] + abChanPoint, bcChanPoint := chanPoints[0], chanPoints[1] + alice, bob, carol := nodes[0], nodes[1], nodes[2] - // Send one more utxo to Alice - she will need two utxos to sweep the - // anchor output living on the local and remote commits. - ht.FundCoins(btcutil.SatoshiPerBitcoin, alice) + // For neutrino backend, we need one more UTXO for Bob to create his + // sweeping txns. + if ht.IsNeutrinoBackend() { + ht.FundCoins(btcutil.SatoshiPerBitcoin, bob) + } - // Send a payment with a specified finalCTLVDelta, which will be used - // as our deadline later on when Alice force closes the channel. + // Subscribe the invoice. + streamCarol := carol.RPC.SubscribeSingleInvoice(payHash[:]) + + // With the network active, we'll now add a hodl invoice at Carol's + // end. + invoiceReq := &invoicesrpc.AddHoldInvoiceRequest{ + Value: int64(invoiceAmt), + CltvExpiry: finalCltvDelta, + Hash: payHash[:], + } + invoice := carol.RPC.AddHoldInvoice(invoiceReq) + + // Let Alice pay the invoices. req := &routerrpc.SendPaymentRequest{ - Dest: bob.PubKey[:], - Amt: int64(htlcAmt), - PaymentHash: ht.Random32Bytes(), - FinalCltvDelta: finalCltvDelta, + PaymentRequest: invoice.PaymentRequest, TimeoutSeconds: 60, FeeLimitMsat: noFeeLimitMsat, } - alice.RPC.SendPayment(req) - // Once the HTLC has cleared, all the nodes in our mini network should - // show that the HTLC has been locked in. - ht.AssertNumActiveHtlcs(alice, 1) - ht.AssertNumActiveHtlcs(bob, 1) + // Assert the payments are inflight. + ht.SendPaymentAndAssertStatus(alice, req, lnrpc.Payment_IN_FLIGHT) - // Alice force closes the channel. - _, closeTxid := ht.CloseChannelAssertPending(alice, chanPoint, true) + // Wait for Carol to mark invoice as accepted. There is a small gap to + // bridge between adding the htlc to the channel and executing the exit + // hop logic. + ht.AssertInvoiceState(streamCarol, lnrpc.Invoice_ACCEPTED) - // Now that the channel has been force closed, it should show up in the - // PendingChannels RPC under the waiting close section. - ht.AssertChannelWaitingClose(alice, chanPoint) + // At this point, all 3 nodes should now have an active channel with + // the created HTLCs pending on all of them. + // + // Alice should have one outgoing HTLCs on channel Alice -> Bob. + ht.AssertOutgoingHTLCActive(alice, abChanPoint, payHash[:]) - // Alice should have two pending sweeps, - // - anchor sweeping from her local commitment. - // - anchor sweeping from her remote commitment (invalid). + // Bob should have one incoming HTLC on channel Alice -> Bob, and one + // outgoing HTLC on channel Bob -> Carol. + ht.AssertIncomingHTLCActive(bob, abChanPoint, payHash[:]) + ht.AssertOutgoingHTLCActive(bob, bcChanPoint, payHash[:]) + + // Carol should have one incoming HTLC on channel Bob -> Carol. + ht.AssertIncomingHTLCActive(carol, bcChanPoint, payHash[:]) + + // Let Carol go offline so we can focus on testing Bob's sweeping + // behavior. + ht.Shutdown(carol) + + // We'll now mine enough blocks to trigger Bob to force close channel + // Bob->Carol due to his outgoing HTLC is about to timeout. With the + // default outgoing broadcast delta of zero, this will be the same + // height as the outgoing htlc's expiry height. + numBlocks := padCLTV(uint32( + invoiceReq.CltvExpiry - lncfg.DefaultOutgoingBroadcastDelta, + )) + ht.MineEmptyBlocks(int(numBlocks)) + + // Assert Bob's force closing tx has been broadcast. + closeTxid := ht.Miner.AssertNumTxsInMempool(1)[0] + + // Remember the force close height so we can calculate the deadline + // height. + _, forceCloseHeight := ht.Miner.GetBestBlock() + + // Bob should have two pending sweeps, + // - anchor sweeping from his local commitment. + // - anchor sweeping from his remote commitment (invalid). // // TODO(yy): consider only sweeping the anchor from the local // commitment. Previously we would sweep up to three versions of @@ -152,108 +185,114 @@ func testSweepAnchorCPFPLocalForceClose(ht *lntest.HarnessTest) { // their commitment tx and replaces ours. With the new fee bumping, we // should be safe to only sweep our local anchor since we RBF it on // every new block, which destroys the remote's ability to pin us. - ht.AssertNumPendingSweeps(alice, 2) + sweeps := ht.AssertNumPendingSweeps(bob, 2) - // Bob should have no pending sweeps here. Although he learned about - // the force close tx, because he doesn't have any outgoing HTLCs, he - // doesn't need to sweep anything. - ht.AssertNumPendingSweeps(bob, 0) + // The two anchor sweeping should have the same deadline height. + deadlineHeight := uint32(forceCloseHeight) + deadlineDeltaAnchor + require.Equal(ht, deadlineHeight, sweeps[0].DeadlineHeight) + require.Equal(ht, deadlineHeight, sweeps[1].DeadlineHeight) - // Mine a block so Alice's force closing tx stays in the mempool, which - // also triggers the sweep. + // Remember the deadline height for the CPFP anchor. + anchorDeadline := sweeps[0].DeadlineHeight + + // Mine a block so Bob's force closing tx stays in the mempool, which + // also triggers the CPFP anchor sweep. ht.MineEmptyBlocks(1) - // TODO(yy): we should also handle the edge case where the force close - // tx confirms here - we should cancel the fee bumping attempt for this - // anchor sweep and let it stay in mempool? Or should we unlease the - // wallet input and ask the sweeper to re-sweep the anchor? - // ht.MineBlocksAndAssertNumTxes(1, 1) + // Bob should still have two pending sweeps, + // - anchor sweeping from his local commitment. + // - anchor sweeping from his remote commitment (invalid). + ht.AssertNumPendingSweeps(bob, 2) - // We now check the expected fee and fee rate are used for Alice. + // We now check the expected fee and fee rate are used for Bob's anchor + // sweeping tx. // - // We should see Alice's anchor sweeping tx triggered by the above - // block, along with Alice's force close tx. + // We should see Bob's anchor sweeping tx triggered by the above + // block, along with his force close tx. txns := ht.Miner.GetNumTxsFromMempool(2) // Find the sweeping tx. sweepTx := ht.FindSweepingTxns(txns, 1, *closeTxid)[0] - // Get the weight for Alice's sweep tx. + // Get the weight for Bob's anchor sweeping tx. txWeight := ht.CalculateTxWeight(sweepTx) - // Calculate the fee and fee rate of Alice's sweeping tx. + // Bob should start with the initial fee rate of 2500 sat/kw. + startFeeAnchor := startFeeRateAnchor.FeeForWeight(txWeight) + + // Calculate the fee and fee rate of Bob's sweeping tx. fee := uint64(ht.CalculateTxFee(sweepTx)) feeRate := uint64(ht.CalculateTxFeeRate(sweepTx)) - // Alice should start with the initial fee rate of 2000 sat/kw. - startFee := startFeeRate.FeeForWeight(txWeight) + // feeFuncWidth is the width of the fee function. By the time we got + // here, we've already mined one block, and the fee function maxes + // out one block before the deadline, so the width is the original + // deadline minus 2. + feeFuncWidth := deadlineDeltaAnchor - 2 // Calculate the expected delta increased per block. - // - // NOTE: Assume a wallet tr output is used for fee bumping, with the tx - // weight of 725, we expect this value to be 2355. - feeDeltaAlice := (budget - startFee).MulF64(1 / float64(10)) + feeDelta := (cpfpBudget - startFeeAnchor).MulF64( + 1 / float64(feeFuncWidth), + ) // We expect the startingFee and startingFeeRate being used. Allow some // deviation because weight estimates during tx generation are // estimates. // // TODO(yy): unify all the units and types re int vs uint! - require.InEpsilonf(ht, uint64(startFee), fee, 0.01, - "want %d, got %d", startFee, fee) - require.InEpsilonf(ht, uint64(startFeeRate), feeRate, - 0.01, "want %d, got %d", startFeeRate, fee) + require.InEpsilonf(ht, uint64(startFeeAnchor), fee, 0.01, + "want %d, got %d", startFeeAnchor, fee) + require.InEpsilonf(ht, uint64(startFeeRateAnchor), feeRate, + 0.01, "want %d, got %d", startFeeRateAnchor, fee) - // Bob has no time-sensitive outputs, so he should sweep nothing. - ht.AssertNumPendingSweeps(bob, 0) - - // We now mine deadline-1 empty blocks. For each block mined, Alice - // should perform an RBF on her CPFP anchor sweeping tx. By the end of - // this iteration, we expect Alice to use start sweeping her htlc - // output after one more block. - for i := uint32(1); i <= deadline; i++ { + // We now mine deadline-2 empty blocks. For each block mined, Bob + // should perform an RBF on his CPFP anchor sweeping tx. By the end of + // this iteration, we expect Bob to use up his CPFP budget after one + // more block. + for i := uint32(1); i <= feeFuncWidth-1; i++ { // Mine an empty block. Since the sweeping tx is not confirmed, - // Alice's fee bumper should increase its fees. + // Bob's fee bumper should increase its fees. ht.MineEmptyBlocks(1) - // Alice should still have two pending sweeps, - // - anchor sweeping from her local commitment. - // - anchor sweeping from her remote commitment (invalid). - ht.AssertNumPendingSweeps(alice, 2) + // Bob should still have two pending sweeps, + // - anchor sweeping from his local commitment. + // - anchor sweeping from his remote commitment (invalid). + ht.AssertNumPendingSweeps(bob, 2) - // We expect to see two txns in the mempool, - // - Alice's force close tx. - // - Alice's anchor sweep tx. - ht.Miner.AssertNumTxsInMempool(2) - - // Make sure Alice's old sweeping tx has been removed from the + // Make sure Bob's old sweeping tx has been removed from the // mempool. ht.Miner.AssertTxNotInMempool(sweepTx.TxHash()) + // We expect to see two txns in the mempool, + // - Bob's force close tx. + // - Bob's anchor sweep tx. + ht.Miner.AssertNumTxsInMempool(2) + // We expect the fees to increase by i*delta. - expectedFee := startFee + feeDeltaAlice.MulF64(float64(i)) + expectedFee := startFeeAnchor + feeDelta.MulF64(float64(i)) expectedFeeRate := chainfee.NewSatPerKWeight( expectedFee, uint64(txWeight), ) - // We should see Alice's anchor sweeping tx being fee bumped - // since it's not confirmed, along with her force close tx. + // We should see Bob's anchor sweeping tx being fee bumped + // since it's not confirmed, along with his force close tx. txns = ht.Miner.GetNumTxsFromMempool(2) // Find the sweeping tx. sweepTx = ht.FindSweepingTxns(txns, 1, *closeTxid)[0] - // Calculate the fee rate of Alice's new sweeping tx. + // Calculate the fee rate of Bob's new sweeping tx. feeRate = uint64(ht.CalculateTxFeeRate(sweepTx)) - // Calculate the fee of Alice's new sweeping tx. + // Calculate the fee of Bob's new sweeping tx. fee = uint64(ht.CalculateTxFee(sweepTx)) - ht.Logf("Alice(deadline=%v): txWeight=%v, expected: [fee=%d, "+ - "feerate=%v], got: [fee=%v, feerate=%v]", deadline-i, - txWeight, expectedFee, expectedFeeRate, fee, feeRate) + ht.Logf("Bob(position=%v): txWeight=%v, expected: [fee=%d, "+ + "feerate=%v], got: [fee=%v, feerate=%v]", + feeFuncWidth-i, txWeight, expectedFee, + expectedFeeRate, fee, feeRate) - // Assert Alice's tx has the expected fee and fee rate. + // Assert Bob's tx has the expected fee and fee rate. require.InEpsilonf(ht, uint64(expectedFee), fee, 0.01, "deadline=%v, want %d, got %d", i, expectedFee, fee) require.InEpsilonf(ht, uint64(expectedFeeRate), feeRate, 0.01, @@ -261,27 +300,34 @@ func testSweepAnchorCPFPLocalForceClose(ht *lntest.HarnessTest) { feeRate) } - // Once out of the above loop, we should've mined deadline-1 blocks. If - // we mine one more block, we'd use up all the CPFP budget. + // We now check the budget has been used up at the deadline-1 block. + // + // Once out of the above loop, we expect to be 2 blocks before the CPFP + // deadline. + _, currentHeight := ht.Miner.GetBestBlock() + require.Equal(ht, int(anchorDeadline-2), int(currentHeight)) + + // Mine one more block, we'd use up all the CPFP budget. ht.MineEmptyBlocks(1) - // Get the last sweeping tx - we should see two txns here, Alice's - // anchor sweeping tx and her force close tx. + // Make sure Bob's old sweeping tx has been removed from the mempool. + ht.Miner.AssertTxNotInMempool(sweepTx.TxHash()) + + // Get the last sweeping tx - we should see two txns here, Bob's anchor + // sweeping tx and his force close tx. txns = ht.Miner.GetNumTxsFromMempool(2) // Find the sweeping tx. sweepTx = ht.FindSweepingTxns(txns, 1, *closeTxid)[0] - // Calculate the fee and fee rate of Alice's new sweeping tx. + // Calculate the fee of Bob's new sweeping tx. fee = uint64(ht.CalculateTxFee(sweepTx)) - feeRate = uint64(ht.CalculateTxFeeRate(sweepTx)) - // Alice should still have two pending sweeps, - // - anchor sweeping from her local commitment. - // - anchor sweeping from her remote commitment (invalid). - ht.AssertNumPendingSweeps(alice, 2) + // Assert the budget is now used up. + require.InEpsilonf(ht, uint64(cpfpBudget), fee, 0.01, "want %d, got %d", + cpfpBudget, fee) - // Mine one more block. Since Alice's budget has been used up, there + // Mine one more block. Since Bob's budget has been used up, there // won't be any more sweeping attempts. We now assert this by checking // that the sweeping tx stayed unchanged. ht.MineEmptyBlocks(1) @@ -289,30 +335,361 @@ func testSweepAnchorCPFPLocalForceClose(ht *lntest.HarnessTest) { // Get the current sweeping tx and assert it stays unchanged. // // We expect two txns here, one for the anchor sweeping, the other for - // the HTLC sweeping. + // the force close tx. txns = ht.Miner.GetNumTxsFromMempool(2) // Find the sweeping tx. currentSweepTx := ht.FindSweepingTxns(txns, 1, *closeTxid)[0] - // Calculate the fee and fee rate of Alice's current sweeping tx. - currentFee := uint64(ht.CalculateTxFee(sweepTx)) - currentFeeRate := uint64(ht.CalculateTxFeeRate(sweepTx)) + // Assert the anchor sweep tx stays unchanged. + require.Equal(ht, sweepTx.TxHash(), currentSweepTx.TxHash()) + + // Mine a block to confirm Bob's sweeping and force close txns, this is + // needed to clean up the mempool. + ht.MineBlocksAndAssertNumTxes(1, 2) + + // The above mined block should confirm Bob's force close tx, and his + // contractcourt will offer the HTLC to his sweeper. We are not testing + // the HTLC sweeping behaviors so we just perform a simple check and + // exit the test. + ht.AssertNumPendingSweeps(bob, 1) + + // Finally, clean the mempool for the next test. + ht.CleanShutDown() +} + +// testSweepCPFPAnchorIncomingTimeout checks when a channel is force closed by +// a local node due to the incoming HTLC is about to time out, the anchor +// output is used for CPFPing the force close tx. +// +// Setup: +// 1. Fund Alice with 1 UTXOs - she only needs one for the funding process, +// 2. Fund Bob with 1 UTXO - he only needs one for the funding process, and +// the change output will be used for sweeping his anchor on local commit. +// 3. Create a linear network from Alice -> Bob -> Carol. +// 4. Alice pays an invoice to Carol through Bob. +// 5. Alice goes offline. +// 6. Carol settles the invoice. +// +// Test: +// 1. Bob force closes the channel with Alice, using the anchor output for +// CPFPing the force close tx. +// 2. Bob's anchor output is swept and fee bumped based on its deadline and +// budget. +func testSweepCPFPAnchorIncomingTimeout(ht *lntest.HarnessTest) { + // Setup testing params. + // + // Invoice is 100k sats. + invoiceAmt := btcutil.Amount(100_000) + + // Use the smallest CLTV so we can mine fewer blocks. + cltvDelta := routing.MinCLTVDelta + + // goToChainDelta is the broadcast delta of Bob's incoming HTLC. When + // the block height is at CLTV-goToChainDelta, Bob will force close the + // channel Alice=>Bob. + goToChainDelta := uint32(lncfg.DefaultIncomingBroadcastDelta) + + // deadlineDeltaAnchor is the expected deadline delta for the CPFP + // anchor sweeping tx. + deadlineDeltaAnchor := goToChainDelta / 2 + + // startFeeRateAnchor is the starting fee rate for the CPFP anchor + // sweeping tx. + startFeeRateAnchor := chainfee.SatPerKWeight(2500) + + // Set up the fee estimator to return the testing fee rate when the + // conf target is the deadline. + // + // TODO(yy): switch to conf when `blockbeat` is in place. + // ht.SetFeeEstimateWithConf(startFeeRateAnchor, deadlineDeltaAnchor) + ht.SetFeeEstimate(startFeeRateAnchor) + + // Create a preimage, that will be held by Carol. + var preimage lntypes.Preimage + copy(preimage[:], ht.Random32Bytes()) + payHash := preimage.Hash() + + // We now set up the force close scenario. We will create a network + // from Alice -> Bob -> Carol, where Alice will send a payment to Carol + // via Bob, Alice goes offline, Carol settles the payment. We expect + // Bob to sweep his anchor and incoming HTLC. + // + // Prepare params. + cfg := []string{ + "--protocol.anchors", + // Use a small CLTV to mine less blocks. + fmt.Sprintf("--bitcoin.timelockdelta=%d", cltvDelta), + // Use a very large CSV, this way to_local outputs are never + // swept so we can focus on testing HTLCs. + fmt.Sprintf("--bitcoin.defaultremotedelay=%v", cltvDelta*10), + } + openChannelParams := lntest.OpenChannelParams{ + Amt: invoiceAmt * 10, + } + + // Create a three hop network: Alice -> Bob -> Carol. + chanPoints, nodes := createSimpleNetwork(ht, cfg, 3, openChannelParams) + + // Unwrap the results. + abChanPoint, bcChanPoint := chanPoints[0], chanPoints[1] + alice, bob, carol := nodes[0], nodes[1], nodes[2] + + // For neutrino backend, we need one more UTXO for Bob to create his + // sweeping txns. + if ht.IsNeutrinoBackend() { + ht.FundCoins(btcutil.SatoshiPerBitcoin, bob) + } + + // Subscribe the invoice. + streamCarol := carol.RPC.SubscribeSingleInvoice(payHash[:]) + + // With the network active, we'll now add a hodl invoice at Carol's + // end. + invoiceReq := &invoicesrpc.AddHoldInvoiceRequest{ + Value: int64(invoiceAmt), + CltvExpiry: finalCltvDelta, + Hash: payHash[:], + } + invoice := carol.RPC.AddHoldInvoice(invoiceReq) + + // Let Alice pay the invoices. + req := &routerrpc.SendPaymentRequest{ + PaymentRequest: invoice.PaymentRequest, + TimeoutSeconds: 60, + FeeLimitMsat: noFeeLimitMsat, + } + + // Assert the payments are inflight. + ht.SendPaymentAndAssertStatus(alice, req, lnrpc.Payment_IN_FLIGHT) + + // Wait for Carol to mark invoice as accepted. There is a small gap to + // bridge between adding the htlc to the channel and executing the exit + // hop logic. + ht.AssertInvoiceState(streamCarol, lnrpc.Invoice_ACCEPTED) + + // At this point, all 3 nodes should now have an active channel with + // the created HTLCs pending on all of them. + // + // Alice should have one outgoing HTLCs on channel Alice -> Bob. + ht.AssertOutgoingHTLCActive(alice, abChanPoint, payHash[:]) + + // Bob should have one incoming HTLC on channel Alice -> Bob, and one + // outgoing HTLC on channel Bob -> Carol. + htlc := ht.AssertIncomingHTLCActive(bob, abChanPoint, payHash[:]) + ht.AssertOutgoingHTLCActive(bob, bcChanPoint, payHash[:]) + + // Calculate the budget used for Bob's anchor sweeping. + // + // htlcValue is the incoming HTLC's value. + htlcValue := btcutil.Amount(htlc.Amount) + + // htlcBudget is the budget used to sweep the incoming HTLC. + htlcBudget := htlcValue.MulF64(contractcourt.DefaultBudgetRatio) + + // cpfpBudget is the budget used to sweep the CPFP anchor. + cpfpBudget := (htlcValue - htlcBudget).MulF64( + contractcourt.DefaultBudgetRatio, + ) + + // Carol should have one incoming HTLC on channel Bob -> Carol. + ht.AssertIncomingHTLCActive(carol, bcChanPoint, payHash[:]) + + // Let Alice go offline. Once Bob later learns the preimage, he + // couldn't settle it with Alice so he has to go onchain to collect it. + ht.Shutdown(alice) + + // Carol settles invoice. + carol.RPC.SettleInvoice(preimage[:]) + + // Bob should have settled his outgoing HTLC with Carol. + ht.AssertHTLCNotActive(bob, bcChanPoint, payHash[:]) + + // We'll now mine enough blocks to trigger Bob to force close channel + // Alice->Bob due to his incoming HTLC is about to timeout. With the + // default incoming broadcast delta of 10, this will be the same + // height as the incoming htlc's expiry height minus 10. + forceCloseHeight := htlc.ExpirationHeight - goToChainDelta + + // Mine till the goToChainHeight is reached. + _, currentHeight := ht.Miner.GetBestBlock() + numBlocks := forceCloseHeight - uint32(currentHeight) + ht.MineEmptyBlocks(int(numBlocks)) + + // Assert Bob's force closing tx has been broadcast. + closeTxid := ht.Miner.AssertNumTxsInMempool(1)[0] + + // Bob should have two pending sweeps, + // - anchor sweeping from his local commitment. + // - anchor sweeping from his remote commitment (invalid). + sweeps := ht.AssertNumPendingSweeps(bob, 2) + + // The two anchor sweeping should have the same deadline height. + deadlineHeight := forceCloseHeight + deadlineDeltaAnchor + require.Equal(ht, deadlineHeight, sweeps[0].DeadlineHeight) + require.Equal(ht, deadlineHeight, sweeps[1].DeadlineHeight) + + // Remember the deadline height for the CPFP anchor. + anchorDeadline := sweeps[0].DeadlineHeight + + // Mine a block so Bob's force closing tx stays in the mempool, which + // also triggers the CPFP anchor sweep. + ht.MineEmptyBlocks(1) + + // Bob should still have two pending sweeps, + // - anchor sweeping from his local commitment. + // - anchor sweeping from his remote commitment (invalid). + ht.AssertNumPendingSweeps(bob, 2) + + // We now check the expected fee and fee rate are used for Bob's anchor + // sweeping tx. + // + // We should see Bob's anchor sweeping tx triggered by the above + // block, along with his force close tx. + txns := ht.Miner.GetNumTxsFromMempool(2) + + // Find the sweeping tx. + sweepTx := ht.FindSweepingTxns(txns, 1, *closeTxid)[0] + + // Get the weight for Bob's anchor sweeping tx. + txWeight := ht.CalculateTxWeight(sweepTx) + + // Bob should start with the initial fee rate of 2500 sat/kw. + startFeeAnchor := startFeeRateAnchor.FeeForWeight(txWeight) + + // Calculate the fee and fee rate of Bob's sweeping tx. + fee := uint64(ht.CalculateTxFee(sweepTx)) + feeRate := uint64(ht.CalculateTxFeeRate(sweepTx)) + + // feeFuncWidth is the width of the fee function. By the time we got + // here, we've already mined one block, and the fee function maxes + // out one block before the deadline, so the width is the original + // deadline minus 2. + feeFuncWidth := deadlineDeltaAnchor - 2 + + // Calculate the expected delta increased per block. + feeDelta := (cpfpBudget - startFeeAnchor).MulF64( + 1 / float64(feeFuncWidth), + ) + + // We expect the startingFee and startingFeeRate being used. Allow some + // deviation because weight estimates during tx generation are + // estimates. + // + // TODO(yy): unify all the units and types re int vs uint! + require.InEpsilonf(ht, uint64(startFeeAnchor), fee, 0.01, + "want %d, got %d", startFeeAnchor, fee) + require.InEpsilonf(ht, uint64(startFeeRateAnchor), feeRate, + 0.01, "want %d, got %d", startFeeRateAnchor, fee) + + // We now mine deadline-2 empty blocks. For each block mined, Bob + // should perform an RBF on his CPFP anchor sweeping tx. By the end of + // this iteration, we expect Bob to use up his CPFP budget after one + // more block. + for i := uint32(1); i <= feeFuncWidth-1; i++ { + // Mine an empty block. Since the sweeping tx is not confirmed, + // Bob's fee bumper should increase its fees. + ht.MineEmptyBlocks(1) + + // Bob should still have two pending sweeps, + // - anchor sweeping from his local commitment. + // - anchor sweeping from his remote commitment (invalid). + ht.AssertNumPendingSweeps(bob, 2) + + // Make sure Bob's old sweeping tx has been removed from the + // mempool. + ht.Miner.AssertTxNotInMempool(sweepTx.TxHash()) + + // We expect to see two txns in the mempool, + // - Bob's force close tx. + // - Bob's anchor sweep tx. + ht.Miner.AssertNumTxsInMempool(2) + + // We expect the fees to increase by i*delta. + expectedFee := startFeeAnchor + feeDelta.MulF64(float64(i)) + expectedFeeRate := chainfee.NewSatPerKWeight( + expectedFee, uint64(txWeight), + ) + + // We should see Bob's anchor sweeping tx being fee bumped + // since it's not confirmed, along with his force close tx. + txns = ht.Miner.GetNumTxsFromMempool(2) + + // Find the sweeping tx. + sweepTx = ht.FindSweepingTxns(txns, 1, *closeTxid)[0] + + // Calculate the fee rate of Bob's new sweeping tx. + feeRate = uint64(ht.CalculateTxFeeRate(sweepTx)) + + // Calculate the fee of Bob's new sweeping tx. + fee = uint64(ht.CalculateTxFee(sweepTx)) + + ht.Logf("Bob(position=%v): txWeight=%v, expected: [fee=%d, "+ + "feerate=%v], got: [fee=%v, feerate=%v]", + feeFuncWidth-i, txWeight, expectedFee, + expectedFeeRate, fee, feeRate) + + // Assert Bob's tx has the expected fee and fee rate. + require.InEpsilonf(ht, uint64(expectedFee), fee, 0.01, + "deadline=%v, want %d, got %d", i, expectedFee, fee) + require.InEpsilonf(ht, uint64(expectedFeeRate), feeRate, 0.01, + "deadline=%v, want %d, got %d", i, expectedFeeRate, + feeRate) + } + + // We now check the budget has been used up at the deadline-1 block. + // + // Once out of the above loop, we expect to be 2 blocks before the CPFP + // deadline. + _, currentHeight = ht.Miner.GetBestBlock() + require.Equal(ht, int(anchorDeadline-2), int(currentHeight)) + + // Mine one more block, we'd use up all the CPFP budget. + ht.MineEmptyBlocks(1) + + // Make sure Bob's old sweeping tx has been removed from the mempool. + ht.Miner.AssertTxNotInMempool(sweepTx.TxHash()) + + // Get the last sweeping tx - we should see two txns here, Bob's anchor + // sweeping tx and his force close tx. + txns = ht.Miner.GetNumTxsFromMempool(2) + + // Find the sweeping tx. + sweepTx = ht.FindSweepingTxns(txns, 1, *closeTxid)[0] + + // Calculate the fee of Bob's new sweeping tx. + fee = uint64(ht.CalculateTxFee(sweepTx)) + + // Assert the budget is now used up. + require.InEpsilonf(ht, uint64(cpfpBudget), fee, 0.01, "want %d, got %d", + cpfpBudget, fee) + + // Mine one more block. Since Bob's budget has been used up, there + // won't be any more sweeping attempts. We now assert this by checking + // that the sweeping tx stayed unchanged. + ht.MineEmptyBlocks(1) + + // Get the current sweeping tx and assert it stays unchanged. + // + // We expect two txns here, one for the anchor sweeping, the other for + // the force close tx. + txns = ht.Miner.GetNumTxsFromMempool(2) + + // Find the sweeping tx. + currentSweepTx := ht.FindSweepingTxns(txns, 1, *closeTxid)[0] // Assert the anchor sweep tx stays unchanged. require.Equal(ht, sweepTx.TxHash(), currentSweepTx.TxHash()) - require.Equal(ht, fee, currentFee) - require.Equal(ht, feeRate, currentFeeRate) - // Mine a block to confirm Alice's sweeping and force close txns, this - // is needed to clean up the mempool. + // Mine a block to confirm Bob's sweeping and force close txns, this is + // needed to clean up the mempool. ht.MineBlocksAndAssertNumTxes(1, 2) - // The above mined block should confirm Alice's force close tx, and her - // contractcourt will offer the HTLC to her sweeper. We are not testing + // The above mined block should confirm Bob's force close tx, and his + // contractcourt will offer the HTLC to his sweeper. We are not testing // the HTLC sweeping behaviors so we just perform a simple check and // exit the test. - ht.AssertNumPendingSweeps(alice, 1) + ht.AssertNumPendingSweeps(bob, 1) // Finally, clean the mempool for the next test. ht.CleanShutDown() From 95016b849a20ee275f493deee28f4df6e7b1a720 Mon Sep 17 00:00:00 2001 From: Ononiwu Maureen <59079323+Chinwendu20@users.noreply.github.com> Date: Tue, 14 May 2024 00:01:51 +0100 Subject: [PATCH 093/109] fn: Added `HasDuplicates` function to slice Signed-off-by: Ononiwu Maureen <59079323+Chinwendu20@users.noreply.github.com> --- fn/slice.go | 7 +++++++ fn/slice_test.go | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/fn/slice.go b/fn/slice.go index 2e27acc45..f42d34544 100644 --- a/fn/slice.go +++ b/fn/slice.go @@ -198,3 +198,10 @@ func Sum[B Number](items []B) B { return a + b }, 0, items) } + +// HasDuplicates checks if the given slice contains any duplicate elements. +// It returns false if there are no duplicates in the slice (i.e., all elements +// are unique), otherwise returns false. +func HasDuplicates[A comparable](items []A) bool { + return len(NewSet(items...)) != len(items) +} diff --git a/fn/slice_test.go b/fn/slice_test.go index de02be836..016ef87d3 100644 --- a/fn/slice_test.go +++ b/fn/slice_test.go @@ -241,3 +241,43 @@ func TestSliceToMap(t *testing.T) { }) } } + +// TestHasDuplicates tests the HasDuplicates function. +func TestHasDuplicates(t *testing.T) { + // Define test cases. + testCases := []struct { + name string + items []int + want bool + }{ + { + name: "All unique", + items: []int{1, 2, 3, 4, 5}, + want: false, + }, + { + name: "Some duplicates", + items: []int{1, 2, 2, 3, 4}, + want: true, + }, + { + name: "No items", + items: []int{}, + want: false, + }, + { + name: "All duplicates", + items: []int{1, 1, 1, 1}, + want: true, + }, + } + + // Execute each test case. + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + got := HasDuplicates(tc.items) + + require.Equal(t, tc.want, got) + }) + } +} From 4079f61d7e4aa207f16b603f9ebf0b667f72e4bb Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 16 May 2024 23:22:19 +0800 Subject: [PATCH 094/109] itest+sweep: fix current itest re anchor deadline --- itest/lnd_channel_force_close_test.go | 91 ++++++++++----------------- itest/lnd_multi-hop_test.go | 28 +++++---- itest/lnd_sweep_test.go | 16 ++--- sweep/fee_bumper.go | 4 +- 4 files changed, 59 insertions(+), 80 deletions(-) diff --git a/itest/lnd_channel_force_close_test.go b/itest/lnd_channel_force_close_test.go index dc28f034b..11dcd0acb 100644 --- a/itest/lnd_channel_force_close_test.go +++ b/itest/lnd_channel_force_close_test.go @@ -216,34 +216,17 @@ func channelForceClosureTest(ht *lntest.HarnessTest, // We expect to see Alice's force close tx in the mempool. ht.Miner.GetNumTxsFromMempool(1) - // Assert Alice's has the pending anchor outputs - one for local and - // the other for remote (invalid). - sweeps := ht.AssertNumPendingSweeps(alice, 2) - aliceAnchor := sweeps[0] - if aliceAnchor.Outpoint.TxidStr != waitingClose.Commitments.LocalTxid { - aliceAnchor = sweeps[1] - } - require.Equal(ht, aliceAnchor.Outpoint.TxidStr, - waitingClose.Commitments.LocalTxid) - // Mine a block which should confirm the commitment transaction // broadcast as a result of the force closure. Once mined, we also // expect Alice's anchor sweeping tx being published. ht.MineBlocksAndAssertNumTxes(1, 1) - // Assert Alice's anchor sweeping tx is found in the mempool. - aliceSweepTxid := ht.Miner.AssertNumTxsInMempool(1)[0] - - // Add alice's anchor to our expected set of reports. - op := fmt.Sprintf("%v:%v", aliceAnchor.Outpoint.TxidStr, - aliceAnchor.Outpoint.OutputIndex) - aliceReports[op] = &lnrpc.Resolution{ - ResolutionType: lnrpc.ResolutionType_ANCHOR, - Outcome: lnrpc.ResolutionOutcome_CLAIMED, - SweepTxid: aliceSweepTxid.String(), - Outpoint: aliceAnchor.Outpoint, - AmountSat: uint64(anchorSize), - } + // Assert Alice's has one pending anchor output - because she doesn't + // have incoming HTLCs, her outgoing HTLC won't have a deadline, thus + // she won't use the anchor to perform CPFP. + aliceAnchor := ht.AssertNumPendingSweeps(alice, 1)[0] + require.Equal(ht, aliceAnchor.Outpoint.TxidStr, + waitingClose.Commitments.LocalTxid) // Now that the commitment has been confirmed, the channel should be // marked as force closed. @@ -290,10 +273,8 @@ func channelForceClosureTest(ht *lntest.HarnessTest, } // Mine a block to trigger Carol's sweeper to make decisions on the - // anchor sweeping. This block will also confirm Alice's anchor - // sweeping tx as her anchor is used for CPFP due to there are - // time-sensitive HTLCs. - ht.MineBlocksAndAssertNumTxes(1, 1) + // anchor sweeping. + ht.MineEmptyBlocks(1) // Carol's sweep tx should be in the mempool already, as her output is // not timelocked. @@ -307,7 +288,7 @@ func channelForceClosureTest(ht *lntest.HarnessTest, totalFeeCarol := ht.CalculateTxFee(carolTx) // If we have anchors, add an anchor resolution for carol. - op = fmt.Sprintf("%v:%v", carolAnchor.Outpoint.TxidStr, + op := fmt.Sprintf("%v:%v", carolAnchor.Outpoint.TxidStr, carolAnchor.Outpoint.OutputIndex) carolReports[op] = &lnrpc.Resolution{ ResolutionType: lnrpc.ResolutionType_ANCHOR, @@ -336,27 +317,8 @@ func channelForceClosureTest(ht *lntest.HarnessTest, // commit and anchor outputs. ht.MineBlocksAndAssertNumTxes(1, 1) - // Once Alice's anchor sweeping is mined, she should have no pending - // sweep requests atm. - ht.AssertNumPendingSweeps(alice, 0) - - // TODO(yy): fix the case in 0.18.1 - the CPFP anchor sweeping may be - // replaced with a following request after the above restart - the - // anchor will be offered to the sweeper again with updated params, - // which cannot be swept due to it being uneconomical. - var anchorRecovered bool - err = wait.NoError(func() error { - sweepResp := alice.RPC.ListSweeps(false, 0) - txns := sweepResp.GetTransactionIds().TransactionIds - - if len(txns) >= 1 { - anchorRecovered = true - return nil - } - - return fmt.Errorf("expected 1 sweep tx, got %d", len(txns)) - }, wait.DefaultTimeout) - ht.Logf("waiting for Alice's anchor sweep to be broadcast: %v", err) + // Alice should still have the anchor sweeping request. + ht.AssertNumPendingSweeps(alice, 1) // The following restart checks to ensure that outputs in the // kindergarten bucket are persisted while waiting for the required @@ -399,12 +361,8 @@ func channelForceClosureTest(ht *lntest.HarnessTest, return errors.New("all funds should still be in " + "limbo") } - if !anchorRecovered { - return nil - } - if forceClose.RecoveredBalance != anchorSize { - return fmt.Errorf("expected %v to be recovered", - anchorSize) + if forceClose.RecoveredBalance != 0 { + return errors.New("no funds should be recovered") } return nil @@ -417,7 +375,11 @@ func channelForceClosureTest(ht *lntest.HarnessTest, // At this point, the CSV will expire in the next block, meaning that // the output should be offered to the sweeper. - aliceCommit := ht.AssertNumPendingSweeps(alice, 1)[0] + sweeps := ht.AssertNumPendingSweeps(alice, 2) + commitSweep, anchorSweep := sweeps[0], sweeps[1] + if commitSweep.AmountSat < anchorSweep.AmountSat { + commitSweep, anchorSweep = anchorSweep, commitSweep + } // Restart Alice to ensure that she resumes watching the finalized // commitment sweep txid. @@ -438,16 +400,27 @@ func channelForceClosureTest(ht *lntest.HarnessTest, } // We expect a resolution which spends our commit output. - op = fmt.Sprintf("%v:%v", aliceCommit.Outpoint.TxidStr, - aliceCommit.Outpoint.OutputIndex) + op = fmt.Sprintf("%v:%v", commitSweep.Outpoint.TxidStr, + commitSweep.Outpoint.OutputIndex) aliceReports[op] = &lnrpc.Resolution{ ResolutionType: lnrpc.ResolutionType_COMMIT, Outcome: lnrpc.ResolutionOutcome_CLAIMED, SweepTxid: sweepingTXID.String(), - Outpoint: aliceCommit.Outpoint, + Outpoint: commitSweep.Outpoint, AmountSat: uint64(aliceBalance), } + // Add alice's anchor to our expected set of reports. + op = fmt.Sprintf("%v:%v", aliceAnchor.Outpoint.TxidStr, + aliceAnchor.Outpoint.OutputIndex) + aliceReports[op] = &lnrpc.Resolution{ + ResolutionType: lnrpc.ResolutionType_ANCHOR, + Outcome: lnrpc.ResolutionOutcome_CLAIMED, + SweepTxid: sweepingTXID.String(), + Outpoint: aliceAnchor.Outpoint, + AmountSat: uint64(anchorSize), + } + // Check that we can find the commitment sweep in our set of known // sweeps, using the simple transaction id ListSweeps output. ht.AssertSweepFound(alice, sweepingTXID.String(), false, 0) diff --git a/itest/lnd_multi-hop_test.go b/itest/lnd_multi-hop_test.go index fa4590d04..7ff9f48b4 100644 --- a/itest/lnd_multi-hop_test.go +++ b/itest/lnd_multi-hop_test.go @@ -713,9 +713,11 @@ func runMultiHopLocalForceCloseOnChainHtlcTimeout(ht *lntest.HarnessTest, // to be mined to trigger a force close later on. var blocksMined uint32 - // Increase the fee estimate so that the following force close tx will - // be cpfp'ed. - ht.SetFeeEstimate(30000) + // We need to mine a block otherwise `FindOutgoingHTLCDeadline` cannot + // find the incoming HTLC on Bob's ChainArbitrator. + // + // TODO(yy): Investigate and fix it! + ht.MineEmptyBlocks(1) // Now that all parties have the HTLC locked in, we'll immediately // force close the Bob -> Carol channel. This should trigger contract @@ -755,7 +757,7 @@ func runMultiHopLocalForceCloseOnChainHtlcTimeout(ht *lntest.HarnessTest, ht.MineEmptyBlocks(int(defaultCSV - blocksMined)) blocksMined = defaultCSV - // Assert Bob has the sweep and trigger it.. + // Assert Bob has the sweep and trigger it. ht.AssertNumPendingSweeps(bob, 1) ht.MineEmptyBlocks(1) blocksMined++ @@ -1523,10 +1525,6 @@ func runMultiHopHtlcRemoteChainClaim(ht *lntest.HarnessTest, ht.AssertNumPendingSweeps(bob, 1) ht.AssertNumPendingSweeps(alice, 1) - // Mine a block to confirm Alice's CPFP anchor sweeping. - ht.MineBlocksAndAssertNumTxes(1, 1) - blocksMined++ - // Mine enough blocks for Alice to sweep her funds from the force // closed channel. AssertStreamChannelForceClosed() already mined a // block containing the commitment tx and the commit sweep tx will be @@ -1537,7 +1535,7 @@ func runMultiHopHtlcRemoteChainClaim(ht *lntest.HarnessTest, blocksMined = defaultCSV // Alice should now sweep her funds. - ht.AssertNumPendingSweeps(alice, 1) + ht.AssertNumPendingSweeps(alice, 2) // Mine a block to trigger the sweep. ht.MineEmptyBlocks(1) @@ -1690,7 +1688,7 @@ func runMultiHopHtlcRemoteChainClaim(ht *lntest.HarnessTest, ht.MineEmptyBlocks(numBlocks) // Both Alice and Bob should offer their commit sweeps. - ht.AssertNumPendingSweeps(alice, 1) + ht.AssertNumPendingSweeps(alice, 2) ht.AssertNumPendingSweeps(bob, 1) // Mine a block to trigger the sweeps. @@ -2472,7 +2470,6 @@ func runExtraPreimageFromRemoteCommit(ht *lntest.HarnessTest, if ht.IsNeutrinoBackend() { // Mine a block to confirm Carol's 2nd level success tx. ht.MineBlocksAndAssertNumTxes(1, 1) - numTxesMempool-- numBlocks-- } @@ -2503,6 +2500,15 @@ func runExtraPreimageFromRemoteCommit(ht *lntest.HarnessTest, case lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE: } + // For neutrino backend, Carol's second-stage sweep should be offered + // to her sweeper. + if ht.IsNeutrinoBackend() { + ht.AssertNumPendingSweeps(carol, 1) + + // Mine a block to trigger the sweep. + ht.MineEmptyBlocks(1) + } + // Mine a block to clean the mempool. ht.MineBlocksAndAssertNumTxes(1, numTxesMempool) diff --git a/itest/lnd_sweep_test.go b/itest/lnd_sweep_test.go index b79dda521..4702def38 100644 --- a/itest/lnd_sweep_test.go +++ b/itest/lnd_sweep_test.go @@ -874,9 +874,6 @@ func testSweepHTLCs(ht *lntest.HarnessTest) { )) ht.MineBlocks(numBlocks) - // Bob force closes the channel. - // ht.CloseChannelAssertPending(bob, bcChanPoint, true) - // Before we mine empty blocks to check the RBF behavior, we need to be // aware that Bob's incoming HTLC will expire before his outgoing HTLC // deadline is reached. This happens because the incoming HTLC is sent @@ -944,7 +941,7 @@ func testSweepHTLCs(ht *lntest.HarnessTest) { // Now the start fee rate is checked, we can calculate the fee rate // delta. outgoingFeeRateDelta := (outgoingEndFeeRate - outgoingStartFeeRate) / - chainfee.SatPerKWeight(outgoingHTLCDeadline) + chainfee.SatPerKWeight(outgoingHTLCDeadline-1) // outgoingFuncPosition records the position of Bob's fee function used // for his outgoing HTLC sweeping tx. @@ -1083,7 +1080,7 @@ func testSweepHTLCs(ht *lntest.HarnessTest) { // Now the start fee rate is checked, we can calculate the fee rate // delta. incomingFeeRateDelta := (incomingEndFeeRate - incomingStartFeeRate) / - chainfee.SatPerKWeight(incomingHTLCDeadline) + chainfee.SatPerKWeight(incomingHTLCDeadline-1) // incomingFuncPosition records the position of Bob's fee function used // for his incoming HTLC sweeping tx. @@ -1143,7 +1140,10 @@ func testSweepHTLCs(ht *lntest.HarnessTest) { // We now mine enough blocks till we reach the end of the outgoing // HTLC's deadline. Along the way, we check the expected fee rates are // used for both incoming and outgoing HTLC sweeping txns. - blocksLeft := outgoingHTLCDeadline - outgoingFuncPosition + // + // NOTE: We need to subtract 1 from the deadline as the budget must be + // used up before the deadline. + blocksLeft := outgoingHTLCDeadline - outgoingFuncPosition - 1 for i := int32(0); i < blocksLeft; i++ { // Mine an empty block. ht.MineEmptyBlocks(1) @@ -1418,7 +1418,7 @@ func testSweepCommitOutputAndAnchor(ht *lntest.HarnessTest) { bobTxWeight := uint64(ht.CalculateTxWeight(bobSweepTx)) bobEndingFeeRate := chainfee.NewSatPerKWeight(bobBudget, bobTxWeight) bobFeeRateDelta := (bobEndingFeeRate - bobStartFeeRate) / - chainfee.SatPerKWeight(deadlineB) + chainfee.SatPerKWeight(deadlineB-1) // Mine an empty block, which should trigger Alice's contractcourt to // offer her commit output to the sweeper. @@ -1550,7 +1550,7 @@ func testSweepCommitOutputAndAnchor(ht *lntest.HarnessTest) { aliceTxWeight := uint64(ht.CalculateTxWeight(aliceSweepTx)) aliceEndingFeeRate := sweep.DefaultMaxFeeRate.FeePerKWeight() aliceFeeRateDelta := (aliceEndingFeeRate - aliceStartingFeeRate) / - chainfee.SatPerKWeight(deadlineA) + chainfee.SatPerKWeight(deadlineA-1) aliceFeeRate := ht.CalculateTxFeeRate(aliceSweepTx) expectedFeeRateAlice := aliceStartingFeeRate + diff --git a/sweep/fee_bumper.go b/sweep/fee_bumper.go index a0e558cbb..dd471efff 100644 --- a/sweep/fee_bumper.go +++ b/sweep/fee_bumper.go @@ -1216,8 +1216,8 @@ func (t *TxPublisher) createSweepTx(inputs []input.Input, changePkScript []byte, } } - log.Debugf("Created sweep tx %v for %v inputs", sweepTx.TxHash(), - len(inputs)) + log.Debugf("Created sweep tx %v for inputs:\n%v", sweepTx.TxHash(), + inputTypeSummary(inputs)) return sweepTx, txFee, nil } From 71ee50f87c9785d46b30acc5351c423a125792fc Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 16 May 2024 23:28:14 +0800 Subject: [PATCH 095/109] lncli: add missing `SatPerVbyte` field in `bumpfee` cli --- cmd/lncli/walletrpc_active.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/cmd/lncli/walletrpc_active.go b/cmd/lncli/walletrpc_active.go index a79fc0065..bb808a7cd 100644 --- a/cmd/lncli/walletrpc_active.go +++ b/cmd/lncli/walletrpc_active.go @@ -287,10 +287,11 @@ func bumpFee(ctx *cli.Context) error { } resp, err := client.BumpFee(ctxc, &walletrpc.BumpFeeRequest{ - Outpoint: protoOutPoint, - TargetConf: uint32(ctx.Uint64("conf_target")), - Immediate: immediate, - Budget: ctx.Uint64("budget"), + Outpoint: protoOutPoint, + TargetConf: uint32(ctx.Uint64("conf_target")), + Immediate: immediate, + Budget: ctx.Uint64("budget"), + SatPerVbyte: ctx.Uint64("sat_per_vbyte"), }) if err != nil { return err @@ -487,10 +488,11 @@ func bumpForceCloseFee(ctx *cli.Context) error { resp, err := walletClient.BumpFee( ctxc, &walletrpc.BumpFeeRequest{ - Outpoint: sweep.Outpoint, - TargetConf: uint32(ctx.Uint64("conf_target")), - Budget: ctx.Uint64("budget"), - Immediate: ctx.Bool("immediate"), + Outpoint: sweep.Outpoint, + TargetConf: uint32(ctx.Uint64("conf_target")), + Budget: ctx.Uint64("budget"), + Immediate: ctx.Bool("immediate"), + SatPerVbyte: ctx.Uint64("sat_per_vbyte"), }) if err != nil { return err From e45db07a10873012f7c8b62efa10fdd22e13db6b Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 17 May 2024 05:02:02 +0800 Subject: [PATCH 096/109] contractcourt+itest: make sure ChannelArbitrator has the latest htlcs --- contractcourt/chain_arbitrator.go | 4 ++++ contractcourt/channel_arbitrator.go | 3 +++ itest/lnd_multi-hop_test.go | 6 ------ 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/contractcourt/chain_arbitrator.go b/contractcourt/chain_arbitrator.go index fbddd81f0..0cc4b111a 100644 --- a/contractcourt/chain_arbitrator.go +++ b/contractcourt/chain_arbitrator.go @@ -1287,6 +1287,10 @@ func (c *ChainArbitrator) FindOutgoingHTLCDeadline(scid lnwire.ShortChannelID, continue } + // Make sure the channel arbitrator has the latest view of its + // active HTLCs. + channelArb.updateActiveHTLCs() + // Iterate all the known HTLCs to find the targeted incoming // HTLC. for _, htlcs := range channelArb.activeHTLCs { diff --git a/contractcourt/channel_arbitrator.go b/contractcourt/channel_arbitrator.go index f9df71c19..cda0d4e1f 100644 --- a/contractcourt/channel_arbitrator.go +++ b/contractcourt/channel_arbitrator.go @@ -3089,6 +3089,9 @@ func (c *ChannelArbitrator) channelAttendant(bestHeight int32) { // We've just received a request to forcibly close out the // channel. We'll case closeReq := <-c.forceCloseReqs: + log.Infof("ChannelArbitrator(%v): received force "+ + "close request", c.cfg.ChanPoint) + if c.state != StateDefault { select { case closeReq.closeTx <- nil: diff --git a/itest/lnd_multi-hop_test.go b/itest/lnd_multi-hop_test.go index 7ff9f48b4..09b2cdf46 100644 --- a/itest/lnd_multi-hop_test.go +++ b/itest/lnd_multi-hop_test.go @@ -713,12 +713,6 @@ func runMultiHopLocalForceCloseOnChainHtlcTimeout(ht *lntest.HarnessTest, // to be mined to trigger a force close later on. var blocksMined uint32 - // We need to mine a block otherwise `FindOutgoingHTLCDeadline` cannot - // find the incoming HTLC on Bob's ChainArbitrator. - // - // TODO(yy): Investigate and fix it! - ht.MineEmptyBlocks(1) - // Now that all parties have the HTLC locked in, we'll immediately // force close the Bob -> Carol channel. This should trigger contract // resolution mode for both of them. From 347537791e5f8305cea66ed54a8362f8331464c3 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Mon, 20 May 2024 22:02:13 +0800 Subject: [PATCH 097/109] sweep: improve loggings based on feedback This commit changes the logging levels and add a few more loggings based on the testing results from the testnet/mainnet. --- chainntnfs/txnotifier.go | 16 ++++++++-------- sweep/sweeper.go | 17 ++++++++++------- sweep/sweeper_test.go | 4 ++-- sweep/tx_input_set.go | 6 ++++-- 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/chainntnfs/txnotifier.go b/chainntnfs/txnotifier.go index f6cd0c1b8..be471da3c 100644 --- a/chainntnfs/txnotifier.go +++ b/chainntnfs/txnotifier.go @@ -772,8 +772,8 @@ func (n *TxNotifier) CancelConf(confRequest ConfRequest, confID uint64) { return } - Log.Infof("Canceling confirmation notification: conf_id=%d, %v", confID, - confRequest) + Log.Debugf("Canceling confirmation notification: conf_id=%d, %v", + confID, confRequest) // We'll close all the notification channels to let the client know // their cancel request has been fulfilled. @@ -925,7 +925,7 @@ func (n *TxNotifier) dispatchConfDetails( // we'll dispatch a confirmation notification to the caller. confHeight := details.BlockHeight + ntfn.NumConfirmations - 1 if confHeight <= n.currentHeight { - Log.Infof("Dispatching %v confirmation notification for %v", + Log.Debugf("Dispatching %v confirmation notification for %v", ntfn.NumConfirmations, ntfn.ConfRequest) // We'll send a 0 value to the Updates channel, @@ -1058,7 +1058,7 @@ func (n *TxNotifier) RegisterSpend(outpoint *wire.OutPoint, pkScript []byte, n.Lock() defer n.Unlock() - Log.Infof("New spend subscription: spend_id=%d, %v, height_hint=%d", + Log.Debugf("New spend subscription: spend_id=%d, %v, height_hint=%d", ntfn.SpendID, ntfn.SpendRequest, startHeight) // Keep track of the notification request so that we can properly @@ -1136,7 +1136,7 @@ func (n *TxNotifier) RegisterSpend(outpoint *wire.OutPoint, pkScript []byte, // notifications don't also attempt a historical dispatch. spendSet.rescanStatus = rescanPending - Log.Infof("Dispatching historical spend rescan for %v, start=%d, "+ + Log.Debugf("Dispatching historical spend rescan for %v, start=%d, "+ "end=%d", ntfn.SpendRequest, startHeight, n.currentHeight) return &SpendRegistration{ @@ -1171,7 +1171,7 @@ func (n *TxNotifier) CancelSpend(spendRequest SpendRequest, spendID uint64) { return } - Log.Infof("Canceling spend notification: spend_id=%d, %v", spendID, + Log.Debugf("Canceling spend notification: spend_id=%d, %v", spendID, spendRequest) // We'll close all the notification channels to let the client know @@ -1364,7 +1364,7 @@ func (n *TxNotifier) dispatchSpendDetails(ntfn *SpendNtfn, details *SpendDetail) return nil } - Log.Infof("Dispatching confirmed spend notification for %v at "+ + Log.Debugf("Dispatching confirmed spend notification for %v at "+ "current height=%d: %v", ntfn.SpendRequest, n.currentHeight, details) @@ -1743,7 +1743,7 @@ func (n *TxNotifier) NotifyHeight(height uint32) error { for ntfn := range n.ntfnsByConfirmHeight[height] { confSet := n.confNotifications[ntfn.ConfRequest] - Log.Infof("Dispatching %v confirmation notification for %v", + Log.Debugf("Dispatching %v confirmation notification for %v", ntfn.NumConfirmations, ntfn.ConfRequest) // The default notification we assigned above includes the diff --git a/sweep/sweeper.go b/sweep/sweeper.go index e8e7d77a4..39a03228d 100644 --- a/sweep/sweeper.go +++ b/sweep/sweeper.go @@ -767,11 +767,11 @@ func (s *UtxoSweeper) signalResult(pi *SweeperInput, result Result) { listeners := pi.listeners if result.Err == nil { - log.Debugf("Dispatching sweep success for %v to %v listeners", + log.Tracef("Dispatching sweep success for %v to %v listeners", op, len(listeners), ) } else { - log.Debugf("Dispatching sweep error for %v to %v listeners: %v", + log.Tracef("Dispatching sweep error for %v to %v listeners: %v", op, len(listeners), result.Err, ) } @@ -830,6 +830,9 @@ func (s *UtxoSweeper) sweep(set InputSet) error { outpoints[i] = inp.OutPoint() } + log.Errorf("Initial broadcast failed: %v, inputs=\n%v", err, + inputTypeSummary(set.Inputs())) + // TODO(yy): find out which input is causing the failure. s.markInputsPublishFailed(outpoints) @@ -855,7 +858,7 @@ func (s *UtxoSweeper) markInputsPendingPublish(set InputSet) { // It could be that this input is an additional wallet // input that was attached. In that case there also // isn't a pending input to update. - log.Debugf("Skipped marking input as pending "+ + log.Tracef("Skipped marking input as pending "+ "published: %v not found in pending inputs", input.OutPoint()) @@ -904,7 +907,7 @@ func (s *UtxoSweeper) markInputsPublished(tr *TxRecord, // It could be that this input is an additional wallet // input that was attached. In that case there also // isn't a pending input to update. - log.Debugf("Skipped marking input as published: %v "+ + log.Tracef("Skipped marking input as published: %v "+ "not found in pending inputs", input.PreviousOutPoint) @@ -940,7 +943,7 @@ func (s *UtxoSweeper) markInputsPublishFailed(outpoints []wire.OutPoint) { // It could be that this input is an additional wallet // input that was attached. In that case there also // isn't a pending input to update. - log.Debugf("Skipped marking input as publish failed: "+ + log.Tracef("Skipped marking input as publish failed: "+ "%v not found in pending inputs", op) continue @@ -948,7 +951,7 @@ func (s *UtxoSweeper) markInputsPublishFailed(outpoints []wire.OutPoint) { // Valdiate that the input is in an expected state. if pi.state != PendingPublish && pi.state != Published { - log.Errorf("Expect input %v to have %v, instead it "+ + log.Debugf("Expect input %v to have %v, instead it "+ "has %v", op, PendingPublish, pi.state) continue @@ -1397,7 +1400,7 @@ func (s *UtxoSweeper) markInputsSwept(tx *wire.MsgTx, isOurTx bool) { if !ok { // It's very likely that a spending tx contains inputs // that we don't know. - log.Debugf("Skipped marking input as swept: %v not "+ + log.Tracef("Skipped marking input as swept: %v not "+ "found in pending inputs", outpoint) continue diff --git a/sweep/sweeper_test.go b/sweep/sweeper_test.go index 667906de9..c8d9fc510 100644 --- a/sweep/sweeper_test.go +++ b/sweep/sweeper_test.go @@ -695,12 +695,12 @@ func TestSweepPendingInputs(t *testing.T) { // Mock the methods used in `sweep`. This is not important for this // unit test. - setNeedWallet.On("Inputs").Return(nil).Times(4) + setNeedWallet.On("Inputs").Return(nil).Maybe() setNeedWallet.On("DeadlineHeight").Return(testHeight).Once() setNeedWallet.On("Budget").Return(btcutil.Amount(1)).Once() setNeedWallet.On("StartingFeeRate").Return( fn.None[chainfee.SatPerKWeight]()).Once() - normalSet.On("Inputs").Return(nil).Times(4) + normalSet.On("Inputs").Return(nil).Maybe() normalSet.On("DeadlineHeight").Return(testHeight).Once() normalSet.On("Budget").Return(btcutil.Amount(1)).Once() normalSet.On("StartingFeeRate").Return( diff --git a/sweep/tx_input_set.go b/sweep/tx_input_set.go index cfa4a0ba4..27cdafada 100644 --- a/sweep/tx_input_set.go +++ b/sweep/tx_input_set.go @@ -241,13 +241,13 @@ func (b *BudgetInputSet) NeedWalletInput() bool { // If the input's budget is not even covered by itself, we need // to borrow outputs from other inputs. if budgetBorrowable < 0 { - log.Debugf("Input %v specified a budget that exceeds "+ + log.Tracef("Input %v specified a budget that exceeds "+ "its output value: %v > %v", inp, budget, output) } } - log.Tracef("NeedWalletInput: budgetNeeded=%v, budgetBorrowable=%v", + log.Debugf("NeedWalletInput: budgetNeeded=%v, budgetBorrowable=%v", budgetNeeded, budgetBorrowable) // If we don't have enough extra budget to borrow, we need wallet @@ -314,6 +314,8 @@ func (b *BudgetInputSet) AddWalletInputs(wallet Wallet) error { } b.addInput(pi) + log.Debugf("Added wallet input %v to input set", pi) + // Return if we've reached the minimum output amount. if !b.NeedWalletInput() { return nil From 94a9baefeba174fbebe42a12053866c631b849eb Mon Sep 17 00:00:00 2001 From: Keagan McClelland Date: Wed, 15 May 2024 12:15:54 -0700 Subject: [PATCH 098/109] peer: reduce upper bound of pong bytes to ease bandwidth load --- peer/brontide.go | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/peer/brontide.go b/peer/brontide.go index 1fa6c1311..3cb682235 100644 --- a/peer/brontide.go +++ b/peer/brontide.go @@ -76,6 +76,12 @@ const ( // ErrorBufferSize is the number of historic peer errors that we store. ErrorBufferSize = 10 + + // pongSizeCeiling is the upper bound on a uniformly distributed random + // variable that we use for requesting pong responses. We don't use the + // MaxPongBytes (upper bound accepted by the protocol) because it is + // needlessly wasteful of precious Tor bandwidth for little to no gain. + pongSizeCeiling = 4096 ) var ( @@ -558,17 +564,16 @@ func NewBrontide(cfg Config) *Brontide { return lastSerializedBlockHeader[:] } - // TODO(roasbeef): make dynamic in order to - // create fake cover traffic - // NOTE(proofofkeags): this was changed to be - // dynamic to allow better pong identification, - // however, more thought is needed to make this - // actually usable as a traffic decoy + // TODO(roasbeef): make dynamic in order to create fake cover traffic. + // + // NOTE(proofofkeags): this was changed to be dynamic to allow better + // pong identification, however, more thought is needed to make this + // actually usable as a traffic decoy. randPongSize := func() uint16 { return uint16( // We don't need cryptographic randomness here. /* #nosec */ - rand.Intn(lnwire.MaxPongBytes + 1), + rand.Intn(pongSizeCeiling) + 1, ) } From 61191a576dfff5505e4c0ea1527acd4ca26a2791 Mon Sep 17 00:00:00 2001 From: Keagan McClelland Date: Wed, 15 May 2024 14:27:45 -0700 Subject: [PATCH 099/109] peer: make PingManager.Stop infallible --- peer/brontide.go | 8 +++----- peer/ping_manager.go | 10 +++------- peer/ping_manager_test.go | 2 +- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/peer/brontide.go b/peer/brontide.go index 3cb682235..23e9dd834 100644 --- a/peer/brontide.go +++ b/peer/brontide.go @@ -1257,15 +1257,13 @@ func (p *Brontide) Disconnect(reason error) { p.log.Infof(err.Error()) + // Stop PingManager before closing TCP connection. + p.pingManager.Stop() + // Ensure that the TCP connection is properly closed before continuing. p.cfg.Conn.Close() close(p.quit) - - if err := p.pingManager.Stop(); err != nil { - p.log.Errorf("couldn't stop pingManager during disconnect: %v", - err) - } } // String returns the string representation of this peer. diff --git a/peer/ping_manager.go b/peer/ping_manager.go index c456a0581..f5c6180be 100644 --- a/peer/ping_manager.go +++ b/peer/ping_manager.go @@ -196,12 +196,10 @@ func (m *PingManager) pingHandler() { } } -// Stop interrupts the goroutines that the PingManager owns. Can only be called -// when the PingManager is running. -func (m *PingManager) Stop() error { +// Stop interrupts the goroutines that the PingManager owns. +func (m *PingManager) Stop() { if m.pingTicker == nil { - return errors.New("PingManager cannot be stopped because it " + - "isn't running") + return } m.stopped.Do(func() { @@ -211,8 +209,6 @@ func (m *PingManager) Stop() error { m.pingTicker.Stop() m.pingTimeout.Stop() }) - - return nil } // setPingState is a private method to keep track of all of the fields we need diff --git a/peer/ping_manager_test.go b/peer/ping_manager_test.go index bdfeeb6af..0f4c3be49 100644 --- a/peer/ping_manager_test.go +++ b/peer/ping_manager_test.go @@ -83,6 +83,6 @@ func TestPingManager(t *testing.T) { require.False(t, test.result) } - require.NoError(t, mgr.Stop(), "Could not stop pingManager") + mgr.Stop() } } From 1148e572bf4dee930d9fb5be1e69c4bf01cc599c Mon Sep 17 00:00:00 2001 From: Keagan McClelland Date: Thu, 16 May 2024 11:19:20 -0700 Subject: [PATCH 100/109] peer: triple timeout parameters to give tor more grace --- peer/brontide.go | 52 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/peer/brontide.go b/peer/brontide.go index 23e9dd834..7aea59be1 100644 --- a/peer/brontide.go +++ b/peer/brontide.go @@ -7,6 +7,7 @@ import ( "fmt" "math/rand" "net" + "strings" "sync" "sync/atomic" "time" @@ -82,6 +83,10 @@ const ( // MaxPongBytes (upper bound accepted by the protocol) because it is // needlessly wasteful of precious Tor bandwidth for little to no gain. pongSizeCeiling = 4096 + + // torTimeoutMultiplier is the scaling factor we use on network timeouts + // for Tor peers. + torTimeoutMultiplier = 3 ) var ( @@ -395,6 +400,23 @@ type Brontide struct { bytesReceived uint64 bytesSent uint64 + // isTorConnection is a flag that indicates whether or not we believe + // the remote peer is a tor connection. It is not always possible to + // know this with certainty but we have heuristics we use that should + // catch most cases. + // + // NOTE: We judge the tor-ness of a connection by if the remote peer has + // ".onion" in the address OR if it's connected over localhost. + // This will miss cases where our peer is connected to our clearnet + // address over the tor network (via exit nodes). It will also misjudge + // actual localhost connections as tor. We need to include this because + // inbound connections to our tor address will appear to come from the + // local socks5 proxy. This heuristic is only used to expand the timeout + // window for peers so it is OK to misjudge this. If you use this field + // for any other purpose you should seriously consider whether or not + // this heuristic is good enough for your use case. + isTorConnection bool + pingManager *PingManager // lastPingPayload stores an unsafe pointer wrapped as an atomic @@ -534,6 +556,12 @@ func NewBrontide(cfg Config) *Brontide { log: build.NewPrefixLog(logPrefix, peerLog), } + if cfg.Conn != nil && cfg.Conn.RemoteAddr() != nil { + remoteAddr := cfg.Conn.RemoteAddr().String() + p.isTorConnection = strings.Contains(remoteAddr, ".onion") || + strings.Contains(remoteAddr, "127.0.0.1") + } + var ( lastBlockHeader *wire.BlockHeader lastSerializedBlockHeader [wire.MaxBlockHeaderPayload]byte @@ -580,8 +608,8 @@ func NewBrontide(cfg Config) *Brontide { p.pingManager = NewPingManager(&PingManagerConfig{ NewPingPayload: newPingPayload, NewPongSize: randPongSize, - IntervalDuration: pingInterval, - TimeoutDuration: pingTimeout, + IntervalDuration: p.scaleTimeout(pingInterval), + TimeoutDuration: p.scaleTimeout(pingTimeout), SendPing: func(ping *lnwire.Ping) { p.queueMsg(ping, nil) }, @@ -1299,7 +1327,9 @@ func (p *Brontide) readNextMessage() (lnwire.Message, error) { // pool. We do so only after the task has been scheduled to // ensure the deadline doesn't expire while the message is in // the process of being scheduled. - readDeadline := time.Now().Add(readMessageTimeout) + readDeadline := time.Now().Add( + p.scaleTimeout(readMessageTimeout), + ) readErr := noiseConn.SetReadDeadline(readDeadline) if readErr != nil { return readErr @@ -2181,7 +2211,9 @@ func (p *Brontide) writeMessage(msg lnwire.Message) error { flushMsg := func() error { // Ensure the write deadline is set before we attempt to send // the message. - writeDeadline := time.Now().Add(writeMessageTimeout) + writeDeadline := time.Now().Add( + p.scaleTimeout(writeMessageTimeout), + ) err := noiseConn.SetWriteDeadline(writeDeadline) if err != nil { return err @@ -4151,3 +4183,15 @@ func (p *Brontide) sendLinkUpdateMsg(cid lnwire.ChannelID, msg lnwire.Message) { // continue processing message. chanStream.AddMsg(msg) } + +// scaleTimeout multiplies the argument duration by a constant factor depending +// on variious heuristics. Currently this is only used to check whether our peer +// appears to be connected over Tor and relaxes the timout deadline. However, +// this is subject to change and should be treated as opaque. +func (p *Brontide) scaleTimeout(timeout time.Duration) time.Duration { + if p.isTorConnection { + return timeout * time.Duration(torTimeoutMultiplier) + } + + return timeout +} From 74237f2c243c618ec14012b668a923508158e71d Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 22 May 2024 11:43:56 -0700 Subject: [PATCH 101/109] build: bump verison to v0.18.0-beta.rc3 --- build/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/version.go b/build/version.go index 9ff734a2b..d3beca8a0 100644 --- a/build/version.go +++ b/build/version.go @@ -47,7 +47,7 @@ const ( // AppPreRelease MUST only contain characters from semanticAlphabet per // the semantic versioning spec. - AppPreRelease = "beta.rc2" + AppPreRelease = "beta.rc3" ) func init() { From f62c00fe34635c1b68054a9fe018e07e54df4999 Mon Sep 17 00:00:00 2001 From: feelancer21 <2828397+feelancer21@users.noreply.github.com> Date: Tue, 14 May 2024 00:21:26 +0200 Subject: [PATCH 102/109] multi: Inbound fees are retained when not provided Fixes the problem that inbound base fee and fee rate are overwritten with 0 if they are not specified in PolicyUpdateRequest. This ensures backward compatibility with older rpc clients that do not yet support the inbound feature. --- cmd/lncli/commands.go | 26 +- itest/lnd_multi-hop-payments_test.go | 8 +- lnrpc/lightning.pb.go | 2649 +++++++++++++------------- lnrpc/lightning.proto | 15 +- lnrpc/lightning.swagger.json | 25 +- routing/localchans/manager.go | 22 +- routing/router.go | 3 +- rpcserver.go | 31 +- 8 files changed, 1457 insertions(+), 1322 deletions(-) diff --git a/cmd/lncli/commands.go b/cmd/lncli/commands.go index a510138eb..519d1d7fd 100644 --- a/cmd/lncli/commands.go +++ b/cmd/lncli/commands.go @@ -2387,12 +2387,28 @@ func updateChannelPolicy(ctx *cli.Context) error { return errors.New("inbound_fee_rate_ppm out of range") } + // Inbound fees are optional. However, if an update is required, + // both the base fee and the fee rate must be provided. + var inboundFee *lnrpc.InboundFee + if ctx.IsSet("inbound_base_fee_msat") != + ctx.IsSet("inbound_fee_rate_ppm") { + + return errors.New("both parameters must be provided: " + + "inbound_base_fee_msat and inbound_fee_rate_ppm") + } + + if ctx.IsSet("inbound_fee_rate_ppm") { + inboundFee = &lnrpc.InboundFee{ + BaseFeeMsat: int32(inboundBaseFeeMsat), + FeeRatePpm: int32(inboundFeeRatePpm), + } + } + req := &lnrpc.PolicyUpdateRequest{ - BaseFeeMsat: baseFee, - TimeLockDelta: uint32(timeLockDelta), - MaxHtlcMsat: ctx.Uint64("max_htlc_msat"), - InboundBaseFeeMsat: int32(inboundBaseFeeMsat), - InboundFeeRatePpm: int32(inboundFeeRatePpm), + BaseFeeMsat: baseFee, + TimeLockDelta: uint32(timeLockDelta), + MaxHtlcMsat: ctx.Uint64("max_htlc_msat"), + InboundFee: inboundFee, } if ctx.IsSet("min_htlc_msat") { diff --git a/itest/lnd_multi-hop-payments_test.go b/itest/lnd_multi-hop-payments_test.go index 2da2213d7..665b54cab 100644 --- a/itest/lnd_multi-hop-payments_test.go +++ b/itest/lnd_multi-hop-payments_test.go @@ -257,9 +257,11 @@ func updateChannelPolicy(ht *lntest.HarnessTest, hn *node.HarnessNode, Scope: &lnrpc.PolicyUpdateRequest_ChanPoint{ ChanPoint: chanPoint, }, - MaxHtlcMsat: maxHtlc, - InboundBaseFeeMsat: inboundBaseFee, - InboundFeeRatePpm: inboundFeeRate, + MaxHtlcMsat: maxHtlc, + InboundFee: &lnrpc.InboundFee{ + BaseFeeMsat: inboundBaseFee, + FeeRatePpm: inboundFeeRate, + }, } hn.RPC.UpdateChannelPolicy(updateFeeReq) diff --git a/lnrpc/lightning.pb.go b/lnrpc/lightning.pb.go index 161fd2f11..b58a97d7e 100644 --- a/lnrpc/lightning.pb.go +++ b/lnrpc/lightning.pb.go @@ -1368,7 +1368,7 @@ func (x Failure_FailureCode) Number() protoreflect.EnumNumber { // Deprecated: Use Failure_FailureCode.Descriptor instead. func (Failure_FailureCode) EnumDescriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{186, 0} + return file_lightning_proto_rawDescGZIP(), []int{187, 0} } type LookupHtlcResolutionRequest struct { @@ -14717,6 +14717,65 @@ func (x *FeeReportResponse) GetMonthFeeSum() uint64 { return 0 } +type InboundFee struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The inbound base fee charged regardless of the number of milli-satoshis + // received in the channel. By default, only negative values are accepted. + BaseFeeMsat int32 `protobuf:"varint,1,opt,name=base_fee_msat,json=baseFeeMsat,proto3" json:"base_fee_msat,omitempty"` + // The effective inbound fee rate in micro-satoshis (parts per million). + // By default, only negative values are accepted. + FeeRatePpm int32 `protobuf:"varint,2,opt,name=fee_rate_ppm,json=feeRatePpm,proto3" json:"fee_rate_ppm,omitempty"` +} + +func (x *InboundFee) Reset() { + *x = InboundFee{} + if protoimpl.UnsafeEnabled { + mi := &file_lightning_proto_msgTypes[160] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *InboundFee) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InboundFee) ProtoMessage() {} + +func (x *InboundFee) ProtoReflect() protoreflect.Message { + mi := &file_lightning_proto_msgTypes[160] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InboundFee.ProtoReflect.Descriptor instead. +func (*InboundFee) Descriptor() ([]byte, []int) { + return file_lightning_proto_rawDescGZIP(), []int{160} +} + +func (x *InboundFee) GetBaseFeeMsat() int32 { + if x != nil { + return x.BaseFeeMsat + } + return 0 +} + +func (x *InboundFee) GetFeeRatePpm() int32 { + if x != nil { + return x.FeeRatePpm + } + return 0 +} + type PolicyUpdateRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -14743,15 +14802,16 @@ type PolicyUpdateRequest struct { // min_htlc_msat_specified is true. MinHtlcMsat uint64 `protobuf:"varint,7,opt,name=min_htlc_msat,json=minHtlcMsat,proto3" json:"min_htlc_msat,omitempty"` // If true, min_htlc_msat is applied. - MinHtlcMsatSpecified bool `protobuf:"varint,8,opt,name=min_htlc_msat_specified,json=minHtlcMsatSpecified,proto3" json:"min_htlc_msat_specified,omitempty"` - InboundBaseFeeMsat int32 `protobuf:"varint,10,opt,name=inbound_base_fee_msat,json=inboundBaseFeeMsat,proto3" json:"inbound_base_fee_msat,omitempty"` - InboundFeeRatePpm int32 `protobuf:"varint,11,opt,name=inbound_fee_rate_ppm,json=inboundFeeRatePpm,proto3" json:"inbound_fee_rate_ppm,omitempty"` + MinHtlcMsatSpecified bool `protobuf:"varint,8,opt,name=min_htlc_msat_specified,json=minHtlcMsatSpecified,proto3" json:"min_htlc_msat_specified,omitempty"` + // Optional inbound fee. If unset, the previously set value will be + // retained [EXPERIMENTAL]. + InboundFee *InboundFee `protobuf:"bytes,10,opt,name=inbound_fee,json=inboundFee,proto3" json:"inbound_fee,omitempty"` } func (x *PolicyUpdateRequest) Reset() { *x = PolicyUpdateRequest{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[160] + mi := &file_lightning_proto_msgTypes[161] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14764,7 +14824,7 @@ func (x *PolicyUpdateRequest) String() string { func (*PolicyUpdateRequest) ProtoMessage() {} func (x *PolicyUpdateRequest) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[160] + mi := &file_lightning_proto_msgTypes[161] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14777,7 +14837,7 @@ func (x *PolicyUpdateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PolicyUpdateRequest.ProtoReflect.Descriptor instead. func (*PolicyUpdateRequest) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{160} + return file_lightning_proto_rawDescGZIP(), []int{161} } func (m *PolicyUpdateRequest) GetScope() isPolicyUpdateRequest_Scope { @@ -14850,18 +14910,11 @@ func (x *PolicyUpdateRequest) GetMinHtlcMsatSpecified() bool { return false } -func (x *PolicyUpdateRequest) GetInboundBaseFeeMsat() int32 { +func (x *PolicyUpdateRequest) GetInboundFee() *InboundFee { if x != nil { - return x.InboundBaseFeeMsat + return x.InboundFee } - return 0 -} - -func (x *PolicyUpdateRequest) GetInboundFeeRatePpm() int32 { - if x != nil { - return x.InboundFeeRatePpm - } - return 0 + return nil } type isPolicyUpdateRequest_Scope interface { @@ -14898,7 +14951,7 @@ type FailedUpdate struct { func (x *FailedUpdate) Reset() { *x = FailedUpdate{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[161] + mi := &file_lightning_proto_msgTypes[162] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14911,7 +14964,7 @@ func (x *FailedUpdate) String() string { func (*FailedUpdate) ProtoMessage() {} func (x *FailedUpdate) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[161] + mi := &file_lightning_proto_msgTypes[162] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14924,7 +14977,7 @@ func (x *FailedUpdate) ProtoReflect() protoreflect.Message { // Deprecated: Use FailedUpdate.ProtoReflect.Descriptor instead. func (*FailedUpdate) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{161} + return file_lightning_proto_rawDescGZIP(), []int{162} } func (x *FailedUpdate) GetOutpoint() *OutPoint { @@ -14960,7 +15013,7 @@ type PolicyUpdateResponse struct { func (x *PolicyUpdateResponse) Reset() { *x = PolicyUpdateResponse{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[162] + mi := &file_lightning_proto_msgTypes[163] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -14973,7 +15026,7 @@ func (x *PolicyUpdateResponse) String() string { func (*PolicyUpdateResponse) ProtoMessage() {} func (x *PolicyUpdateResponse) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[162] + mi := &file_lightning_proto_msgTypes[163] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -14986,7 +15039,7 @@ func (x *PolicyUpdateResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PolicyUpdateResponse.ProtoReflect.Descriptor instead. func (*PolicyUpdateResponse) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{162} + return file_lightning_proto_rawDescGZIP(), []int{163} } func (x *PolicyUpdateResponse) GetFailedUpdates() []*FailedUpdate { @@ -15023,7 +15076,7 @@ type ForwardingHistoryRequest struct { func (x *ForwardingHistoryRequest) Reset() { *x = ForwardingHistoryRequest{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[163] + mi := &file_lightning_proto_msgTypes[164] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15036,7 +15089,7 @@ func (x *ForwardingHistoryRequest) String() string { func (*ForwardingHistoryRequest) ProtoMessage() {} func (x *ForwardingHistoryRequest) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[163] + mi := &file_lightning_proto_msgTypes[164] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15049,7 +15102,7 @@ func (x *ForwardingHistoryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ForwardingHistoryRequest.ProtoReflect.Descriptor instead. func (*ForwardingHistoryRequest) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{163} + return file_lightning_proto_rawDescGZIP(), []int{164} } func (x *ForwardingHistoryRequest) GetStartTime() uint64 { @@ -15130,7 +15183,7 @@ type ForwardingEvent struct { func (x *ForwardingEvent) Reset() { *x = ForwardingEvent{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[164] + mi := &file_lightning_proto_msgTypes[165] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15143,7 +15196,7 @@ func (x *ForwardingEvent) String() string { func (*ForwardingEvent) ProtoMessage() {} func (x *ForwardingEvent) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[164] + mi := &file_lightning_proto_msgTypes[165] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15156,7 +15209,7 @@ func (x *ForwardingEvent) ProtoReflect() protoreflect.Message { // Deprecated: Use ForwardingEvent.ProtoReflect.Descriptor instead. func (*ForwardingEvent) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{164} + return file_lightning_proto_rawDescGZIP(), []int{165} } // Deprecated: Marked as deprecated in lightning.proto. @@ -15260,7 +15313,7 @@ type ForwardingHistoryResponse struct { func (x *ForwardingHistoryResponse) Reset() { *x = ForwardingHistoryResponse{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[165] + mi := &file_lightning_proto_msgTypes[166] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15273,7 +15326,7 @@ func (x *ForwardingHistoryResponse) String() string { func (*ForwardingHistoryResponse) ProtoMessage() {} func (x *ForwardingHistoryResponse) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[165] + mi := &file_lightning_proto_msgTypes[166] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15286,7 +15339,7 @@ func (x *ForwardingHistoryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ForwardingHistoryResponse.ProtoReflect.Descriptor instead. func (*ForwardingHistoryResponse) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{165} + return file_lightning_proto_rawDescGZIP(), []int{166} } func (x *ForwardingHistoryResponse) GetForwardingEvents() []*ForwardingEvent { @@ -15315,7 +15368,7 @@ type ExportChannelBackupRequest struct { func (x *ExportChannelBackupRequest) Reset() { *x = ExportChannelBackupRequest{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[166] + mi := &file_lightning_proto_msgTypes[167] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15328,7 +15381,7 @@ func (x *ExportChannelBackupRequest) String() string { func (*ExportChannelBackupRequest) ProtoMessage() {} func (x *ExportChannelBackupRequest) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[166] + mi := &file_lightning_proto_msgTypes[167] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15341,7 +15394,7 @@ func (x *ExportChannelBackupRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ExportChannelBackupRequest.ProtoReflect.Descriptor instead. func (*ExportChannelBackupRequest) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{166} + return file_lightning_proto_rawDescGZIP(), []int{167} } func (x *ExportChannelBackupRequest) GetChanPoint() *ChannelPoint { @@ -15368,7 +15421,7 @@ type ChannelBackup struct { func (x *ChannelBackup) Reset() { *x = ChannelBackup{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[167] + mi := &file_lightning_proto_msgTypes[168] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15381,7 +15434,7 @@ func (x *ChannelBackup) String() string { func (*ChannelBackup) ProtoMessage() {} func (x *ChannelBackup) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[167] + mi := &file_lightning_proto_msgTypes[168] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15394,7 +15447,7 @@ func (x *ChannelBackup) ProtoReflect() protoreflect.Message { // Deprecated: Use ChannelBackup.ProtoReflect.Descriptor instead. func (*ChannelBackup) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{167} + return file_lightning_proto_rawDescGZIP(), []int{168} } func (x *ChannelBackup) GetChanPoint() *ChannelPoint { @@ -15428,7 +15481,7 @@ type MultiChanBackup struct { func (x *MultiChanBackup) Reset() { *x = MultiChanBackup{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[168] + mi := &file_lightning_proto_msgTypes[169] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15441,7 +15494,7 @@ func (x *MultiChanBackup) String() string { func (*MultiChanBackup) ProtoMessage() {} func (x *MultiChanBackup) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[168] + mi := &file_lightning_proto_msgTypes[169] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15454,7 +15507,7 @@ func (x *MultiChanBackup) ProtoReflect() protoreflect.Message { // Deprecated: Use MultiChanBackup.ProtoReflect.Descriptor instead. func (*MultiChanBackup) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{168} + return file_lightning_proto_rawDescGZIP(), []int{169} } func (x *MultiChanBackup) GetChanPoints() []*ChannelPoint { @@ -15480,7 +15533,7 @@ type ChanBackupExportRequest struct { func (x *ChanBackupExportRequest) Reset() { *x = ChanBackupExportRequest{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[169] + mi := &file_lightning_proto_msgTypes[170] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15493,7 +15546,7 @@ func (x *ChanBackupExportRequest) String() string { func (*ChanBackupExportRequest) ProtoMessage() {} func (x *ChanBackupExportRequest) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[169] + mi := &file_lightning_proto_msgTypes[170] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15506,7 +15559,7 @@ func (x *ChanBackupExportRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ChanBackupExportRequest.ProtoReflect.Descriptor instead. func (*ChanBackupExportRequest) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{169} + return file_lightning_proto_rawDescGZIP(), []int{170} } type ChanBackupSnapshot struct { @@ -15525,7 +15578,7 @@ type ChanBackupSnapshot struct { func (x *ChanBackupSnapshot) Reset() { *x = ChanBackupSnapshot{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[170] + mi := &file_lightning_proto_msgTypes[171] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15538,7 +15591,7 @@ func (x *ChanBackupSnapshot) String() string { func (*ChanBackupSnapshot) ProtoMessage() {} func (x *ChanBackupSnapshot) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[170] + mi := &file_lightning_proto_msgTypes[171] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15551,7 +15604,7 @@ func (x *ChanBackupSnapshot) ProtoReflect() protoreflect.Message { // Deprecated: Use ChanBackupSnapshot.ProtoReflect.Descriptor instead. func (*ChanBackupSnapshot) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{170} + return file_lightning_proto_rawDescGZIP(), []int{171} } func (x *ChanBackupSnapshot) GetSingleChanBackups() *ChannelBackups { @@ -15580,7 +15633,7 @@ type ChannelBackups struct { func (x *ChannelBackups) Reset() { *x = ChannelBackups{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[171] + mi := &file_lightning_proto_msgTypes[172] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15593,7 +15646,7 @@ func (x *ChannelBackups) String() string { func (*ChannelBackups) ProtoMessage() {} func (x *ChannelBackups) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[171] + mi := &file_lightning_proto_msgTypes[172] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15606,7 +15659,7 @@ func (x *ChannelBackups) ProtoReflect() protoreflect.Message { // Deprecated: Use ChannelBackups.ProtoReflect.Descriptor instead. func (*ChannelBackups) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{171} + return file_lightning_proto_rawDescGZIP(), []int{172} } func (x *ChannelBackups) GetChanBackups() []*ChannelBackup { @@ -15631,7 +15684,7 @@ type RestoreChanBackupRequest struct { func (x *RestoreChanBackupRequest) Reset() { *x = RestoreChanBackupRequest{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[172] + mi := &file_lightning_proto_msgTypes[173] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15644,7 +15697,7 @@ func (x *RestoreChanBackupRequest) String() string { func (*RestoreChanBackupRequest) ProtoMessage() {} func (x *RestoreChanBackupRequest) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[172] + mi := &file_lightning_proto_msgTypes[173] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15657,7 +15710,7 @@ func (x *RestoreChanBackupRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RestoreChanBackupRequest.ProtoReflect.Descriptor instead. func (*RestoreChanBackupRequest) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{172} + return file_lightning_proto_rawDescGZIP(), []int{173} } func (m *RestoreChanBackupRequest) GetBackup() isRestoreChanBackupRequest_Backup { @@ -15709,7 +15762,7 @@ type RestoreBackupResponse struct { func (x *RestoreBackupResponse) Reset() { *x = RestoreBackupResponse{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[173] + mi := &file_lightning_proto_msgTypes[174] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15722,7 +15775,7 @@ func (x *RestoreBackupResponse) String() string { func (*RestoreBackupResponse) ProtoMessage() {} func (x *RestoreBackupResponse) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[173] + mi := &file_lightning_proto_msgTypes[174] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15735,7 +15788,7 @@ func (x *RestoreBackupResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RestoreBackupResponse.ProtoReflect.Descriptor instead. func (*RestoreBackupResponse) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{173} + return file_lightning_proto_rawDescGZIP(), []int{174} } type ChannelBackupSubscription struct { @@ -15747,7 +15800,7 @@ type ChannelBackupSubscription struct { func (x *ChannelBackupSubscription) Reset() { *x = ChannelBackupSubscription{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[174] + mi := &file_lightning_proto_msgTypes[175] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15760,7 +15813,7 @@ func (x *ChannelBackupSubscription) String() string { func (*ChannelBackupSubscription) ProtoMessage() {} func (x *ChannelBackupSubscription) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[174] + mi := &file_lightning_proto_msgTypes[175] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15773,7 +15826,7 @@ func (x *ChannelBackupSubscription) ProtoReflect() protoreflect.Message { // Deprecated: Use ChannelBackupSubscription.ProtoReflect.Descriptor instead. func (*ChannelBackupSubscription) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{174} + return file_lightning_proto_rawDescGZIP(), []int{175} } type VerifyChanBackupResponse struct { @@ -15785,7 +15838,7 @@ type VerifyChanBackupResponse struct { func (x *VerifyChanBackupResponse) Reset() { *x = VerifyChanBackupResponse{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[175] + mi := &file_lightning_proto_msgTypes[176] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15798,7 +15851,7 @@ func (x *VerifyChanBackupResponse) String() string { func (*VerifyChanBackupResponse) ProtoMessage() {} func (x *VerifyChanBackupResponse) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[175] + mi := &file_lightning_proto_msgTypes[176] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15811,7 +15864,7 @@ func (x *VerifyChanBackupResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use VerifyChanBackupResponse.ProtoReflect.Descriptor instead. func (*VerifyChanBackupResponse) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{175} + return file_lightning_proto_rawDescGZIP(), []int{176} } type MacaroonPermission struct { @@ -15828,7 +15881,7 @@ type MacaroonPermission struct { func (x *MacaroonPermission) Reset() { *x = MacaroonPermission{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[176] + mi := &file_lightning_proto_msgTypes[177] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15841,7 +15894,7 @@ func (x *MacaroonPermission) String() string { func (*MacaroonPermission) ProtoMessage() {} func (x *MacaroonPermission) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[176] + mi := &file_lightning_proto_msgTypes[177] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15854,7 +15907,7 @@ func (x *MacaroonPermission) ProtoReflect() protoreflect.Message { // Deprecated: Use MacaroonPermission.ProtoReflect.Descriptor instead. func (*MacaroonPermission) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{176} + return file_lightning_proto_rawDescGZIP(), []int{177} } func (x *MacaroonPermission) GetEntity() string { @@ -15888,7 +15941,7 @@ type BakeMacaroonRequest struct { func (x *BakeMacaroonRequest) Reset() { *x = BakeMacaroonRequest{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[177] + mi := &file_lightning_proto_msgTypes[178] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15901,7 +15954,7 @@ func (x *BakeMacaroonRequest) String() string { func (*BakeMacaroonRequest) ProtoMessage() {} func (x *BakeMacaroonRequest) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[177] + mi := &file_lightning_proto_msgTypes[178] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15914,7 +15967,7 @@ func (x *BakeMacaroonRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use BakeMacaroonRequest.ProtoReflect.Descriptor instead. func (*BakeMacaroonRequest) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{177} + return file_lightning_proto_rawDescGZIP(), []int{178} } func (x *BakeMacaroonRequest) GetPermissions() []*MacaroonPermission { @@ -15950,7 +16003,7 @@ type BakeMacaroonResponse struct { func (x *BakeMacaroonResponse) Reset() { *x = BakeMacaroonResponse{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[178] + mi := &file_lightning_proto_msgTypes[179] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -15963,7 +16016,7 @@ func (x *BakeMacaroonResponse) String() string { func (*BakeMacaroonResponse) ProtoMessage() {} func (x *BakeMacaroonResponse) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[178] + mi := &file_lightning_proto_msgTypes[179] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -15976,7 +16029,7 @@ func (x *BakeMacaroonResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use BakeMacaroonResponse.ProtoReflect.Descriptor instead. func (*BakeMacaroonResponse) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{178} + return file_lightning_proto_rawDescGZIP(), []int{179} } func (x *BakeMacaroonResponse) GetMacaroon() string { @@ -15995,7 +16048,7 @@ type ListMacaroonIDsRequest struct { func (x *ListMacaroonIDsRequest) Reset() { *x = ListMacaroonIDsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[179] + mi := &file_lightning_proto_msgTypes[180] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16008,7 +16061,7 @@ func (x *ListMacaroonIDsRequest) String() string { func (*ListMacaroonIDsRequest) ProtoMessage() {} func (x *ListMacaroonIDsRequest) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[179] + mi := &file_lightning_proto_msgTypes[180] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16021,7 +16074,7 @@ func (x *ListMacaroonIDsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListMacaroonIDsRequest.ProtoReflect.Descriptor instead. func (*ListMacaroonIDsRequest) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{179} + return file_lightning_proto_rawDescGZIP(), []int{180} } type ListMacaroonIDsResponse struct { @@ -16036,7 +16089,7 @@ type ListMacaroonIDsResponse struct { func (x *ListMacaroonIDsResponse) Reset() { *x = ListMacaroonIDsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[180] + mi := &file_lightning_proto_msgTypes[181] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16049,7 +16102,7 @@ func (x *ListMacaroonIDsResponse) String() string { func (*ListMacaroonIDsResponse) ProtoMessage() {} func (x *ListMacaroonIDsResponse) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[180] + mi := &file_lightning_proto_msgTypes[181] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16062,7 +16115,7 @@ func (x *ListMacaroonIDsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListMacaroonIDsResponse.ProtoReflect.Descriptor instead. func (*ListMacaroonIDsResponse) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{180} + return file_lightning_proto_rawDescGZIP(), []int{181} } func (x *ListMacaroonIDsResponse) GetRootKeyIds() []uint64 { @@ -16084,7 +16137,7 @@ type DeleteMacaroonIDRequest struct { func (x *DeleteMacaroonIDRequest) Reset() { *x = DeleteMacaroonIDRequest{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[181] + mi := &file_lightning_proto_msgTypes[182] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16097,7 +16150,7 @@ func (x *DeleteMacaroonIDRequest) String() string { func (*DeleteMacaroonIDRequest) ProtoMessage() {} func (x *DeleteMacaroonIDRequest) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[181] + mi := &file_lightning_proto_msgTypes[182] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16110,7 +16163,7 @@ func (x *DeleteMacaroonIDRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteMacaroonIDRequest.ProtoReflect.Descriptor instead. func (*DeleteMacaroonIDRequest) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{181} + return file_lightning_proto_rawDescGZIP(), []int{182} } func (x *DeleteMacaroonIDRequest) GetRootKeyId() uint64 { @@ -16132,7 +16185,7 @@ type DeleteMacaroonIDResponse struct { func (x *DeleteMacaroonIDResponse) Reset() { *x = DeleteMacaroonIDResponse{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[182] + mi := &file_lightning_proto_msgTypes[183] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16145,7 +16198,7 @@ func (x *DeleteMacaroonIDResponse) String() string { func (*DeleteMacaroonIDResponse) ProtoMessage() {} func (x *DeleteMacaroonIDResponse) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[182] + mi := &file_lightning_proto_msgTypes[183] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16158,7 +16211,7 @@ func (x *DeleteMacaroonIDResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteMacaroonIDResponse.ProtoReflect.Descriptor instead. func (*DeleteMacaroonIDResponse) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{182} + return file_lightning_proto_rawDescGZIP(), []int{183} } func (x *DeleteMacaroonIDResponse) GetDeleted() bool { @@ -16180,7 +16233,7 @@ type MacaroonPermissionList struct { func (x *MacaroonPermissionList) Reset() { *x = MacaroonPermissionList{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[183] + mi := &file_lightning_proto_msgTypes[184] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16193,7 +16246,7 @@ func (x *MacaroonPermissionList) String() string { func (*MacaroonPermissionList) ProtoMessage() {} func (x *MacaroonPermissionList) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[183] + mi := &file_lightning_proto_msgTypes[184] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16206,7 +16259,7 @@ func (x *MacaroonPermissionList) ProtoReflect() protoreflect.Message { // Deprecated: Use MacaroonPermissionList.ProtoReflect.Descriptor instead. func (*MacaroonPermissionList) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{183} + return file_lightning_proto_rawDescGZIP(), []int{184} } func (x *MacaroonPermissionList) GetPermissions() []*MacaroonPermission { @@ -16225,7 +16278,7 @@ type ListPermissionsRequest struct { func (x *ListPermissionsRequest) Reset() { *x = ListPermissionsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[184] + mi := &file_lightning_proto_msgTypes[185] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16238,7 +16291,7 @@ func (x *ListPermissionsRequest) String() string { func (*ListPermissionsRequest) ProtoMessage() {} func (x *ListPermissionsRequest) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[184] + mi := &file_lightning_proto_msgTypes[185] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16251,7 +16304,7 @@ func (x *ListPermissionsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListPermissionsRequest.ProtoReflect.Descriptor instead. func (*ListPermissionsRequest) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{184} + return file_lightning_proto_rawDescGZIP(), []int{185} } type ListPermissionsResponse struct { @@ -16267,7 +16320,7 @@ type ListPermissionsResponse struct { func (x *ListPermissionsResponse) Reset() { *x = ListPermissionsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[185] + mi := &file_lightning_proto_msgTypes[186] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16280,7 +16333,7 @@ func (x *ListPermissionsResponse) String() string { func (*ListPermissionsResponse) ProtoMessage() {} func (x *ListPermissionsResponse) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[185] + mi := &file_lightning_proto_msgTypes[186] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16293,7 +16346,7 @@ func (x *ListPermissionsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListPermissionsResponse.ProtoReflect.Descriptor instead. func (*ListPermissionsResponse) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{185} + return file_lightning_proto_rawDescGZIP(), []int{186} } func (x *ListPermissionsResponse) GetMethodPermissions() map[string]*MacaroonPermissionList { @@ -16330,7 +16383,7 @@ type Failure struct { func (x *Failure) Reset() { *x = Failure{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[186] + mi := &file_lightning_proto_msgTypes[187] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16343,7 +16396,7 @@ func (x *Failure) String() string { func (*Failure) ProtoMessage() {} func (x *Failure) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[186] + mi := &file_lightning_proto_msgTypes[187] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16356,7 +16409,7 @@ func (x *Failure) ProtoReflect() protoreflect.Message { // Deprecated: Use Failure.ProtoReflect.Descriptor instead. func (*Failure) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{186} + return file_lightning_proto_rawDescGZIP(), []int{187} } func (x *Failure) GetCode() Failure_FailureCode { @@ -16470,7 +16523,7 @@ type ChannelUpdate struct { func (x *ChannelUpdate) Reset() { *x = ChannelUpdate{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[187] + mi := &file_lightning_proto_msgTypes[188] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16483,7 +16536,7 @@ func (x *ChannelUpdate) String() string { func (*ChannelUpdate) ProtoMessage() {} func (x *ChannelUpdate) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[187] + mi := &file_lightning_proto_msgTypes[188] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16496,7 +16549,7 @@ func (x *ChannelUpdate) ProtoReflect() protoreflect.Message { // Deprecated: Use ChannelUpdate.ProtoReflect.Descriptor instead. func (*ChannelUpdate) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{187} + return file_lightning_proto_rawDescGZIP(), []int{188} } func (x *ChannelUpdate) GetSignature() []byte { @@ -16596,7 +16649,7 @@ type MacaroonId struct { func (x *MacaroonId) Reset() { *x = MacaroonId{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[188] + mi := &file_lightning_proto_msgTypes[189] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16609,7 +16662,7 @@ func (x *MacaroonId) String() string { func (*MacaroonId) ProtoMessage() {} func (x *MacaroonId) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[188] + mi := &file_lightning_proto_msgTypes[189] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16622,7 +16675,7 @@ func (x *MacaroonId) ProtoReflect() protoreflect.Message { // Deprecated: Use MacaroonId.ProtoReflect.Descriptor instead. func (*MacaroonId) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{188} + return file_lightning_proto_rawDescGZIP(), []int{189} } func (x *MacaroonId) GetNonce() []byte { @@ -16658,7 +16711,7 @@ type Op struct { func (x *Op) Reset() { *x = Op{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[189] + mi := &file_lightning_proto_msgTypes[190] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16671,7 +16724,7 @@ func (x *Op) String() string { func (*Op) ProtoMessage() {} func (x *Op) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[189] + mi := &file_lightning_proto_msgTypes[190] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16684,7 +16737,7 @@ func (x *Op) ProtoReflect() protoreflect.Message { // Deprecated: Use Op.ProtoReflect.Descriptor instead. func (*Op) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{189} + return file_lightning_proto_rawDescGZIP(), []int{190} } func (x *Op) GetEntity() string { @@ -16714,7 +16767,7 @@ type CheckMacPermRequest struct { func (x *CheckMacPermRequest) Reset() { *x = CheckMacPermRequest{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[190] + mi := &file_lightning_proto_msgTypes[191] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16727,7 +16780,7 @@ func (x *CheckMacPermRequest) String() string { func (*CheckMacPermRequest) ProtoMessage() {} func (x *CheckMacPermRequest) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[190] + mi := &file_lightning_proto_msgTypes[191] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16740,7 +16793,7 @@ func (x *CheckMacPermRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CheckMacPermRequest.ProtoReflect.Descriptor instead. func (*CheckMacPermRequest) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{190} + return file_lightning_proto_rawDescGZIP(), []int{191} } func (x *CheckMacPermRequest) GetMacaroon() []byte { @@ -16775,7 +16828,7 @@ type CheckMacPermResponse struct { func (x *CheckMacPermResponse) Reset() { *x = CheckMacPermResponse{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[191] + mi := &file_lightning_proto_msgTypes[192] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16788,7 +16841,7 @@ func (x *CheckMacPermResponse) String() string { func (*CheckMacPermResponse) ProtoMessage() {} func (x *CheckMacPermResponse) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[191] + mi := &file_lightning_proto_msgTypes[192] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16801,7 +16854,7 @@ func (x *CheckMacPermResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CheckMacPermResponse.ProtoReflect.Descriptor instead. func (*CheckMacPermResponse) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{191} + return file_lightning_proto_rawDescGZIP(), []int{192} } func (x *CheckMacPermResponse) GetValid() bool { @@ -16855,7 +16908,7 @@ type RPCMiddlewareRequest struct { func (x *RPCMiddlewareRequest) Reset() { *x = RPCMiddlewareRequest{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[192] + mi := &file_lightning_proto_msgTypes[193] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -16868,7 +16921,7 @@ func (x *RPCMiddlewareRequest) String() string { func (*RPCMiddlewareRequest) ProtoMessage() {} func (x *RPCMiddlewareRequest) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[192] + mi := &file_lightning_proto_msgTypes[193] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -16881,7 +16934,7 @@ func (x *RPCMiddlewareRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RPCMiddlewareRequest.ProtoReflect.Descriptor instead. func (*RPCMiddlewareRequest) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{192} + return file_lightning_proto_rawDescGZIP(), []int{193} } func (x *RPCMiddlewareRequest) GetRequestId() uint64 { @@ -17009,7 +17062,7 @@ type StreamAuth struct { func (x *StreamAuth) Reset() { *x = StreamAuth{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[193] + mi := &file_lightning_proto_msgTypes[194] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17022,7 +17075,7 @@ func (x *StreamAuth) String() string { func (*StreamAuth) ProtoMessage() {} func (x *StreamAuth) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[193] + mi := &file_lightning_proto_msgTypes[194] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17035,7 +17088,7 @@ func (x *StreamAuth) ProtoReflect() protoreflect.Message { // Deprecated: Use StreamAuth.ProtoReflect.Descriptor instead. func (*StreamAuth) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{193} + return file_lightning_proto_rawDescGZIP(), []int{194} } func (x *StreamAuth) GetMethodFullUri() string { @@ -17072,7 +17125,7 @@ type RPCMessage struct { func (x *RPCMessage) Reset() { *x = RPCMessage{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[194] + mi := &file_lightning_proto_msgTypes[195] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17085,7 +17138,7 @@ func (x *RPCMessage) String() string { func (*RPCMessage) ProtoMessage() {} func (x *RPCMessage) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[194] + mi := &file_lightning_proto_msgTypes[195] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17098,7 +17151,7 @@ func (x *RPCMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use RPCMessage.ProtoReflect.Descriptor instead. func (*RPCMessage) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{194} + return file_lightning_proto_rawDescGZIP(), []int{195} } func (x *RPCMessage) GetMethodFullUri() string { @@ -17159,7 +17212,7 @@ type RPCMiddlewareResponse struct { func (x *RPCMiddlewareResponse) Reset() { *x = RPCMiddlewareResponse{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[195] + mi := &file_lightning_proto_msgTypes[196] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17172,7 +17225,7 @@ func (x *RPCMiddlewareResponse) String() string { func (*RPCMiddlewareResponse) ProtoMessage() {} func (x *RPCMiddlewareResponse) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[195] + mi := &file_lightning_proto_msgTypes[196] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17185,7 +17238,7 @@ func (x *RPCMiddlewareResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RPCMiddlewareResponse.ProtoReflect.Descriptor instead. func (*RPCMiddlewareResponse) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{195} + return file_lightning_proto_rawDescGZIP(), []int{196} } func (x *RPCMiddlewareResponse) GetRefMsgId() uint64 { @@ -17271,7 +17324,7 @@ type MiddlewareRegistration struct { func (x *MiddlewareRegistration) Reset() { *x = MiddlewareRegistration{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[196] + mi := &file_lightning_proto_msgTypes[197] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17284,7 +17337,7 @@ func (x *MiddlewareRegistration) String() string { func (*MiddlewareRegistration) ProtoMessage() {} func (x *MiddlewareRegistration) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[196] + mi := &file_lightning_proto_msgTypes[197] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17297,7 +17350,7 @@ func (x *MiddlewareRegistration) ProtoReflect() protoreflect.Message { // Deprecated: Use MiddlewareRegistration.ProtoReflect.Descriptor instead. func (*MiddlewareRegistration) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{196} + return file_lightning_proto_rawDescGZIP(), []int{197} } func (x *MiddlewareRegistration) GetMiddlewareName() string { @@ -17344,7 +17397,7 @@ type InterceptFeedback struct { func (x *InterceptFeedback) Reset() { *x = InterceptFeedback{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[197] + mi := &file_lightning_proto_msgTypes[198] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17357,7 +17410,7 @@ func (x *InterceptFeedback) String() string { func (*InterceptFeedback) ProtoMessage() {} func (x *InterceptFeedback) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[197] + mi := &file_lightning_proto_msgTypes[198] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17370,7 +17423,7 @@ func (x *InterceptFeedback) ProtoReflect() protoreflect.Message { // Deprecated: Use InterceptFeedback.ProtoReflect.Descriptor instead. func (*InterceptFeedback) Descriptor() ([]byte, []int) { - return file_lightning_proto_rawDescGZIP(), []int{197} + return file_lightning_proto_rawDescGZIP(), []int{198} } func (x *InterceptFeedback) GetError() string { @@ -17429,7 +17482,7 @@ type PendingChannelsResponse_PendingChannel struct { func (x *PendingChannelsResponse_PendingChannel) Reset() { *x = PendingChannelsResponse_PendingChannel{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[204] + mi := &file_lightning_proto_msgTypes[205] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17442,7 +17495,7 @@ func (x *PendingChannelsResponse_PendingChannel) String() string { func (*PendingChannelsResponse_PendingChannel) ProtoMessage() {} func (x *PendingChannelsResponse_PendingChannel) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[204] + mi := &file_lightning_proto_msgTypes[205] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17583,7 +17636,7 @@ type PendingChannelsResponse_PendingOpenChannel struct { func (x *PendingChannelsResponse_PendingOpenChannel) Reset() { *x = PendingChannelsResponse_PendingOpenChannel{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[205] + mi := &file_lightning_proto_msgTypes[206] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17596,7 +17649,7 @@ func (x *PendingChannelsResponse_PendingOpenChannel) String() string { func (*PendingChannelsResponse_PendingOpenChannel) ProtoMessage() {} func (x *PendingChannelsResponse_PendingOpenChannel) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[205] + mi := &file_lightning_proto_msgTypes[206] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17669,7 +17722,7 @@ type PendingChannelsResponse_WaitingCloseChannel struct { func (x *PendingChannelsResponse_WaitingCloseChannel) Reset() { *x = PendingChannelsResponse_WaitingCloseChannel{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[206] + mi := &file_lightning_proto_msgTypes[207] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17682,7 +17735,7 @@ func (x *PendingChannelsResponse_WaitingCloseChannel) String() string { func (*PendingChannelsResponse_WaitingCloseChannel) ProtoMessage() {} func (x *PendingChannelsResponse_WaitingCloseChannel) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[206] + mi := &file_lightning_proto_msgTypes[207] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17758,7 +17811,7 @@ type PendingChannelsResponse_Commitments struct { func (x *PendingChannelsResponse_Commitments) Reset() { *x = PendingChannelsResponse_Commitments{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[207] + mi := &file_lightning_proto_msgTypes[208] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17771,7 +17824,7 @@ func (x *PendingChannelsResponse_Commitments) String() string { func (*PendingChannelsResponse_Commitments) ProtoMessage() {} func (x *PendingChannelsResponse_Commitments) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[207] + mi := &file_lightning_proto_msgTypes[208] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17843,7 +17896,7 @@ type PendingChannelsResponse_ClosedChannel struct { func (x *PendingChannelsResponse_ClosedChannel) Reset() { *x = PendingChannelsResponse_ClosedChannel{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[208] + mi := &file_lightning_proto_msgTypes[209] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17856,7 +17909,7 @@ func (x *PendingChannelsResponse_ClosedChannel) String() string { func (*PendingChannelsResponse_ClosedChannel) ProtoMessage() {} func (x *PendingChannelsResponse_ClosedChannel) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[208] + mi := &file_lightning_proto_msgTypes[209] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -17912,7 +17965,7 @@ type PendingChannelsResponse_ForceClosedChannel struct { func (x *PendingChannelsResponse_ForceClosedChannel) Reset() { *x = PendingChannelsResponse_ForceClosedChannel{} if protoimpl.UnsafeEnabled { - mi := &file_lightning_proto_msgTypes[209] + mi := &file_lightning_proto_msgTypes[210] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -17925,7 +17978,7 @@ func (x *PendingChannelsResponse_ForceClosedChannel) String() string { func (*PendingChannelsResponse_ForceClosedChannel) ProtoMessage() {} func (x *PendingChannelsResponse_ForceClosedChannel) ProtoReflect() protoreflect.Message { - mi := &file_lightning_proto_msgTypes[209] + mi := &file_lightning_proto_msgTypes[210] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -20208,845 +20261,847 @@ var file_lightning_proto_rawDesc = []byte{ 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x77, 0x65, 0x65, 0x6b, 0x46, 0x65, 0x65, 0x53, 0x75, 0x6d, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x46, - 0x65, 0x65, 0x53, 0x75, 0x6d, 0x22, 0xda, 0x03, 0x0a, 0x13, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, - 0x06, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, - 0x06, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x12, 0x34, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x5f, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6c, 0x6e, - 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x69, 0x6e, 0x74, - 0x48, 0x00, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x22, 0x0a, - 0x0d, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x62, 0x61, 0x73, 0x65, 0x46, 0x65, 0x65, 0x4d, 0x73, 0x61, - 0x74, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x01, 0x52, 0x07, 0x66, 0x65, 0x65, 0x52, 0x61, 0x74, 0x65, 0x12, 0x20, 0x0a, 0x0c, - 0x66, 0x65, 0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x70, 0x6d, 0x18, 0x09, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x0a, 0x66, 0x65, 0x65, 0x52, 0x61, 0x74, 0x65, 0x50, 0x70, 0x6d, 0x12, 0x26, - 0x0a, 0x0f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x64, 0x65, 0x6c, 0x74, - 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x74, 0x69, 0x6d, 0x65, 0x4c, 0x6f, 0x63, - 0x6b, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x68, 0x74, - 0x6c, 0x63, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, - 0x61, 0x78, 0x48, 0x74, 0x6c, 0x63, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x69, - 0x6e, 0x5f, 0x68, 0x74, 0x6c, 0x63, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x0b, 0x6d, 0x69, 0x6e, 0x48, 0x74, 0x6c, 0x63, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x35, - 0x0a, 0x17, 0x6d, 0x69, 0x6e, 0x5f, 0x68, 0x74, 0x6c, 0x63, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x5f, - 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x14, 0x6d, 0x69, 0x6e, 0x48, 0x74, 0x6c, 0x63, 0x4d, 0x73, 0x61, 0x74, 0x53, 0x70, 0x65, 0x63, - 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x31, 0x0a, 0x15, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, - 0x5f, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x61, 0x73, - 0x65, 0x46, 0x65, 0x65, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x2f, 0x0a, 0x14, 0x69, 0x6e, 0x62, 0x6f, - 0x75, 0x6e, 0x64, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x70, 0x6d, - 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x46, - 0x65, 0x65, 0x52, 0x61, 0x74, 0x65, 0x50, 0x70, 0x6d, 0x42, 0x07, 0x0a, 0x05, 0x73, 0x63, 0x6f, - 0x70, 0x65, 0x22, 0x8c, 0x01, 0x0a, 0x0c, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x12, 0x2b, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x75, - 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x12, 0x2c, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x14, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, - 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x21, - 0x0a, 0x0c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x22, 0x52, 0x0a, 0x14, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x0e, 0x66, 0x61, 0x69, - 0x6c, 0x65, 0x64, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x73, 0x22, 0xc9, 0x01, 0x0a, 0x18, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, - 0x64, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, - 0x65, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x0b, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, - 0x24, 0x0a, 0x0e, 0x6e, 0x75, 0x6d, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6e, 0x75, 0x6d, 0x4d, 0x61, 0x78, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x61, 0x6c, - 0x69, 0x61, 0x73, 0x5f, 0x6c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0f, 0x70, 0x65, 0x65, 0x72, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, - 0x70, 0x22, 0x85, 0x03, 0x0a, 0x0f, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x20, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x18, 0x01, 0x52, 0x09, 0x74, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x20, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x5f, - 0x69, 0x64, 0x5f, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x30, 0x01, 0x52, - 0x08, 0x63, 0x68, 0x61, 0x6e, 0x49, 0x64, 0x49, 0x6e, 0x12, 0x22, 0x0a, 0x0b, 0x63, 0x68, 0x61, - 0x6e, 0x5f, 0x69, 0x64, 0x5f, 0x6f, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, - 0x30, 0x01, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x49, 0x64, 0x4f, 0x75, 0x74, 0x12, 0x15, 0x0a, - 0x06, 0x61, 0x6d, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x61, - 0x6d, 0x74, 0x49, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x61, 0x6d, 0x74, 0x5f, 0x6f, 0x75, 0x74, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x74, 0x4f, 0x75, 0x74, 0x12, 0x10, 0x0a, - 0x03, 0x66, 0x65, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x66, 0x65, 0x65, 0x12, - 0x19, 0x0a, 0x08, 0x66, 0x65, 0x65, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x07, 0x66, 0x65, 0x65, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x1e, 0x0a, 0x0b, 0x61, 0x6d, - 0x74, 0x5f, 0x69, 0x6e, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x09, 0x61, 0x6d, 0x74, 0x49, 0x6e, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x20, 0x0a, 0x0c, 0x61, 0x6d, - 0x74, 0x5f, 0x6f, 0x75, 0x74, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x0a, 0x61, 0x6d, 0x74, 0x4f, 0x75, 0x74, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x21, 0x0a, 0x0c, - 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x6e, 0x73, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4e, 0x73, 0x12, - 0x22, 0x0a, 0x0d, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x5f, 0x69, 0x6e, - 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x65, 0x65, 0x72, 0x41, 0x6c, 0x69, 0x61, - 0x73, 0x49, 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x61, 0x6c, 0x69, 0x61, - 0x73, 0x5f, 0x6f, 0x75, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x65, 0x65, - 0x72, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4f, 0x75, 0x74, 0x22, 0x8c, 0x01, 0x0a, 0x19, 0x46, 0x6f, - 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x11, 0x66, 0x6f, 0x72, 0x77, 0x61, - 0x72, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, 0x77, 0x61, - 0x72, 0x64, 0x69, 0x6e, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x10, 0x66, 0x6f, 0x72, 0x77, - 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, - 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, - 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x4f, 0x66, 0x66, - 0x73, 0x65, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x50, 0x0a, 0x1a, 0x45, 0x78, 0x70, 0x6f, - 0x72, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x32, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, - 0x09, 0x63, 0x68, 0x61, 0x6e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x22, 0x64, 0x0a, 0x0d, 0x43, 0x68, - 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x32, 0x0a, 0x0a, 0x63, - 0x68, 0x61, 0x6e, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x65, 0x65, 0x53, 0x75, 0x6d, 0x22, 0x52, 0x0a, 0x0a, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, + 0x46, 0x65, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x66, 0x65, 0x65, 0x5f, + 0x6d, 0x73, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x62, 0x61, 0x73, 0x65, + 0x46, 0x65, 0x65, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x20, 0x0a, 0x0c, 0x66, 0x65, 0x65, 0x5f, 0x72, + 0x61, 0x74, 0x65, 0x5f, 0x70, 0x70, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x66, + 0x65, 0x65, 0x52, 0x61, 0x74, 0x65, 0x50, 0x70, 0x6d, 0x22, 0xaa, 0x03, 0x0a, 0x13, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x18, 0x0a, 0x06, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x08, 0x48, 0x00, 0x52, 0x06, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x12, 0x34, 0x0a, 0x0a, 0x63, + 0x68, 0x61, 0x6e, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, - 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, - 0x1f, 0x0a, 0x0b, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, - 0x22, 0x73, 0x0a, 0x0f, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, - 0x6b, 0x75, 0x70, 0x12, 0x34, 0x0a, 0x0b, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x63, - 0x68, 0x61, 0x6e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x75, 0x6c, - 0x74, 0x69, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x43, 0x68, 0x61, 0x6e, 0x42, - 0x61, 0x63, 0x6b, 0x75, 0x70, 0x22, 0x19, 0x0a, 0x17, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, - 0x6b, 0x75, 0x70, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x22, 0x9f, 0x01, 0x0a, 0x12, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, - 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x45, 0x0a, 0x13, 0x73, 0x69, 0x6e, 0x67, 0x6c, - 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, - 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x52, 0x11, 0x73, 0x69, 0x6e, - 0x67, 0x6c, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12, 0x42, - 0x0a, 0x11, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x62, 0x61, 0x63, - 0x6b, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, - 0x70, 0x52, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, - 0x75, 0x70, 0x22, 0x49, 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, - 0x6b, 0x75, 0x70, 0x73, 0x12, 0x37, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x62, 0x61, 0x63, - 0x6b, 0x75, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, - 0x52, 0x0b, 0x63, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x22, 0x8e, 0x01, - 0x0a, 0x18, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, - 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x0c, 0x63, 0x68, - 0x61, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x15, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, - 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x48, 0x00, 0x52, 0x0b, 0x63, 0x68, 0x61, 0x6e, 0x42, - 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x5f, - 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0c, 0x48, 0x00, 0x52, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, - 0x63, 0x6b, 0x75, 0x70, 0x42, 0x08, 0x0a, 0x06, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x22, 0x17, - 0x0a, 0x15, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x0a, 0x19, 0x43, 0x68, 0x61, 0x6e, 0x6e, - 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x1a, 0x0a, 0x18, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x68, - 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x44, 0x0a, 0x12, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, - 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x16, - 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb0, 0x01, 0x0a, 0x13, 0x42, 0x61, 0x6b, 0x65, 0x4d, - 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3b, - 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x61, 0x63, 0x61, - 0x72, 0x6f, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0b, - 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x72, - 0x6f, 0x6f, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x12, 0x3c, 0x0a, 0x1a, 0x61, - 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x70, 0x65, - 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x18, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x50, 0x65, - 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x32, 0x0a, 0x14, 0x42, 0x61, 0x6b, - 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x22, 0x18, 0x0a, - 0x16, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3b, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x4d, - 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0c, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x69, - 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x04, 0x52, 0x0a, 0x72, 0x6f, 0x6f, 0x74, 0x4b, 0x65, - 0x79, 0x49, 0x64, 0x73, 0x22, 0x39, 0x0a, 0x17, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, - 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x1e, 0x0a, 0x0b, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x22, - 0x34, 0x0a, 0x18, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, - 0x6e, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x64, 0x22, 0x55, 0x0a, 0x16, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, - 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x12, - 0x3b, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x61, 0x63, - 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, - 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x18, 0x0a, 0x16, - 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xe4, 0x01, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x50, - 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x64, 0x0a, 0x12, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x70, 0x65, 0x72, - 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, 0x69, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x50, 0x65, 0x72, - 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x63, 0x0a, 0x16, 0x4d, 0x65, 0x74, 0x68, - 0x6f, 0x64, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x12, 0x33, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x61, 0x63, 0x61, - 0x72, 0x6f, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x69, - 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xcc, 0x08, - 0x0a, 0x07, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x12, 0x2e, 0x0a, 0x04, 0x63, 0x6f, 0x64, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x43, - 0x6f, 0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x3b, 0x0a, 0x0e, 0x63, 0x68, 0x61, - 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x14, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, - 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x68, 0x74, 0x6c, 0x63, 0x5f, 0x6d, - 0x73, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x68, 0x74, 0x6c, 0x63, 0x4d, - 0x73, 0x61, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x6e, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x68, 0x61, - 0x5f, 0x32, 0x35, 0x36, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x6f, 0x6e, 0x69, 0x6f, - 0x6e, 0x53, 0x68, 0x61, 0x32, 0x35, 0x36, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x74, 0x76, 0x5f, - 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x63, 0x6c, - 0x74, 0x76, 0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, - 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x30, - 0x0a, 0x14, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x66, 0x61, - 0x69, 0x6c, 0x75, 0x72, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x8b, 0x06, 0x0a, 0x0b, 0x46, 0x61, 0x69, - 0x6c, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x53, 0x45, - 0x52, 0x56, 0x45, 0x44, 0x10, 0x00, 0x12, 0x28, 0x0a, 0x24, 0x49, 0x4e, 0x43, 0x4f, 0x52, 0x52, - 0x45, 0x43, 0x54, 0x5f, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x50, - 0x41, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x44, 0x45, 0x54, 0x41, 0x49, 0x4c, 0x53, 0x10, 0x01, - 0x12, 0x1c, 0x0a, 0x18, 0x49, 0x4e, 0x43, 0x4f, 0x52, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x50, 0x41, - 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x41, 0x4d, 0x4f, 0x55, 0x4e, 0x54, 0x10, 0x02, 0x12, 0x1f, - 0x0a, 0x1b, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x5f, 0x49, 0x4e, 0x43, 0x4f, 0x52, 0x52, 0x45, 0x43, - 0x54, 0x5f, 0x43, 0x4c, 0x54, 0x56, 0x5f, 0x45, 0x58, 0x50, 0x49, 0x52, 0x59, 0x10, 0x03, 0x12, - 0x1f, 0x0a, 0x1b, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x5f, 0x49, 0x4e, 0x43, 0x4f, 0x52, 0x52, 0x45, - 0x43, 0x54, 0x5f, 0x48, 0x54, 0x4c, 0x43, 0x5f, 0x41, 0x4d, 0x4f, 0x55, 0x4e, 0x54, 0x10, 0x04, - 0x12, 0x19, 0x0a, 0x15, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x5f, 0x45, 0x58, 0x50, 0x49, 0x52, 0x59, - 0x5f, 0x54, 0x4f, 0x4f, 0x5f, 0x53, 0x4f, 0x4f, 0x4e, 0x10, 0x05, 0x12, 0x11, 0x0a, 0x0d, 0x49, - 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x52, 0x45, 0x41, 0x4c, 0x4d, 0x10, 0x06, 0x12, 0x13, - 0x0a, 0x0f, 0x45, 0x58, 0x50, 0x49, 0x52, 0x59, 0x5f, 0x54, 0x4f, 0x4f, 0x5f, 0x53, 0x4f, 0x4f, - 0x4e, 0x10, 0x07, 0x12, 0x19, 0x0a, 0x15, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x4f, - 0x4e, 0x49, 0x4f, 0x4e, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x10, 0x08, 0x12, 0x16, - 0x0a, 0x12, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x4f, 0x4e, 0x49, 0x4f, 0x4e, 0x5f, - 0x48, 0x4d, 0x41, 0x43, 0x10, 0x09, 0x12, 0x15, 0x0a, 0x11, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, - 0x44, 0x5f, 0x4f, 0x4e, 0x49, 0x4f, 0x4e, 0x5f, 0x4b, 0x45, 0x59, 0x10, 0x0a, 0x12, 0x18, 0x0a, - 0x14, 0x41, 0x4d, 0x4f, 0x55, 0x4e, 0x54, 0x5f, 0x42, 0x45, 0x4c, 0x4f, 0x57, 0x5f, 0x4d, 0x49, - 0x4e, 0x49, 0x4d, 0x55, 0x4d, 0x10, 0x0b, 0x12, 0x14, 0x0a, 0x10, 0x46, 0x45, 0x45, 0x5f, 0x49, - 0x4e, 0x53, 0x55, 0x46, 0x46, 0x49, 0x43, 0x49, 0x45, 0x4e, 0x54, 0x10, 0x0c, 0x12, 0x19, 0x0a, - 0x15, 0x49, 0x4e, 0x43, 0x4f, 0x52, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x43, 0x4c, 0x54, 0x56, 0x5f, - 0x45, 0x58, 0x50, 0x49, 0x52, 0x59, 0x10, 0x0d, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x48, 0x41, 0x4e, - 0x4e, 0x45, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x0e, 0x12, 0x1d, - 0x0a, 0x19, 0x54, 0x45, 0x4d, 0x50, 0x4f, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x43, 0x48, 0x41, 0x4e, - 0x4e, 0x45, 0x4c, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, 0x0f, 0x12, 0x21, 0x0a, - 0x1d, 0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, 0x44, 0x5f, 0x4e, 0x4f, 0x44, 0x45, 0x5f, 0x46, - 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4e, 0x47, 0x10, 0x10, - 0x12, 0x24, 0x0a, 0x20, 0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, 0x44, 0x5f, 0x43, 0x48, 0x41, - 0x4e, 0x4e, 0x45, 0x4c, 0x5f, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x4d, 0x49, 0x53, - 0x53, 0x49, 0x4e, 0x47, 0x10, 0x11, 0x12, 0x15, 0x0a, 0x11, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, - 0x4e, 0x5f, 0x4e, 0x45, 0x58, 0x54, 0x5f, 0x50, 0x45, 0x45, 0x52, 0x10, 0x12, 0x12, 0x1a, 0x0a, - 0x16, 0x54, 0x45, 0x4d, 0x50, 0x4f, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x4e, 0x4f, 0x44, 0x45, 0x5f, - 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, 0x13, 0x12, 0x1a, 0x0a, 0x16, 0x50, 0x45, 0x52, - 0x4d, 0x41, 0x4e, 0x45, 0x4e, 0x54, 0x5f, 0x4e, 0x4f, 0x44, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, - 0x55, 0x52, 0x45, 0x10, 0x14, 0x12, 0x1d, 0x0a, 0x19, 0x50, 0x45, 0x52, 0x4d, 0x41, 0x4e, 0x45, - 0x4e, 0x54, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, - 0x52, 0x45, 0x10, 0x15, 0x12, 0x12, 0x0a, 0x0e, 0x45, 0x58, 0x50, 0x49, 0x52, 0x59, 0x5f, 0x54, - 0x4f, 0x4f, 0x5f, 0x46, 0x41, 0x52, 0x10, 0x16, 0x12, 0x0f, 0x0a, 0x0b, 0x4d, 0x50, 0x50, 0x5f, - 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, 0x17, 0x12, 0x19, 0x0a, 0x15, 0x49, 0x4e, 0x56, - 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x4f, 0x4e, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x41, 0x59, 0x4c, 0x4f, - 0x41, 0x44, 0x10, 0x18, 0x12, 0x1a, 0x0a, 0x16, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, - 0x4f, 0x4e, 0x49, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x49, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x19, - 0x12, 0x15, 0x0a, 0x10, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x46, 0x41, 0x49, - 0x4c, 0x55, 0x52, 0x45, 0x10, 0xe5, 0x07, 0x12, 0x14, 0x0a, 0x0f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, - 0x57, 0x4e, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, 0xe6, 0x07, 0x12, 0x17, 0x0a, - 0x12, 0x55, 0x4e, 0x52, 0x45, 0x41, 0x44, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, - 0x55, 0x52, 0x45, 0x10, 0xe7, 0x07, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0xb3, 0x03, 0x0a, - 0x0d, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x1c, - 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1d, 0x0a, 0x0a, - 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x09, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1b, 0x0a, 0x07, 0x63, - 0x68, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x30, 0x01, - 0x52, 0x06, 0x63, 0x68, 0x61, 0x6e, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x74, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x63, - 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, - 0x12, 0x26, 0x0a, 0x0f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x64, 0x65, - 0x6c, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x74, 0x69, 0x6d, 0x65, 0x4c, - 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x2a, 0x0a, 0x11, 0x68, 0x74, 0x6c, 0x63, - 0x5f, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x0f, 0x68, 0x74, 0x6c, 0x63, 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, - 0x4d, 0x73, 0x61, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x66, 0x65, 0x65, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x62, 0x61, 0x73, 0x65, 0x46, 0x65, 0x65, 0x12, - 0x19, 0x0a, 0x08, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, - 0x0d, 0x52, 0x07, 0x66, 0x65, 0x65, 0x52, 0x61, 0x74, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x68, 0x74, - 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, - 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x68, 0x74, 0x6c, 0x63, 0x4d, 0x61, 0x78, 0x69, 0x6d, - 0x75, 0x6d, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, - 0x6f, 0x70, 0x61, 0x71, 0x75, 0x65, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0c, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x0f, 0x65, 0x78, 0x74, 0x72, 0x61, 0x4f, 0x70, 0x61, 0x71, 0x75, 0x65, 0x44, 0x61, - 0x74, 0x61, 0x22, 0x5d, 0x0a, 0x0a, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x64, - 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, - 0x65, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x74, 0x6f, 0x72, 0x61, - 0x67, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x03, 0x6f, 0x70, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x09, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x70, 0x52, 0x03, 0x6f, 0x70, - 0x73, 0x22, 0x36, 0x0a, 0x02, 0x4f, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, - 0x18, 0x0a, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x8e, 0x01, 0x0a, 0x13, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x12, 0x3b, 0x0a, - 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x61, 0x63, 0x61, 0x72, - 0x6f, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x70, - 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x66, 0x75, - 0x6c, 0x6c, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x66, 0x75, 0x6c, 0x6c, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x22, 0x2c, 0x0a, 0x14, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x22, 0xf4, 0x02, 0x0a, 0x14, 0x52, 0x50, 0x43, - 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, - 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x61, 0x77, 0x5f, 0x6d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x72, 0x61, 0x77, 0x4d, 0x61, 0x63, 0x61, 0x72, - 0x6f, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x17, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x63, 0x61, - 0x76, 0x65, 0x61, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x43, 0x61, 0x76, 0x65, - 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, 0x0b, 0x73, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x11, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x41, - 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x0a, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x41, 0x75, 0x74, - 0x68, 0x12, 0x2d, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x50, 0x43, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x2f, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x50, 0x43, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x72, 0x65, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, - 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0b, 0x72, 0x65, 0x67, 0x43, 0x6f, - 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x6d, 0x73, 0x67, 0x5f, 0x69, 0x64, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x42, 0x10, 0x0a, - 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, - 0x34, 0x0a, 0x0a, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x41, 0x75, 0x74, 0x68, 0x12, 0x26, 0x0a, - 0x0f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x75, 0x72, 0x69, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x46, 0x75, - 0x6c, 0x6c, 0x55, 0x72, 0x69, 0x22, 0xab, 0x01, 0x0a, 0x0a, 0x52, 0x50, 0x43, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x66, - 0x75, 0x6c, 0x6c, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x46, 0x75, 0x6c, 0x6c, 0x55, 0x72, 0x69, 0x12, 0x1d, 0x0a, 0x0a, - 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x72, 0x70, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x09, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x70, 0x63, 0x12, 0x1b, 0x0a, 0x09, 0x74, - 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x69, - 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x73, 0x65, - 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x45, 0x72, - 0x72, 0x6f, 0x72, 0x22, 0xc0, 0x01, 0x0a, 0x15, 0x52, 0x50, 0x43, 0x4d, 0x69, 0x64, 0x64, 0x6c, - 0x65, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, - 0x0a, 0x72, 0x65, 0x66, 0x5f, 0x6d, 0x73, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x08, 0x72, 0x65, 0x66, 0x4d, 0x73, 0x67, 0x49, 0x64, 0x12, 0x3b, 0x0a, 0x08, 0x72, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, - 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x08, - 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x36, 0x0a, 0x08, 0x66, 0x65, 0x65, 0x64, - 0x62, 0x61, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x46, 0x65, 0x65, 0x64, - 0x62, 0x61, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x08, 0x66, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, - 0x42, 0x14, 0x0a, 0x12, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x5f, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xa6, 0x01, 0x0a, 0x16, 0x4d, 0x69, 0x64, 0x64, 0x6c, - 0x65, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6d, 0x69, 0x64, 0x64, - 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3d, 0x0a, 0x1b, 0x63, 0x75, - 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x5f, 0x63, 0x61, - 0x76, 0x65, 0x61, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x18, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x43, - 0x61, 0x76, 0x65, 0x61, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x65, 0x61, - 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x0c, 0x72, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x22, - 0x8b, 0x01, 0x0a, 0x11, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x46, 0x65, 0x65, - 0x64, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x29, 0x0a, 0x10, 0x72, - 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x16, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x15, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, - 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x2a, 0xcb, 0x02, - 0x0a, 0x10, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, - 0x45, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, 0x59, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x00, 0x12, - 0x1b, 0x0a, 0x17, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, - 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x01, 0x12, 0x26, 0x0a, 0x22, - 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x57, 0x49, 0x54, 0x4e, - 0x45, 0x53, 0x53, 0x5f, 0x56, 0x30, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, 0x59, 0x5f, 0x48, 0x41, - 0x53, 0x48, 0x10, 0x02, 0x12, 0x26, 0x0a, 0x22, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x57, 0x49, 0x54, 0x4e, 0x45, 0x53, 0x53, 0x5f, 0x56, 0x30, 0x5f, 0x53, - 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, - 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x55, 0x42, 0x4b, - 0x45, 0x59, 0x10, 0x04, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x53, 0x49, 0x47, 0x10, 0x05, 0x12, 0x18, - 0x0a, 0x14, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e, 0x55, - 0x4c, 0x4c, 0x44, 0x41, 0x54, 0x41, 0x10, 0x06, 0x12, 0x1c, 0x0a, 0x18, 0x53, 0x43, 0x52, 0x49, - 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x4e, - 0x44, 0x41, 0x52, 0x44, 0x10, 0x07, 0x12, 0x1f, 0x0a, 0x1b, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x57, 0x49, 0x54, 0x4e, 0x45, 0x53, 0x53, 0x5f, 0x55, 0x4e, - 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x08, 0x12, 0x22, 0x0a, 0x1e, 0x53, 0x43, 0x52, 0x49, 0x50, - 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x57, 0x49, 0x54, 0x4e, 0x45, 0x53, 0x53, 0x5f, 0x56, - 0x31, 0x5f, 0x54, 0x41, 0x50, 0x52, 0x4f, 0x4f, 0x54, 0x10, 0x09, 0x2a, 0x62, 0x0a, 0x15, 0x43, - 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, - 0x74, 0x65, 0x67, 0x79, 0x12, 0x1e, 0x0a, 0x1a, 0x53, 0x54, 0x52, 0x41, 0x54, 0x45, 0x47, 0x59, - 0x5f, 0x55, 0x53, 0x45, 0x5f, 0x47, 0x4c, 0x4f, 0x42, 0x41, 0x4c, 0x5f, 0x43, 0x4f, 0x4e, 0x46, - 0x49, 0x47, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x54, 0x52, 0x41, 0x54, 0x45, 0x47, 0x59, - 0x5f, 0x4c, 0x41, 0x52, 0x47, 0x45, 0x53, 0x54, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x54, - 0x52, 0x41, 0x54, 0x45, 0x47, 0x59, 0x5f, 0x52, 0x41, 0x4e, 0x44, 0x4f, 0x4d, 0x10, 0x02, 0x2a, - 0xac, 0x01, 0x0a, 0x0b, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x17, 0x0a, 0x13, 0x57, 0x49, 0x54, 0x4e, 0x45, 0x53, 0x53, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, - 0x59, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x4e, 0x45, 0x53, 0x54, - 0x45, 0x44, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, 0x59, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x01, - 0x12, 0x1e, 0x0a, 0x1a, 0x55, 0x4e, 0x55, 0x53, 0x45, 0x44, 0x5f, 0x57, 0x49, 0x54, 0x4e, 0x45, - 0x53, 0x53, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, 0x59, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x02, - 0x12, 0x1d, 0x0a, 0x19, 0x55, 0x4e, 0x55, 0x53, 0x45, 0x44, 0x5f, 0x4e, 0x45, 0x53, 0x54, 0x45, - 0x44, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, 0x59, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x03, 0x12, - 0x12, 0x0a, 0x0e, 0x54, 0x41, 0x50, 0x52, 0x4f, 0x4f, 0x54, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, - 0x59, 0x10, 0x04, 0x12, 0x19, 0x0a, 0x15, 0x55, 0x4e, 0x55, 0x53, 0x45, 0x44, 0x5f, 0x54, 0x41, - 0x50, 0x52, 0x4f, 0x4f, 0x54, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, 0x59, 0x10, 0x05, 0x2a, 0x8c, - 0x01, 0x0a, 0x0e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x43, 0x4f, 0x4d, - 0x4d, 0x49, 0x54, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x10, 0x00, 0x12, 0x0a, - 0x0a, 0x06, 0x4c, 0x45, 0x47, 0x41, 0x43, 0x59, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x54, - 0x41, 0x54, 0x49, 0x43, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x5f, 0x4b, 0x45, 0x59, 0x10, - 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x4e, 0x43, 0x48, 0x4f, 0x52, 0x53, 0x10, 0x03, 0x12, 0x19, - 0x0a, 0x15, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x45, 0x4e, 0x46, 0x4f, 0x52, 0x43, 0x45, - 0x44, 0x5f, 0x4c, 0x45, 0x41, 0x53, 0x45, 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x49, 0x4d, - 0x50, 0x4c, 0x45, 0x5f, 0x54, 0x41, 0x50, 0x52, 0x4f, 0x4f, 0x54, 0x10, 0x05, 0x2a, 0x61, 0x0a, - 0x09, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x15, 0x0a, 0x11, 0x49, 0x4e, - 0x49, 0x54, 0x49, 0x41, 0x54, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, - 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x54, 0x4f, 0x52, 0x5f, 0x4c, - 0x4f, 0x43, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, - 0x54, 0x4f, 0x52, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, - 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x54, 0x4f, 0x52, 0x5f, 0x42, 0x4f, 0x54, 0x48, 0x10, 0x03, - 0x2a, 0x60, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, - 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x4e, 0x43, 0x48, 0x4f, 0x52, 0x10, 0x01, - 0x12, 0x11, 0x0a, 0x0d, 0x49, 0x4e, 0x43, 0x4f, 0x4d, 0x49, 0x4e, 0x47, 0x5f, 0x48, 0x54, 0x4c, - 0x43, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x4f, 0x55, 0x54, 0x47, 0x4f, 0x49, 0x4e, 0x47, 0x5f, - 0x48, 0x54, 0x4c, 0x43, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, - 0x10, 0x04, 0x2a, 0x71, 0x0a, 0x11, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, - 0x4f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x12, 0x13, 0x0a, 0x0f, 0x4f, 0x55, 0x54, 0x43, 0x4f, - 0x4d, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, - 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x43, - 0x4c, 0x41, 0x49, 0x4d, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x41, 0x42, 0x41, 0x4e, - 0x44, 0x4f, 0x4e, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x46, 0x49, 0x52, 0x53, 0x54, - 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x10, 0x04, 0x12, 0x0b, 0x0a, 0x07, 0x54, 0x49, 0x4d, 0x45, - 0x4f, 0x55, 0x54, 0x10, 0x05, 0x2a, 0x39, 0x0a, 0x0e, 0x4e, 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, - 0x72, 0x69, 0x63, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, - 0x57, 0x4e, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x42, 0x45, 0x54, 0x57, 0x45, 0x45, 0x4e, 0x4e, - 0x45, 0x53, 0x53, 0x5f, 0x43, 0x45, 0x4e, 0x54, 0x52, 0x41, 0x4c, 0x49, 0x54, 0x59, 0x10, 0x01, - 0x2a, 0x3b, 0x0a, 0x10, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x48, 0x54, 0x4c, 0x43, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x45, 0x44, - 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x45, 0x54, 0x54, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, - 0x0c, 0x0a, 0x08, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x45, 0x44, 0x10, 0x02, 0x2a, 0xd9, 0x01, - 0x0a, 0x14, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, - 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x13, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, - 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, - 0x1a, 0x0a, 0x16, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, - 0x4e, 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x46, - 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f, - 0x5f, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, 0x46, 0x41, 0x49, 0x4c, - 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, - 0x10, 0x03, 0x12, 0x2c, 0x0a, 0x28, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, - 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x49, 0x4e, 0x43, 0x4f, 0x52, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x50, - 0x41, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x44, 0x45, 0x54, 0x41, 0x49, 0x4c, 0x53, 0x10, 0x04, - 0x12, 0x27, 0x0a, 0x23, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, - 0x4f, 0x4e, 0x5f, 0x49, 0x4e, 0x53, 0x55, 0x46, 0x46, 0x49, 0x43, 0x49, 0x45, 0x4e, 0x54, 0x5f, - 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x05, 0x2a, 0x89, 0x05, 0x0a, 0x0a, 0x46, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x42, 0x69, 0x74, 0x12, 0x18, 0x0a, 0x14, 0x44, 0x41, 0x54, 0x41, - 0x4c, 0x4f, 0x53, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x45, 0x43, 0x54, 0x5f, 0x52, 0x45, 0x51, - 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x44, 0x41, 0x54, 0x41, 0x4c, 0x4f, 0x53, 0x53, 0x5f, 0x50, - 0x52, 0x4f, 0x54, 0x45, 0x43, 0x54, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, - 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x4c, 0x5f, 0x52, 0x4f, 0x55, 0x49, 0x4e, 0x47, 0x5f, 0x53, - 0x59, 0x4e, 0x43, 0x10, 0x03, 0x12, 0x1f, 0x0a, 0x1b, 0x55, 0x50, 0x46, 0x52, 0x4f, 0x4e, 0x54, - 0x5f, 0x53, 0x48, 0x55, 0x54, 0x44, 0x4f, 0x57, 0x4e, 0x5f, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, - 0x5f, 0x52, 0x45, 0x51, 0x10, 0x04, 0x12, 0x1f, 0x0a, 0x1b, 0x55, 0x50, 0x46, 0x52, 0x4f, 0x4e, - 0x54, 0x5f, 0x53, 0x48, 0x55, 0x54, 0x44, 0x4f, 0x57, 0x4e, 0x5f, 0x53, 0x43, 0x52, 0x49, 0x50, - 0x54, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x05, 0x12, 0x16, 0x0a, 0x12, 0x47, 0x4f, 0x53, 0x53, 0x49, - 0x50, 0x5f, 0x51, 0x55, 0x45, 0x52, 0x49, 0x45, 0x53, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x06, 0x12, - 0x16, 0x0a, 0x12, 0x47, 0x4f, 0x53, 0x53, 0x49, 0x50, 0x5f, 0x51, 0x55, 0x45, 0x52, 0x49, 0x45, - 0x53, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x07, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x4c, 0x56, 0x5f, 0x4f, - 0x4e, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x08, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x4c, - 0x56, 0x5f, 0x4f, 0x4e, 0x49, 0x4f, 0x4e, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x09, 0x12, 0x1a, 0x0a, - 0x16, 0x45, 0x58, 0x54, 0x5f, 0x47, 0x4f, 0x53, 0x53, 0x49, 0x50, 0x5f, 0x51, 0x55, 0x45, 0x52, - 0x49, 0x45, 0x53, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x0a, 0x12, 0x1a, 0x0a, 0x16, 0x45, 0x58, 0x54, - 0x5f, 0x47, 0x4f, 0x53, 0x53, 0x49, 0x50, 0x5f, 0x51, 0x55, 0x45, 0x52, 0x49, 0x45, 0x53, 0x5f, - 0x4f, 0x50, 0x54, 0x10, 0x0b, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x54, 0x41, 0x54, 0x49, 0x43, 0x5f, - 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x0c, - 0x12, 0x19, 0x0a, 0x15, 0x53, 0x54, 0x41, 0x54, 0x49, 0x43, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x54, - 0x45, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x0d, 0x12, 0x14, 0x0a, 0x10, 0x50, - 0x41, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x52, 0x45, 0x51, 0x10, - 0x0e, 0x12, 0x14, 0x0a, 0x10, 0x50, 0x41, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x41, 0x44, 0x44, - 0x52, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x0f, 0x12, 0x0b, 0x0a, 0x07, 0x4d, 0x50, 0x50, 0x5f, 0x52, - 0x45, 0x51, 0x10, 0x10, 0x12, 0x0b, 0x0a, 0x07, 0x4d, 0x50, 0x50, 0x5f, 0x4f, 0x50, 0x54, 0x10, - 0x11, 0x12, 0x16, 0x0a, 0x12, 0x57, 0x55, 0x4d, 0x42, 0x4f, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x4e, - 0x45, 0x4c, 0x53, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x12, 0x12, 0x16, 0x0a, 0x12, 0x57, 0x55, 0x4d, - 0x42, 0x4f, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x53, 0x5f, 0x4f, 0x50, 0x54, 0x10, - 0x13, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x4e, 0x43, 0x48, 0x4f, 0x52, 0x53, 0x5f, 0x52, 0x45, 0x51, - 0x10, 0x14, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x4e, 0x43, 0x48, 0x4f, 0x52, 0x53, 0x5f, 0x4f, 0x50, - 0x54, 0x10, 0x15, 0x12, 0x1d, 0x0a, 0x19, 0x41, 0x4e, 0x43, 0x48, 0x4f, 0x52, 0x53, 0x5f, 0x5a, - 0x45, 0x52, 0x4f, 0x5f, 0x46, 0x45, 0x45, 0x5f, 0x48, 0x54, 0x4c, 0x43, 0x5f, 0x52, 0x45, 0x51, - 0x10, 0x16, 0x12, 0x1d, 0x0a, 0x19, 0x41, 0x4e, 0x43, 0x48, 0x4f, 0x52, 0x53, 0x5f, 0x5a, 0x45, - 0x52, 0x4f, 0x5f, 0x46, 0x45, 0x45, 0x5f, 0x48, 0x54, 0x4c, 0x43, 0x5f, 0x4f, 0x50, 0x54, 0x10, - 0x17, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x42, 0x4c, 0x49, 0x4e, 0x44, - 0x49, 0x4e, 0x47, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, 0x44, 0x10, 0x18, 0x12, 0x1b, - 0x0a, 0x17, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x42, 0x4c, 0x49, 0x4e, 0x44, 0x49, 0x4e, 0x47, - 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x10, 0x19, 0x12, 0x0b, 0x0a, 0x07, 0x41, - 0x4d, 0x50, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x1e, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x4d, 0x50, 0x5f, - 0x4f, 0x50, 0x54, 0x10, 0x1f, 0x2a, 0xac, 0x01, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x55, 0x50, 0x44, 0x41, 0x54, - 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, - 0x4e, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, - 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, - 0x1c, 0x0a, 0x18, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, - 0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x02, 0x12, 0x1f, 0x0a, - 0x1b, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, - 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x45, 0x52, 0x52, 0x10, 0x03, 0x12, 0x24, - 0x0a, 0x20, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, - 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x50, 0x41, 0x52, 0x41, 0x4d, 0x45, 0x54, - 0x45, 0x52, 0x10, 0x04, 0x32, 0xb9, 0x27, 0x0a, 0x09, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, - 0x6e, 0x67, 0x12, 0x4a, 0x0a, 0x0d, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, - 0x6e, 0x63, 0x65, 0x12, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x61, 0x6c, 0x6c, - 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x42, - 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, - 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, - 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, - 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, + 0x6f, 0x69, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x50, 0x6f, 0x69, 0x6e, + 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x6d, 0x73, + 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x62, 0x61, 0x73, 0x65, 0x46, 0x65, + 0x65, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x61, 0x74, + 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x07, 0x66, 0x65, 0x65, 0x52, 0x61, 0x74, 0x65, + 0x12, 0x20, 0x0a, 0x0c, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x70, 0x6d, + 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x66, 0x65, 0x65, 0x52, 0x61, 0x74, 0x65, 0x50, + 0x70, 0x6d, 0x12, 0x26, 0x0a, 0x0f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, + 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x74, 0x69, 0x6d, + 0x65, 0x4c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x61, + 0x78, 0x5f, 0x68, 0x74, 0x6c, 0x63, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x48, 0x74, 0x6c, 0x63, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x22, + 0x0a, 0x0d, 0x6d, 0x69, 0x6e, 0x5f, 0x68, 0x74, 0x6c, 0x63, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x69, 0x6e, 0x48, 0x74, 0x6c, 0x63, 0x4d, 0x73, + 0x61, 0x74, 0x12, 0x35, 0x0a, 0x17, 0x6d, 0x69, 0x6e, 0x5f, 0x68, 0x74, 0x6c, 0x63, 0x5f, 0x6d, + 0x73, 0x61, 0x74, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x14, 0x6d, 0x69, 0x6e, 0x48, 0x74, 0x6c, 0x63, 0x4d, 0x73, 0x61, 0x74, + 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x32, 0x0a, 0x0b, 0x69, 0x6e, 0x62, + 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x66, 0x65, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x65, + 0x65, 0x52, 0x0a, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x46, 0x65, 0x65, 0x42, 0x07, 0x0a, + 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x22, 0x8c, 0x01, 0x0a, 0x0c, 0x46, 0x61, 0x69, 0x6c, 0x65, + 0x64, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x2b, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, + 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, + 0x63, 0x2e, 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, + 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x52, 0x0a, 0x14, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, + 0x0e, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x61, + 0x69, 0x6c, 0x65, 0x64, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x66, 0x61, 0x69, 0x6c, + 0x65, 0x64, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x22, 0xc9, 0x01, 0x0a, 0x18, 0x46, 0x6f, + 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, + 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x4f, 0x66, 0x66, + 0x73, 0x65, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x6e, 0x75, 0x6d, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6e, 0x75, 0x6d, + 0x4d, 0x61, 0x78, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x70, 0x65, 0x65, + 0x72, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x5f, 0x6c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x70, 0x65, 0x65, 0x72, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4c, + 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x22, 0x85, 0x03, 0x0a, 0x0f, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, + 0x64, 0x69, 0x6e, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x20, 0x0a, 0x09, 0x74, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x18, 0x01, + 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x20, 0x0a, 0x0a, 0x63, + 0x68, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x5f, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, + 0x02, 0x30, 0x01, 0x52, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x49, 0x64, 0x49, 0x6e, 0x12, 0x22, 0x0a, + 0x0b, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x5f, 0x6f, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x04, 0x42, 0x02, 0x30, 0x01, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x49, 0x64, 0x4f, 0x75, + 0x74, 0x12, 0x15, 0x0a, 0x06, 0x61, 0x6d, 0x74, 0x5f, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x05, 0x61, 0x6d, 0x74, 0x49, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x61, 0x6d, 0x74, 0x5f, + 0x6f, 0x75, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x74, 0x4f, 0x75, + 0x74, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x65, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, + 0x66, 0x65, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x65, 0x65, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x66, 0x65, 0x65, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x1e, + 0x0a, 0x0b, 0x61, 0x6d, 0x74, 0x5f, 0x69, 0x6e, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x09, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x09, 0x61, 0x6d, 0x74, 0x49, 0x6e, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x20, + 0x0a, 0x0c, 0x61, 0x6d, 0x74, 0x5f, 0x6f, 0x75, 0x74, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x61, 0x6d, 0x74, 0x4f, 0x75, 0x74, 0x4d, 0x73, 0x61, 0x74, + 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x6e, 0x73, + 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x4e, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x61, 0x6c, 0x69, 0x61, + 0x73, 0x5f, 0x69, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x65, 0x65, 0x72, + 0x41, 0x6c, 0x69, 0x61, 0x73, 0x49, 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x65, 0x65, 0x72, 0x5f, + 0x61, 0x6c, 0x69, 0x61, 0x73, 0x5f, 0x6f, 0x75, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0c, 0x70, 0x65, 0x65, 0x72, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4f, 0x75, 0x74, 0x22, 0x8c, 0x01, + 0x0a, 0x19, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, + 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x11, 0x66, + 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, + 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x10, + 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, + 0x12, 0x2a, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x5f, + 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x6c, 0x61, 0x73, + 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x50, 0x0a, 0x1a, + 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, + 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x32, 0x0a, 0x0a, 0x63, 0x68, + 0x61, 0x6e, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, + 0x69, 0x6e, 0x74, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x22, 0x64, + 0x0a, 0x0d, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, + 0x32, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, + 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x50, 0x6f, + 0x69, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, + 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x42, 0x61, + 0x63, 0x6b, 0x75, 0x70, 0x22, 0x73, 0x0a, 0x0f, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x43, 0x68, 0x61, + 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x34, 0x0a, 0x0b, 0x63, 0x68, 0x61, 0x6e, 0x5f, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6c, + 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x69, 0x6e, + 0x74, 0x52, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x2a, 0x0a, + 0x11, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, + 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x43, + 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x22, 0x19, 0x0a, 0x17, 0x43, 0x68, 0x61, + 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x22, 0x9f, 0x01, 0x0a, 0x12, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, + 0x6b, 0x75, 0x70, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x45, 0x0a, 0x13, 0x73, + 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, + 0x70, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, + 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x52, + 0x11, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, + 0x70, 0x73, 0x12, 0x42, 0x0a, 0x11, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x5f, 0x63, 0x68, 0x61, 0x6e, + 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x43, 0x68, 0x61, 0x6e, 0x42, + 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x43, 0x68, 0x61, 0x6e, + 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x22, 0x49, 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, + 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12, 0x37, 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x6e, + 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, - 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, - 0x0f, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x44, 0x0a, 0x0b, 0x45, 0x73, - 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x73, 0x74, - 0x69, 0x6d, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x3e, 0x0a, 0x09, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x12, 0x17, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, - 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x44, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x12, - 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, 0x73, 0x70, - 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x15, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, - 0x69, 0x62, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x30, 0x01, 0x12, 0x3b, 0x0a, 0x08, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x61, 0x6e, 0x79, - 0x12, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x61, 0x6e, - 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x61, 0x6e, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x41, 0x0a, 0x0a, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, - 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x0d, 0x56, 0x65, - 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x2e, 0x6c, 0x6e, - 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x50, 0x65, 0x65, 0x72, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, + 0x63, 0x6b, 0x75, 0x70, 0x52, 0x0b, 0x63, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, + 0x73, 0x22, 0x8e, 0x01, 0x0a, 0x18, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, + 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, + 0x0a, 0x0c, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, + 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x48, 0x00, 0x52, 0x0b, 0x63, + 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x6d, 0x75, + 0x6c, 0x74, 0x69, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x43, 0x68, + 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x42, 0x08, 0x0a, 0x06, 0x62, 0x61, 0x63, 0x6b, + 0x75, 0x70, 0x22, 0x17, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x42, 0x61, 0x63, + 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x0a, 0x19, 0x43, + 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, 0x75, 0x62, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x1a, 0x0a, 0x18, 0x56, 0x65, 0x72, 0x69, + 0x66, 0x79, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x44, 0x0a, 0x12, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, + 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x65, 0x6e, 0x74, 0x69, + 0x74, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb0, 0x01, 0x0a, 0x13, 0x42, + 0x61, 0x6b, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x3b, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x1e, 0x0a, 0x0b, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x12, + 0x3c, 0x0a, 0x1a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x18, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x32, 0x0a, + 0x14, 0x42, 0x61, 0x6b, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, + 0x6e, 0x22, 0x18, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, + 0x6e, 0x49, 0x44, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3b, 0x0a, 0x17, 0x4c, + 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0c, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x6b, + 0x65, 0x79, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x04, 0x52, 0x0a, 0x72, 0x6f, + 0x6f, 0x74, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x73, 0x22, 0x39, 0x0a, 0x17, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x0b, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x4b, 0x65, + 0x79, 0x49, 0x64, 0x22, 0x34, 0x0a, 0x18, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, + 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x18, 0x0a, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x22, 0x55, 0x0a, 0x16, 0x4d, 0x61, 0x63, + 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, + 0x69, 0x73, 0x74, 0x12, 0x3b, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, + 0x2e, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, + 0x22, 0x18, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xe4, 0x01, 0x0a, 0x17, 0x4c, + 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x64, 0x0a, 0x12, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, + 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, + 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x11, 0x6d, 0x65, 0x74, 0x68, 0x6f, + 0x64, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x63, 0x0a, 0x16, + 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x33, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 0x22, 0xcc, 0x08, 0x0a, 0x07, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x12, 0x2e, 0x0a, + 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x2e, 0x46, 0x61, 0x69, 0x6c, + 0x75, 0x72, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x3b, 0x0a, + 0x0e, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, + 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x0d, 0x63, 0x68, 0x61, + 0x6e, 0x6e, 0x65, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x68, 0x74, + 0x6c, 0x63, 0x5f, 0x6d, 0x73, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x68, + 0x74, 0x6c, 0x63, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x6e, 0x69, 0x6f, 0x6e, + 0x5f, 0x73, 0x68, 0x61, 0x5f, 0x32, 0x35, 0x36, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, + 0x6f, 0x6e, 0x69, 0x6f, 0x6e, 0x53, 0x68, 0x61, 0x32, 0x35, 0x36, 0x12, 0x1f, 0x0a, 0x0b, 0x63, + 0x6c, 0x74, 0x76, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x0a, 0x63, 0x6c, 0x74, 0x76, 0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x66, 0x6c, 0x61, + 0x67, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x12, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, + 0x6e, 0x64, 0x65, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x8b, 0x06, 0x0a, + 0x0b, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x0c, 0x0a, 0x08, + 0x52, 0x45, 0x53, 0x45, 0x52, 0x56, 0x45, 0x44, 0x10, 0x00, 0x12, 0x28, 0x0a, 0x24, 0x49, 0x4e, + 0x43, 0x4f, 0x52, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, + 0x57, 0x4e, 0x5f, 0x50, 0x41, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x44, 0x45, 0x54, 0x41, 0x49, + 0x4c, 0x53, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x49, 0x4e, 0x43, 0x4f, 0x52, 0x52, 0x45, 0x43, + 0x54, 0x5f, 0x50, 0x41, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x41, 0x4d, 0x4f, 0x55, 0x4e, 0x54, + 0x10, 0x02, 0x12, 0x1f, 0x0a, 0x1b, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x5f, 0x49, 0x4e, 0x43, 0x4f, + 0x52, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x43, 0x4c, 0x54, 0x56, 0x5f, 0x45, 0x58, 0x50, 0x49, 0x52, + 0x59, 0x10, 0x03, 0x12, 0x1f, 0x0a, 0x1b, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x5f, 0x49, 0x4e, 0x43, + 0x4f, 0x52, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x48, 0x54, 0x4c, 0x43, 0x5f, 0x41, 0x4d, 0x4f, 0x55, + 0x4e, 0x54, 0x10, 0x04, 0x12, 0x19, 0x0a, 0x15, 0x46, 0x49, 0x4e, 0x41, 0x4c, 0x5f, 0x45, 0x58, + 0x50, 0x49, 0x52, 0x59, 0x5f, 0x54, 0x4f, 0x4f, 0x5f, 0x53, 0x4f, 0x4f, 0x4e, 0x10, 0x05, 0x12, + 0x11, 0x0a, 0x0d, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x52, 0x45, 0x41, 0x4c, 0x4d, + 0x10, 0x06, 0x12, 0x13, 0x0a, 0x0f, 0x45, 0x58, 0x50, 0x49, 0x52, 0x59, 0x5f, 0x54, 0x4f, 0x4f, + 0x5f, 0x53, 0x4f, 0x4f, 0x4e, 0x10, 0x07, 0x12, 0x19, 0x0a, 0x15, 0x49, 0x4e, 0x56, 0x41, 0x4c, + 0x49, 0x44, 0x5f, 0x4f, 0x4e, 0x49, 0x4f, 0x4e, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, + 0x10, 0x08, 0x12, 0x16, 0x0a, 0x12, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x4f, 0x4e, + 0x49, 0x4f, 0x4e, 0x5f, 0x48, 0x4d, 0x41, 0x43, 0x10, 0x09, 0x12, 0x15, 0x0a, 0x11, 0x49, 0x4e, + 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x4f, 0x4e, 0x49, 0x4f, 0x4e, 0x5f, 0x4b, 0x45, 0x59, 0x10, + 0x0a, 0x12, 0x18, 0x0a, 0x14, 0x41, 0x4d, 0x4f, 0x55, 0x4e, 0x54, 0x5f, 0x42, 0x45, 0x4c, 0x4f, + 0x57, 0x5f, 0x4d, 0x49, 0x4e, 0x49, 0x4d, 0x55, 0x4d, 0x10, 0x0b, 0x12, 0x14, 0x0a, 0x10, 0x46, + 0x45, 0x45, 0x5f, 0x49, 0x4e, 0x53, 0x55, 0x46, 0x46, 0x49, 0x43, 0x49, 0x45, 0x4e, 0x54, 0x10, + 0x0c, 0x12, 0x19, 0x0a, 0x15, 0x49, 0x4e, 0x43, 0x4f, 0x52, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x43, + 0x4c, 0x54, 0x56, 0x5f, 0x45, 0x58, 0x50, 0x49, 0x52, 0x59, 0x10, 0x0d, 0x12, 0x14, 0x0a, 0x10, + 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x5f, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, + 0x10, 0x0e, 0x12, 0x1d, 0x0a, 0x19, 0x54, 0x45, 0x4d, 0x50, 0x4f, 0x52, 0x41, 0x52, 0x59, 0x5f, + 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, + 0x0f, 0x12, 0x21, 0x0a, 0x1d, 0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, 0x44, 0x5f, 0x4e, 0x4f, + 0x44, 0x45, 0x5f, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x4d, 0x49, 0x53, 0x53, 0x49, + 0x4e, 0x47, 0x10, 0x10, 0x12, 0x24, 0x0a, 0x20, 0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, 0x44, + 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x5f, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, + 0x5f, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4e, 0x47, 0x10, 0x11, 0x12, 0x15, 0x0a, 0x11, 0x55, 0x4e, + 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x4e, 0x45, 0x58, 0x54, 0x5f, 0x50, 0x45, 0x45, 0x52, 0x10, + 0x12, 0x12, 0x1a, 0x0a, 0x16, 0x54, 0x45, 0x4d, 0x50, 0x4f, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x4e, + 0x4f, 0x44, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, 0x13, 0x12, 0x1a, 0x0a, + 0x16, 0x50, 0x45, 0x52, 0x4d, 0x41, 0x4e, 0x45, 0x4e, 0x54, 0x5f, 0x4e, 0x4f, 0x44, 0x45, 0x5f, + 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, 0x14, 0x12, 0x1d, 0x0a, 0x19, 0x50, 0x45, 0x52, + 0x4d, 0x41, 0x4e, 0x45, 0x4e, 0x54, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x5f, 0x46, + 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, 0x15, 0x12, 0x12, 0x0a, 0x0e, 0x45, 0x58, 0x50, 0x49, + 0x52, 0x59, 0x5f, 0x54, 0x4f, 0x4f, 0x5f, 0x46, 0x41, 0x52, 0x10, 0x16, 0x12, 0x0f, 0x0a, 0x0b, + 0x4d, 0x50, 0x50, 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, 0x17, 0x12, 0x19, 0x0a, + 0x15, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x4f, 0x4e, 0x49, 0x4f, 0x4e, 0x5f, 0x50, + 0x41, 0x59, 0x4c, 0x4f, 0x41, 0x44, 0x10, 0x18, 0x12, 0x1a, 0x0a, 0x16, 0x49, 0x4e, 0x56, 0x41, + 0x4c, 0x49, 0x44, 0x5f, 0x4f, 0x4e, 0x49, 0x4f, 0x4e, 0x5f, 0x42, 0x4c, 0x49, 0x4e, 0x44, 0x49, + 0x4e, 0x47, 0x10, 0x19, 0x12, 0x15, 0x0a, 0x10, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, + 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, 0xe5, 0x07, 0x12, 0x14, 0x0a, 0x0f, 0x55, + 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, 0xe6, + 0x07, 0x12, 0x17, 0x0a, 0x12, 0x55, 0x4e, 0x52, 0x45, 0x41, 0x44, 0x41, 0x42, 0x4c, 0x45, 0x5f, + 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, 0xe7, 0x07, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, + 0x22, 0xb3, 0x03, 0x0a, 0x0d, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x48, 0x61, 0x73, 0x68, 0x12, + 0x1b, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, + 0x42, 0x02, 0x30, 0x01, 0x52, 0x06, 0x63, 0x68, 0x61, 0x6e, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, + 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x12, + 0x23, 0x0a, 0x0d, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x46, + 0x6c, 0x61, 0x67, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6c, 0x6f, 0x63, + 0x6b, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x74, + 0x69, 0x6d, 0x65, 0x4c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x2a, 0x0a, 0x11, + 0x68, 0x74, 0x6c, 0x63, 0x5f, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x6d, 0x73, 0x61, + 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x68, 0x74, 0x6c, 0x63, 0x4d, 0x69, 0x6e, + 0x69, 0x6d, 0x75, 0x6d, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x61, 0x73, 0x65, + 0x5f, 0x66, 0x65, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x62, 0x61, 0x73, 0x65, + 0x46, 0x65, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x66, 0x65, 0x65, 0x52, 0x61, 0x74, 0x65, 0x12, 0x2a, + 0x0a, 0x11, 0x68, 0x74, 0x6c, 0x63, 0x5f, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x6d, + 0x73, 0x61, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x68, 0x74, 0x6c, 0x63, 0x4d, + 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x4d, 0x73, 0x61, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x65, 0x78, + 0x74, 0x72, 0x61, 0x5f, 0x6f, 0x70, 0x61, 0x71, 0x75, 0x65, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x0c, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x65, 0x78, 0x74, 0x72, 0x61, 0x4f, 0x70, 0x61, 0x71, + 0x75, 0x65, 0x44, 0x61, 0x74, 0x61, 0x22, 0x5d, 0x0a, 0x0a, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, + 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x74, + 0x6f, 0x72, 0x61, 0x67, 0x65, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, + 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x03, 0x6f, 0x70, 0x73, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x70, + 0x52, 0x03, 0x6f, 0x70, 0x73, 0x22, 0x36, 0x0a, 0x02, 0x4f, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x65, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x65, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x8e, 0x01, + 0x0a, 0x13, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, + 0x6e, 0x12, 0x3b, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, + 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, + 0x0a, 0x0a, 0x66, 0x75, 0x6c, 0x6c, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x66, 0x75, 0x6c, 0x6c, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x22, 0x2c, + 0x0a, 0x14, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x22, 0xf4, 0x02, 0x0a, + 0x14, 0x52, 0x50, 0x43, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x61, 0x77, 0x5f, 0x6d, 0x61, 0x63, 0x61, + 0x72, 0x6f, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x72, 0x61, 0x77, 0x4d, + 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x17, 0x63, 0x75, 0x73, 0x74, 0x6f, + 0x6d, 0x5f, 0x63, 0x61, 0x76, 0x65, 0x61, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, + 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x34, 0x0a, 0x0b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x41, 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x0a, 0x73, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x41, 0x75, 0x74, 0x68, 0x12, 0x2d, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, + 0x50, 0x43, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x07, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, + 0x50, 0x43, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x08, 0x72, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x0c, 0x72, 0x65, 0x67, 0x5f, 0x63, 0x6f, 0x6d, + 0x70, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0b, 0x72, + 0x65, 0x67, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x6d, 0x73, + 0x67, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x6d, 0x73, 0x67, 0x49, + 0x64, 0x42, 0x10, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x22, 0x34, 0x0a, 0x0a, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x41, 0x75, 0x74, + 0x68, 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x66, 0x75, 0x6c, 0x6c, + 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6d, 0x65, 0x74, 0x68, + 0x6f, 0x64, 0x46, 0x75, 0x6c, 0x6c, 0x55, 0x72, 0x69, 0x22, 0xab, 0x01, 0x0a, 0x0a, 0x52, 0x50, + 0x43, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x6d, 0x65, 0x74, 0x68, + 0x6f, 0x64, 0x5f, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x46, 0x75, 0x6c, 0x6c, 0x55, 0x72, 0x69, + 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x72, 0x70, 0x63, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x70, 0x63, 0x12, + 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, + 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x0a, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, + 0x69, 0x73, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, + 0x69, 0x73, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xc0, 0x01, 0x0a, 0x15, 0x52, 0x50, 0x43, 0x4d, + 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x1c, 0x0a, 0x0a, 0x72, 0x65, 0x66, 0x5f, 0x6d, 0x73, 0x67, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x72, 0x65, 0x66, 0x4d, 0x73, 0x67, 0x49, 0x64, 0x12, + 0x3b, 0x0a, 0x08, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, + 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x48, 0x00, 0x52, 0x08, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x36, 0x0a, 0x08, + 0x66, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, + 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x08, 0x66, 0x65, 0x65, 0x64, + 0x62, 0x61, 0x63, 0x6b, 0x42, 0x14, 0x0a, 0x12, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, + 0x72, 0x65, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xa6, 0x01, 0x0a, 0x16, 0x4d, + 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, + 0x61, 0x72, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, + 0x6d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3d, + 0x0a, 0x1b, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, + 0x6e, 0x5f, 0x63, 0x61, 0x76, 0x65, 0x61, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x18, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x61, 0x63, 0x61, 0x72, + 0x6f, 0x6f, 0x6e, 0x43, 0x61, 0x76, 0x65, 0x61, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, + 0x0e, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x72, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x4d, + 0x6f, 0x64, 0x65, 0x22, 0x8b, 0x01, 0x0a, 0x11, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, + 0x74, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, + 0x29, 0x0a, 0x10, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x72, 0x65, 0x70, 0x6c, 0x61, + 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x16, 0x72, 0x65, + 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, + 0x69, 0x7a, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x15, 0x72, 0x65, 0x70, 0x6c, + 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, + 0x64, 0x2a, 0xcb, 0x02, 0x0a, 0x10, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x53, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, + 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, 0x59, 0x5f, 0x48, 0x41, 0x53, + 0x48, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x01, + 0x12, 0x26, 0x0a, 0x22, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, + 0x57, 0x49, 0x54, 0x4e, 0x45, 0x53, 0x53, 0x5f, 0x56, 0x30, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, + 0x59, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x02, 0x12, 0x26, 0x0a, 0x22, 0x53, 0x43, 0x52, 0x49, + 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x57, 0x49, 0x54, 0x4e, 0x45, 0x53, 0x53, 0x5f, + 0x56, 0x30, 0x5f, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x03, + 0x12, 0x16, 0x0a, 0x12, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, + 0x50, 0x55, 0x42, 0x4b, 0x45, 0x59, 0x10, 0x04, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x43, 0x52, 0x49, + 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x53, 0x49, 0x47, + 0x10, 0x05, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x4e, 0x55, 0x4c, 0x4c, 0x44, 0x41, 0x54, 0x41, 0x10, 0x06, 0x12, 0x1c, 0x0a, 0x18, + 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e, 0x4f, 0x4e, 0x5f, + 0x53, 0x54, 0x41, 0x4e, 0x44, 0x41, 0x52, 0x44, 0x10, 0x07, 0x12, 0x1f, 0x0a, 0x1b, 0x53, 0x43, + 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x57, 0x49, 0x54, 0x4e, 0x45, 0x53, + 0x53, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x08, 0x12, 0x22, 0x0a, 0x1e, 0x53, + 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x57, 0x49, 0x54, 0x4e, 0x45, + 0x53, 0x53, 0x5f, 0x56, 0x31, 0x5f, 0x54, 0x41, 0x50, 0x52, 0x4f, 0x4f, 0x54, 0x10, 0x09, 0x2a, + 0x62, 0x0a, 0x15, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x1e, 0x0a, 0x1a, 0x53, 0x54, 0x52, 0x41, + 0x54, 0x45, 0x47, 0x59, 0x5f, 0x55, 0x53, 0x45, 0x5f, 0x47, 0x4c, 0x4f, 0x42, 0x41, 0x4c, 0x5f, + 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x54, 0x52, 0x41, + 0x54, 0x45, 0x47, 0x59, 0x5f, 0x4c, 0x41, 0x52, 0x47, 0x45, 0x53, 0x54, 0x10, 0x01, 0x12, 0x13, + 0x0a, 0x0f, 0x53, 0x54, 0x52, 0x41, 0x54, 0x45, 0x47, 0x59, 0x5f, 0x52, 0x41, 0x4e, 0x44, 0x4f, + 0x4d, 0x10, 0x02, 0x2a, 0xac, 0x01, 0x0a, 0x0b, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x57, 0x49, 0x54, 0x4e, 0x45, 0x53, 0x53, 0x5f, 0x50, + 0x55, 0x42, 0x4b, 0x45, 0x59, 0x5f, 0x48, 0x41, 0x53, 0x48, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, + 0x4e, 0x45, 0x53, 0x54, 0x45, 0x44, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, 0x59, 0x5f, 0x48, 0x41, + 0x53, 0x48, 0x10, 0x01, 0x12, 0x1e, 0x0a, 0x1a, 0x55, 0x4e, 0x55, 0x53, 0x45, 0x44, 0x5f, 0x57, + 0x49, 0x54, 0x4e, 0x45, 0x53, 0x53, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, 0x59, 0x5f, 0x48, 0x41, + 0x53, 0x48, 0x10, 0x02, 0x12, 0x1d, 0x0a, 0x19, 0x55, 0x4e, 0x55, 0x53, 0x45, 0x44, 0x5f, 0x4e, + 0x45, 0x53, 0x54, 0x45, 0x44, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, 0x59, 0x5f, 0x48, 0x41, 0x53, + 0x48, 0x10, 0x03, 0x12, 0x12, 0x0a, 0x0e, 0x54, 0x41, 0x50, 0x52, 0x4f, 0x4f, 0x54, 0x5f, 0x50, + 0x55, 0x42, 0x4b, 0x45, 0x59, 0x10, 0x04, 0x12, 0x19, 0x0a, 0x15, 0x55, 0x4e, 0x55, 0x53, 0x45, + 0x44, 0x5f, 0x54, 0x41, 0x50, 0x52, 0x4f, 0x4f, 0x54, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, 0x59, + 0x10, 0x05, 0x2a, 0x8c, 0x01, 0x0a, 0x0e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, + 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, + 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, + 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x45, 0x47, 0x41, 0x43, 0x59, 0x10, 0x01, 0x12, 0x15, + 0x0a, 0x11, 0x53, 0x54, 0x41, 0x54, 0x49, 0x43, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x5f, + 0x4b, 0x45, 0x59, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x4e, 0x43, 0x48, 0x4f, 0x52, 0x53, + 0x10, 0x03, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x45, 0x4e, 0x46, + 0x4f, 0x52, 0x43, 0x45, 0x44, 0x5f, 0x4c, 0x45, 0x41, 0x53, 0x45, 0x10, 0x04, 0x12, 0x12, 0x0a, + 0x0e, 0x53, 0x49, 0x4d, 0x50, 0x4c, 0x45, 0x5f, 0x54, 0x41, 0x50, 0x52, 0x4f, 0x4f, 0x54, 0x10, + 0x05, 0x2a, 0x61, 0x0a, 0x09, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x15, + 0x0a, 0x11, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x54, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, + 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x54, + 0x4f, 0x52, 0x5f, 0x4c, 0x4f, 0x43, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x49, 0x4e, + 0x49, 0x54, 0x49, 0x41, 0x54, 0x4f, 0x52, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x10, 0x02, + 0x12, 0x12, 0x0a, 0x0e, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x54, 0x4f, 0x52, 0x5f, 0x42, 0x4f, + 0x54, 0x48, 0x10, 0x03, 0x2a, 0x60, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, + 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, + 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x4e, 0x43, 0x48, + 0x4f, 0x52, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x49, 0x4e, 0x43, 0x4f, 0x4d, 0x49, 0x4e, 0x47, + 0x5f, 0x48, 0x54, 0x4c, 0x43, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x4f, 0x55, 0x54, 0x47, 0x4f, + 0x49, 0x4e, 0x47, 0x5f, 0x48, 0x54, 0x4c, 0x43, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f, + 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x04, 0x2a, 0x71, 0x0a, 0x11, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, + 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x75, 0x74, 0x63, 0x6f, 0x6d, 0x65, 0x12, 0x13, 0x0a, 0x0f, 0x4f, + 0x55, 0x54, 0x43, 0x4f, 0x4d, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, + 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, + 0x09, 0x55, 0x4e, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, + 0x41, 0x42, 0x41, 0x4e, 0x44, 0x4f, 0x4e, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x46, + 0x49, 0x52, 0x53, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x47, 0x45, 0x10, 0x04, 0x12, 0x0b, 0x0a, 0x07, + 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, 0x05, 0x2a, 0x39, 0x0a, 0x0e, 0x4e, 0x6f, 0x64, + 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, + 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x42, 0x45, 0x54, 0x57, + 0x45, 0x45, 0x4e, 0x4e, 0x45, 0x53, 0x53, 0x5f, 0x43, 0x45, 0x4e, 0x54, 0x52, 0x41, 0x4c, 0x49, + 0x54, 0x59, 0x10, 0x01, 0x2a, 0x3b, 0x0a, 0x10, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x48, + 0x54, 0x4c, 0x43, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x43, 0x43, 0x45, + 0x50, 0x54, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x45, 0x54, 0x54, 0x4c, 0x45, + 0x44, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x45, 0x44, 0x10, + 0x02, 0x2a, 0xd9, 0x01, 0x0a, 0x14, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x46, 0x61, 0x69, + 0x6c, 0x75, 0x72, 0x65, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x13, 0x46, 0x41, + 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f, 0x4e, + 0x45, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, + 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, 0x01, 0x12, + 0x1b, 0x0a, 0x17, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, + 0x4e, 0x5f, 0x4e, 0x4f, 0x5f, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x10, 0x02, 0x12, 0x18, 0x0a, 0x14, + 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x45, + 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x2c, 0x0a, 0x28, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, + 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x49, 0x4e, 0x43, 0x4f, 0x52, 0x52, 0x45, + 0x43, 0x54, 0x5f, 0x50, 0x41, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x44, 0x45, 0x54, 0x41, 0x49, + 0x4c, 0x53, 0x10, 0x04, 0x12, 0x27, 0x0a, 0x23, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, + 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x49, 0x4e, 0x53, 0x55, 0x46, 0x46, 0x49, 0x43, 0x49, + 0x45, 0x4e, 0x54, 0x5f, 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x05, 0x2a, 0x89, 0x05, + 0x0a, 0x0a, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x42, 0x69, 0x74, 0x12, 0x18, 0x0a, 0x14, + 0x44, 0x41, 0x54, 0x41, 0x4c, 0x4f, 0x53, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x45, 0x43, 0x54, + 0x5f, 0x52, 0x45, 0x51, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x44, 0x41, 0x54, 0x41, 0x4c, 0x4f, + 0x53, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x45, 0x43, 0x54, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x01, + 0x12, 0x17, 0x0a, 0x13, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x4c, 0x5f, 0x52, 0x4f, 0x55, 0x49, + 0x4e, 0x47, 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x10, 0x03, 0x12, 0x1f, 0x0a, 0x1b, 0x55, 0x50, 0x46, + 0x52, 0x4f, 0x4e, 0x54, 0x5f, 0x53, 0x48, 0x55, 0x54, 0x44, 0x4f, 0x57, 0x4e, 0x5f, 0x53, 0x43, + 0x52, 0x49, 0x50, 0x54, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x04, 0x12, 0x1f, 0x0a, 0x1b, 0x55, 0x50, + 0x46, 0x52, 0x4f, 0x4e, 0x54, 0x5f, 0x53, 0x48, 0x55, 0x54, 0x44, 0x4f, 0x57, 0x4e, 0x5f, 0x53, + 0x43, 0x52, 0x49, 0x50, 0x54, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x05, 0x12, 0x16, 0x0a, 0x12, 0x47, + 0x4f, 0x53, 0x53, 0x49, 0x50, 0x5f, 0x51, 0x55, 0x45, 0x52, 0x49, 0x45, 0x53, 0x5f, 0x52, 0x45, + 0x51, 0x10, 0x06, 0x12, 0x16, 0x0a, 0x12, 0x47, 0x4f, 0x53, 0x53, 0x49, 0x50, 0x5f, 0x51, 0x55, + 0x45, 0x52, 0x49, 0x45, 0x53, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x07, 0x12, 0x11, 0x0a, 0x0d, 0x54, + 0x4c, 0x56, 0x5f, 0x4f, 0x4e, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x08, 0x12, 0x11, + 0x0a, 0x0d, 0x54, 0x4c, 0x56, 0x5f, 0x4f, 0x4e, 0x49, 0x4f, 0x4e, 0x5f, 0x4f, 0x50, 0x54, 0x10, + 0x09, 0x12, 0x1a, 0x0a, 0x16, 0x45, 0x58, 0x54, 0x5f, 0x47, 0x4f, 0x53, 0x53, 0x49, 0x50, 0x5f, + 0x51, 0x55, 0x45, 0x52, 0x49, 0x45, 0x53, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x0a, 0x12, 0x1a, 0x0a, + 0x16, 0x45, 0x58, 0x54, 0x5f, 0x47, 0x4f, 0x53, 0x53, 0x49, 0x50, 0x5f, 0x51, 0x55, 0x45, 0x52, + 0x49, 0x45, 0x53, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x0b, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x54, 0x41, + 0x54, 0x49, 0x43, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x52, + 0x45, 0x51, 0x10, 0x0c, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x54, 0x41, 0x54, 0x49, 0x43, 0x5f, 0x52, + 0x45, 0x4d, 0x4f, 0x54, 0x45, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x0d, 0x12, + 0x14, 0x0a, 0x10, 0x50, 0x41, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x41, 0x44, 0x44, 0x52, 0x5f, + 0x52, 0x45, 0x51, 0x10, 0x0e, 0x12, 0x14, 0x0a, 0x10, 0x50, 0x41, 0x59, 0x4d, 0x45, 0x4e, 0x54, + 0x5f, 0x41, 0x44, 0x44, 0x52, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x0f, 0x12, 0x0b, 0x0a, 0x07, 0x4d, + 0x50, 0x50, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x10, 0x12, 0x0b, 0x0a, 0x07, 0x4d, 0x50, 0x50, 0x5f, + 0x4f, 0x50, 0x54, 0x10, 0x11, 0x12, 0x16, 0x0a, 0x12, 0x57, 0x55, 0x4d, 0x42, 0x4f, 0x5f, 0x43, + 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x53, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x12, 0x12, 0x16, 0x0a, + 0x12, 0x57, 0x55, 0x4d, 0x42, 0x4f, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x53, 0x5f, + 0x4f, 0x50, 0x54, 0x10, 0x13, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x4e, 0x43, 0x48, 0x4f, 0x52, 0x53, + 0x5f, 0x52, 0x45, 0x51, 0x10, 0x14, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x4e, 0x43, 0x48, 0x4f, 0x52, + 0x53, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x15, 0x12, 0x1d, 0x0a, 0x19, 0x41, 0x4e, 0x43, 0x48, 0x4f, + 0x52, 0x53, 0x5f, 0x5a, 0x45, 0x52, 0x4f, 0x5f, 0x46, 0x45, 0x45, 0x5f, 0x48, 0x54, 0x4c, 0x43, + 0x5f, 0x52, 0x45, 0x51, 0x10, 0x16, 0x12, 0x1d, 0x0a, 0x19, 0x41, 0x4e, 0x43, 0x48, 0x4f, 0x52, + 0x53, 0x5f, 0x5a, 0x45, 0x52, 0x4f, 0x5f, 0x46, 0x45, 0x45, 0x5f, 0x48, 0x54, 0x4c, 0x43, 0x5f, + 0x4f, 0x50, 0x54, 0x10, 0x17, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x42, + 0x4c, 0x49, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, 0x44, + 0x10, 0x18, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x42, 0x4c, 0x49, 0x4e, + 0x44, 0x49, 0x4e, 0x47, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x10, 0x19, 0x12, + 0x0b, 0x0a, 0x07, 0x41, 0x4d, 0x50, 0x5f, 0x52, 0x45, 0x51, 0x10, 0x1e, 0x12, 0x0b, 0x0a, 0x07, + 0x41, 0x4d, 0x50, 0x5f, 0x4f, 0x50, 0x54, 0x10, 0x1f, 0x2a, 0xac, 0x01, 0x0a, 0x0d, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x55, + 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x55, 0x4e, + 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x55, 0x50, 0x44, 0x41, 0x54, + 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, + 0x47, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, + 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, + 0x02, 0x12, 0x1f, 0x0a, 0x1b, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, + 0x55, 0x52, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x45, 0x52, 0x52, + 0x10, 0x03, 0x12, 0x24, 0x0a, 0x20, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, + 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x50, 0x41, 0x52, + 0x41, 0x4d, 0x45, 0x54, 0x45, 0x52, 0x10, 0x04, 0x32, 0xb9, 0x27, 0x0a, 0x09, 0x4c, 0x69, 0x67, + 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x4a, 0x0a, 0x0d, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x61, 0x6c, + 0x6c, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x6c, + 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, + 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, + 0x65, 0x6c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x4b, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, + 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x44, + 0x0a, 0x0b, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x12, 0x19, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x46, 0x65, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, + 0x2e, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x09, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x69, 0x6e, + 0x73, 0x12, 0x17, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x6f, + 0x69, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, 0x73, 0x70, + 0x65, 0x6e, 0x74, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x55, 0x6e, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, 0x73, 0x70, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x15, 0x53, 0x75, + 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x30, 0x01, 0x12, 0x3b, 0x0a, 0x08, 0x53, 0x65, 0x6e, 0x64, + 0x4d, 0x61, 0x6e, 0x79, 0x12, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, + 0x64, 0x4d, 0x61, 0x6e, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x6c, + 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x4d, 0x61, 0x6e, 0x79, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0a, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x12, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x77, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x53, 0x69, 0x67, 0x6e, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x53, 0x69, 0x67, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, + 0x0a, 0x0d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, + 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6c, + 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, + 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x4d, 0x0a, 0x0e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, + 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0e, - 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x12, 0x1c, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6c, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, - 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x09, 0x4c, - 0x69, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x12, 0x17, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, - 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x13, 0x53, - 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x50, 0x65, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x73, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x1a, 0x10, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x30, 0x01, 0x12, 0x38, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, - 0x15, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, - 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, - 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x44, 0x65, 0x62, 0x75, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1a, + 0x1a, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x50, 0x65, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x3e, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x12, 0x17, 0x2e, 0x6c, + 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x47, 0x0a, 0x13, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x50, 0x65, 0x65, 0x72, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, + 0x65, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x10, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x65, 0x65, + 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x38, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, + 0x6e, 0x66, 0x6f, 0x12, 0x15, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x6c, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x44, 0x65, 0x62, 0x75, 0x67, 0x49, 0x6e, + 0x66, 0x6f, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, + 0x62, 0x75, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x62, 0x75, 0x67, 0x49, - 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x62, 0x75, 0x67, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x52, 0x65, - 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x49, 0x6e, - 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x66, - 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0f, 0x50, 0x65, 0x6e, - 0x64, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x12, 0x1d, 0x2e, 0x6c, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x61, 0x6e, - 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6c, 0x6e, - 0x72, 0x70, 0x63, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x61, 0x6e, 0x6e, - 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0c, 0x4c, - 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, + 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0f, 0x47, + 0x65, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1d, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, + 0x72, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, + 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, + 0x0f, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, + 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, + 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x43, + 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x47, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x12, + 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, + 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, - 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1f, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, - 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x30, 0x01, 0x12, 0x4d, 0x0a, 0x0e, - 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x12, 0x1c, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x43, 0x68, 0x61, - 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6c, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x43, 0x68, 0x61, 0x6e, 0x6e, - 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0f, 0x4f, - 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x19, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, - 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x43, - 0x0a, 0x0b, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x19, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, - 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x30, 0x01, 0x12, 0x53, 0x0a, 0x10, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x6e, - 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x10, 0x46, 0x75, 0x6e, 0x64, - 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x74, 0x65, 0x70, 0x12, 0x1b, 0x2e, 0x6c, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x61, 0x6e, - 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x67, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x46, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x74, - 0x65, 0x70, 0x52, 0x65, 0x73, 0x70, 0x12, 0x50, 0x0a, 0x0f, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, - 0x6c, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x46, 0x0a, 0x0c, 0x43, 0x6c, 0x6f, 0x73, - 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, - 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x30, 0x01, - 0x12, 0x4d, 0x0a, 0x0e, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, - 0x65, 0x6c, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x62, 0x61, 0x6e, 0x64, - 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, - 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x3f, 0x0a, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x12, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x88, 0x02, 0x01, 0x28, 0x01, 0x30, 0x01, - 0x12, 0x3a, 0x0a, 0x0f, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x53, - 0x79, 0x6e, 0x63, 0x12, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0b, - 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x19, 0x2e, 0x6c, 0x6e, - 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x16, 0x53, 0x75, 0x62, 0x73, + 0x63, 0x72, 0x69, 0x62, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x73, 0x12, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, + 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, + 0x6e, 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x30, 0x01, + 0x12, 0x4d, 0x0a, 0x0e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, + 0x6c, 0x73, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, + 0x64, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x43, + 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x41, 0x0a, 0x0f, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x53, 0x79, + 0x6e, 0x63, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x43, + 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x69, + 0x6e, 0x74, 0x12, 0x43, 0x0a, 0x0b, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, + 0x6c, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, + 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x6c, + 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x30, 0x01, 0x12, 0x53, 0x0a, 0x10, 0x42, 0x61, 0x74, 0x63, 0x68, + 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1e, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, + 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x6e, 0x43, 0x68, 0x61, + 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x10, + 0x46, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x74, 0x65, 0x70, + 0x12, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x67, 0x1a, 0x1b, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x53, 0x74, 0x65, 0x70, 0x52, 0x65, 0x73, 0x70, 0x12, 0x50, 0x0a, 0x0f, 0x43, 0x68, + 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x12, 0x1c, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x41, 0x63, 0x63, + 0x65, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x41, 0x63, 0x63, 0x65, 0x70, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x46, 0x0a, 0x0c, + 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1a, 0x2e, 0x6c, + 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, + 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, + 0x2e, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x30, 0x01, 0x12, 0x4d, 0x0a, 0x0e, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x43, + 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x41, + 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x62, 0x61, + 0x6e, 0x64, 0x6f, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x61, 0x79, 0x6d, 0x65, + 0x6e, 0x74, 0x12, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x88, 0x02, 0x01, - 0x28, 0x01, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0f, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, - 0x75, 0x74, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x41, 0x64, 0x64, 0x49, 0x6e, - 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x0e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, - 0x76, 0x6f, 0x69, 0x63, 0x65, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, - 0x64, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x45, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x73, - 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, - 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, - 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x0d, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, - 0x70, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x1a, 0x0e, 0x2e, 0x6c, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x41, 0x0a, 0x11, - 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, - 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, - 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x0e, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x30, 0x01, 0x12, - 0x32, 0x0a, 0x0c, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x50, 0x61, 0x79, 0x52, 0x65, 0x71, 0x12, - 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, 0x79, 0x52, 0x65, 0x71, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x1a, 0x0d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, 0x79, - 0x52, 0x65, 0x71, 0x12, 0x47, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x79, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x0d, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, - 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1f, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x50, - 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, + 0x28, 0x01, 0x30, 0x01, 0x12, 0x3a, 0x0a, 0x0f, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x61, 0x79, 0x6d, + 0x65, 0x6e, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x46, 0x0a, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, + 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x03, 0x88, 0x02, 0x01, 0x28, 0x01, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0f, 0x53, 0x65, 0x6e, 0x64, + 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x19, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x54, 0x6f, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, + 0x65, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x41, + 0x64, 0x64, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x0e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, + 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, + 0x63, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x6f, + 0x69, 0x63, 0x65, 0x73, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x6f, + 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x0d, 0x4c, + 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x12, 0x2e, 0x6c, + 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, + 0x1a, 0x0e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, + 0x12, 0x41, 0x0a, 0x11, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x49, 0x6e, 0x76, + 0x6f, 0x69, 0x63, 0x65, 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, + 0x76, 0x6f, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x1a, 0x0e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, + 0x65, 0x30, 0x01, 0x12, 0x32, 0x0a, 0x0c, 0x44, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x50, 0x61, 0x79, + 0x52, 0x65, 0x71, 0x12, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, 0x79, 0x52, + 0x65, 0x71, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x1a, 0x0d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, + 0x2e, 0x50, 0x61, 0x79, 0x52, 0x65, 0x71, 0x12, 0x47, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x50, + 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x40, 0x0a, 0x0d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x47, 0x72, 0x61, 0x70, - 0x68, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, - 0x6c, 0x47, 0x72, 0x61, 0x70, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x47, 0x72, 0x61, - 0x70, 0x68, 0x12, 0x47, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, - 0x72, 0x69, 0x63, 0x73, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, - 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, 0x72, - 0x69, 0x63, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x0b, 0x47, - 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, - 0x65, 0x6c, 0x45, 0x64, 0x67, 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, - 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, - 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x44, - 0x0a, 0x0b, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x12, 0x19, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x6f, 0x75, 0x74, 0x65, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x77, 0x6f, - 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, - 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x35, 0x0a, 0x0a, 0x53, 0x74, 0x6f, 0x70, 0x44, 0x61, 0x65, - 0x6d, 0x6f, 0x6e, 0x12, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x6f, 0x70, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x15, - 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, - 0x47, 0x72, 0x61, 0x70, 0x68, 0x12, 0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x72, - 0x61, 0x70, 0x68, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x53, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x47, 0x72, 0x61, 0x70, 0x68, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0a, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, - 0x76, 0x65, 0x6c, 0x12, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x62, 0x75, - 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x09, 0x46, 0x65, 0x65, 0x52, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x17, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x65, - 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x65, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, - 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, - 0x72, 0x70, 0x63, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x11, 0x46, 0x6f, 0x72, 0x77, - 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1f, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, - 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, - 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, - 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x4e, 0x0a, 0x13, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, - 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x21, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, - 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, - 0x12, 0x54, 0x0a, 0x17, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x41, 0x6c, 0x6c, 0x43, 0x68, 0x61, - 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12, 0x1e, 0x2e, 0x6c, 0x6e, - 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x45, 0x78, - 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, - 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, 0x6e, - 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x4e, 0x0a, 0x10, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, - 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, 0x6e, 0x61, - 0x70, 0x73, 0x68, 0x6f, 0x74, 0x1a, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x56, 0x65, - 0x72, 0x69, 0x66, 0x79, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, - 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12, - 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x43, - 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, - 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, - 0x0a, 0x17, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, - 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12, 0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70, - 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, - 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, - 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x53, 0x6e, - 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x30, 0x01, 0x12, 0x47, 0x0a, 0x0c, 0x42, 0x61, 0x6b, 0x65, - 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x42, 0x61, 0x6b, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x6b, - 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x50, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, - 0x6e, 0x49, 0x44, 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, - 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x12, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, - 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, - 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x18, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x4d, 0x61, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x56, 0x0a, 0x15, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, 0x50, 0x43, 0x4d, 0x69, - 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x12, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x52, 0x50, 0x43, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, - 0x50, 0x43, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x56, 0x0a, 0x11, 0x53, 0x65, 0x6e, 0x64, 0x43, - 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1f, 0x2e, 0x6c, - 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, - 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x58, 0x0a, 0x17, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43, 0x75, 0x73, 0x74, - 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x25, 0x2e, 0x6c, 0x6e, 0x72, - 0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43, 0x75, 0x73, 0x74, - 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x14, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x30, 0x01, 0x12, 0x44, 0x0a, 0x0b, 0x4c, 0x69, 0x73, - 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x5f, 0x0a, 0x14, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x48, 0x74, 0x6c, 0x63, 0x52, 0x65, 0x73, - 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, - 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x48, 0x74, 0x6c, 0x63, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x6c, 0x6e, + 0x12, 0x4a, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, + 0x74, 0x12, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x61, 0x79, + 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x11, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x12, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x41, 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x41, 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x0d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, + 0x47, 0x72, 0x61, 0x70, 0x68, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, + 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x47, 0x72, 0x61, 0x70, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, + 0x6c, 0x47, 0x72, 0x61, 0x70, 0x68, 0x12, 0x47, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, + 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, + 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, + 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x39, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, + 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x45, 0x64, 0x67, 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x47, 0x65, + 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x6c, 0x6e, 0x72, 0x70, + 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x0f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, + 0x66, 0x6f, 0x12, 0x44, 0x0a, 0x0b, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x6f, 0x75, 0x74, 0x65, + 0x73, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, + 0x6f, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, + 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4e, + 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x2e, 0x6c, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, + 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x35, 0x0a, 0x0a, 0x53, 0x74, 0x6f, + 0x70, 0x44, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x12, 0x12, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x57, 0x0a, 0x15, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43, 0x68, 0x61, + 0x6e, 0x6e, 0x65, 0x6c, 0x47, 0x72, 0x61, 0x70, 0x68, 0x12, 0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70, + 0x63, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x53, + 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x47, 0x72, 0x61, 0x70, 0x68, 0x54, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, + 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0a, 0x44, 0x65, 0x62, + 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4c, + 0x65, 0x76, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x09, + 0x46, 0x65, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x17, 0x2e, 0x6c, 0x6e, 0x72, 0x70, + 0x63, 0x2e, 0x46, 0x65, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x65, 0x65, 0x52, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x13, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x11, + 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, + 0x79, 0x12, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, + 0x64, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x6f, 0x72, 0x77, 0x61, + 0x72, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x13, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x68, + 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x21, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, + 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, + 0x63, 0x6b, 0x75, 0x70, 0x12, 0x54, 0x0a, 0x17, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x41, 0x6c, + 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12, + 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, + 0x75, 0x70, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, + 0x75, 0x70, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x4e, 0x0a, 0x10, 0x56, 0x65, + 0x72, 0x69, 0x66, 0x79, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x19, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, + 0x70, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x1a, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, + 0x63, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, + 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x15, 0x52, 0x65, + 0x73, 0x74, 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, + 0x75, 0x70, 0x73, 0x12, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x73, 0x74, + 0x6f, 0x72, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x73, + 0x74, 0x6f, 0x72, 0x65, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x58, 0x0a, 0x17, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x43, + 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x73, 0x12, 0x20, 0x2e, + 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x42, 0x61, 0x63, + 0x6b, 0x75, 0x70, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, + 0x19, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x42, 0x61, 0x63, 0x6b, + 0x75, 0x70, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x30, 0x01, 0x12, 0x47, 0x0a, 0x0c, + 0x42, 0x61, 0x6b, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x12, 0x1a, 0x2e, 0x6c, + 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61, 0x6b, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, + 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, + 0x2e, 0x42, 0x61, 0x6b, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, + 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x73, 0x12, 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x49, 0x44, 0x12, 0x1e, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, + 0x6f, 0x6e, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6c, 0x6e, + 0x72, 0x70, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, + 0x6f, 0x6e, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0f, + 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x1d, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x65, 0x72, 0x6d, 0x69, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, + 0x0a, 0x18, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x50, + 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x4d, 0x61, 0x63, 0x50, 0x65, 0x72, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x15, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x52, + 0x50, 0x43, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, 0x12, 0x1c, 0x2e, 0x6c, + 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x50, 0x43, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, + 0x72, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x1b, 0x2e, 0x6c, 0x6e, 0x72, + 0x70, 0x63, 0x2e, 0x52, 0x50, 0x43, 0x4d, 0x69, 0x64, 0x64, 0x6c, 0x65, 0x77, 0x61, 0x72, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x56, 0x0a, 0x11, 0x53, + 0x65, 0x6e, 0x64, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x12, 0x1f, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x75, 0x73, + 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x20, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x43, 0x75, + 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x17, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, + 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x25, + 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, + 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75, + 0x73, 0x74, 0x6f, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x30, 0x01, 0x12, 0x44, 0x0a, + 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x12, 0x19, 0x2e, 0x6c, + 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x14, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x48, 0x74, 0x6c, + 0x63, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x48, 0x74, 0x6c, 0x63, 0x52, 0x65, - 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, - 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f, - 0x6c, 0x6e, 0x64, 0x2f, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x23, 0x2e, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x6f, 0x6b, 0x75, 0x70, 0x48, 0x74, + 0x6c, 0x63, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x6e, 0x65, 0x74, 0x77, + 0x6f, 0x72, 0x6b, 0x2f, 0x6c, 0x6e, 0x64, 0x2f, 0x6c, 0x6e, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -21062,7 +21117,7 @@ func file_lightning_proto_rawDescGZIP() []byte { } var file_lightning_proto_enumTypes = make([]protoimpl.EnumInfo, 21) -var file_lightning_proto_msgTypes = make([]protoimpl.MessageInfo, 224) +var file_lightning_proto_msgTypes = make([]protoimpl.MessageInfo, 225) var file_lightning_proto_goTypes = []interface{}{ (OutputScriptType)(0), // 0: lnrpc.OutputScriptType (CoinSelectionStrategy)(0), // 1: lnrpc.CoinSelectionStrategy @@ -21245,70 +21300,71 @@ var file_lightning_proto_goTypes = []interface{}{ (*FeeReportRequest)(nil), // 178: lnrpc.FeeReportRequest (*ChannelFeeReport)(nil), // 179: lnrpc.ChannelFeeReport (*FeeReportResponse)(nil), // 180: lnrpc.FeeReportResponse - (*PolicyUpdateRequest)(nil), // 181: lnrpc.PolicyUpdateRequest - (*FailedUpdate)(nil), // 182: lnrpc.FailedUpdate - (*PolicyUpdateResponse)(nil), // 183: lnrpc.PolicyUpdateResponse - (*ForwardingHistoryRequest)(nil), // 184: lnrpc.ForwardingHistoryRequest - (*ForwardingEvent)(nil), // 185: lnrpc.ForwardingEvent - (*ForwardingHistoryResponse)(nil), // 186: lnrpc.ForwardingHistoryResponse - (*ExportChannelBackupRequest)(nil), // 187: lnrpc.ExportChannelBackupRequest - (*ChannelBackup)(nil), // 188: lnrpc.ChannelBackup - (*MultiChanBackup)(nil), // 189: lnrpc.MultiChanBackup - (*ChanBackupExportRequest)(nil), // 190: lnrpc.ChanBackupExportRequest - (*ChanBackupSnapshot)(nil), // 191: lnrpc.ChanBackupSnapshot - (*ChannelBackups)(nil), // 192: lnrpc.ChannelBackups - (*RestoreChanBackupRequest)(nil), // 193: lnrpc.RestoreChanBackupRequest - (*RestoreBackupResponse)(nil), // 194: lnrpc.RestoreBackupResponse - (*ChannelBackupSubscription)(nil), // 195: lnrpc.ChannelBackupSubscription - (*VerifyChanBackupResponse)(nil), // 196: lnrpc.VerifyChanBackupResponse - (*MacaroonPermission)(nil), // 197: lnrpc.MacaroonPermission - (*BakeMacaroonRequest)(nil), // 198: lnrpc.BakeMacaroonRequest - (*BakeMacaroonResponse)(nil), // 199: lnrpc.BakeMacaroonResponse - (*ListMacaroonIDsRequest)(nil), // 200: lnrpc.ListMacaroonIDsRequest - (*ListMacaroonIDsResponse)(nil), // 201: lnrpc.ListMacaroonIDsResponse - (*DeleteMacaroonIDRequest)(nil), // 202: lnrpc.DeleteMacaroonIDRequest - (*DeleteMacaroonIDResponse)(nil), // 203: lnrpc.DeleteMacaroonIDResponse - (*MacaroonPermissionList)(nil), // 204: lnrpc.MacaroonPermissionList - (*ListPermissionsRequest)(nil), // 205: lnrpc.ListPermissionsRequest - (*ListPermissionsResponse)(nil), // 206: lnrpc.ListPermissionsResponse - (*Failure)(nil), // 207: lnrpc.Failure - (*ChannelUpdate)(nil), // 208: lnrpc.ChannelUpdate - (*MacaroonId)(nil), // 209: lnrpc.MacaroonId - (*Op)(nil), // 210: lnrpc.Op - (*CheckMacPermRequest)(nil), // 211: lnrpc.CheckMacPermRequest - (*CheckMacPermResponse)(nil), // 212: lnrpc.CheckMacPermResponse - (*RPCMiddlewareRequest)(nil), // 213: lnrpc.RPCMiddlewareRequest - (*StreamAuth)(nil), // 214: lnrpc.StreamAuth - (*RPCMessage)(nil), // 215: lnrpc.RPCMessage - (*RPCMiddlewareResponse)(nil), // 216: lnrpc.RPCMiddlewareResponse - (*MiddlewareRegistration)(nil), // 217: lnrpc.MiddlewareRegistration - (*InterceptFeedback)(nil), // 218: lnrpc.InterceptFeedback - nil, // 219: lnrpc.SendRequest.DestCustomRecordsEntry - nil, // 220: lnrpc.EstimateFeeRequest.AddrToAmountEntry - nil, // 221: lnrpc.SendManyRequest.AddrToAmountEntry - nil, // 222: lnrpc.Peer.FeaturesEntry - nil, // 223: lnrpc.GetInfoResponse.FeaturesEntry - nil, // 224: lnrpc.GetDebugInfoResponse.ConfigEntry - (*PendingChannelsResponse_PendingChannel)(nil), // 225: lnrpc.PendingChannelsResponse.PendingChannel - (*PendingChannelsResponse_PendingOpenChannel)(nil), // 226: lnrpc.PendingChannelsResponse.PendingOpenChannel - (*PendingChannelsResponse_WaitingCloseChannel)(nil), // 227: lnrpc.PendingChannelsResponse.WaitingCloseChannel - (*PendingChannelsResponse_Commitments)(nil), // 228: lnrpc.PendingChannelsResponse.Commitments - (*PendingChannelsResponse_ClosedChannel)(nil), // 229: lnrpc.PendingChannelsResponse.ClosedChannel - (*PendingChannelsResponse_ForceClosedChannel)(nil), // 230: lnrpc.PendingChannelsResponse.ForceClosedChannel - nil, // 231: lnrpc.WalletBalanceResponse.AccountBalanceEntry - nil, // 232: lnrpc.QueryRoutesRequest.DestCustomRecordsEntry - nil, // 233: lnrpc.Hop.CustomRecordsEntry - nil, // 234: lnrpc.LightningNode.FeaturesEntry - nil, // 235: lnrpc.LightningNode.CustomRecordsEntry - nil, // 236: lnrpc.RoutingPolicy.CustomRecordsEntry - nil, // 237: lnrpc.ChannelEdge.CustomRecordsEntry - nil, // 238: lnrpc.NodeMetricsResponse.BetweennessCentralityEntry - nil, // 239: lnrpc.NodeUpdate.FeaturesEntry - nil, // 240: lnrpc.Invoice.FeaturesEntry - nil, // 241: lnrpc.Invoice.AmpInvoiceStateEntry - nil, // 242: lnrpc.InvoiceHTLC.CustomRecordsEntry - nil, // 243: lnrpc.PayReq.FeaturesEntry - nil, // 244: lnrpc.ListPermissionsResponse.MethodPermissionsEntry + (*InboundFee)(nil), // 181: lnrpc.InboundFee + (*PolicyUpdateRequest)(nil), // 182: lnrpc.PolicyUpdateRequest + (*FailedUpdate)(nil), // 183: lnrpc.FailedUpdate + (*PolicyUpdateResponse)(nil), // 184: lnrpc.PolicyUpdateResponse + (*ForwardingHistoryRequest)(nil), // 185: lnrpc.ForwardingHistoryRequest + (*ForwardingEvent)(nil), // 186: lnrpc.ForwardingEvent + (*ForwardingHistoryResponse)(nil), // 187: lnrpc.ForwardingHistoryResponse + (*ExportChannelBackupRequest)(nil), // 188: lnrpc.ExportChannelBackupRequest + (*ChannelBackup)(nil), // 189: lnrpc.ChannelBackup + (*MultiChanBackup)(nil), // 190: lnrpc.MultiChanBackup + (*ChanBackupExportRequest)(nil), // 191: lnrpc.ChanBackupExportRequest + (*ChanBackupSnapshot)(nil), // 192: lnrpc.ChanBackupSnapshot + (*ChannelBackups)(nil), // 193: lnrpc.ChannelBackups + (*RestoreChanBackupRequest)(nil), // 194: lnrpc.RestoreChanBackupRequest + (*RestoreBackupResponse)(nil), // 195: lnrpc.RestoreBackupResponse + (*ChannelBackupSubscription)(nil), // 196: lnrpc.ChannelBackupSubscription + (*VerifyChanBackupResponse)(nil), // 197: lnrpc.VerifyChanBackupResponse + (*MacaroonPermission)(nil), // 198: lnrpc.MacaroonPermission + (*BakeMacaroonRequest)(nil), // 199: lnrpc.BakeMacaroonRequest + (*BakeMacaroonResponse)(nil), // 200: lnrpc.BakeMacaroonResponse + (*ListMacaroonIDsRequest)(nil), // 201: lnrpc.ListMacaroonIDsRequest + (*ListMacaroonIDsResponse)(nil), // 202: lnrpc.ListMacaroonIDsResponse + (*DeleteMacaroonIDRequest)(nil), // 203: lnrpc.DeleteMacaroonIDRequest + (*DeleteMacaroonIDResponse)(nil), // 204: lnrpc.DeleteMacaroonIDResponse + (*MacaroonPermissionList)(nil), // 205: lnrpc.MacaroonPermissionList + (*ListPermissionsRequest)(nil), // 206: lnrpc.ListPermissionsRequest + (*ListPermissionsResponse)(nil), // 207: lnrpc.ListPermissionsResponse + (*Failure)(nil), // 208: lnrpc.Failure + (*ChannelUpdate)(nil), // 209: lnrpc.ChannelUpdate + (*MacaroonId)(nil), // 210: lnrpc.MacaroonId + (*Op)(nil), // 211: lnrpc.Op + (*CheckMacPermRequest)(nil), // 212: lnrpc.CheckMacPermRequest + (*CheckMacPermResponse)(nil), // 213: lnrpc.CheckMacPermResponse + (*RPCMiddlewareRequest)(nil), // 214: lnrpc.RPCMiddlewareRequest + (*StreamAuth)(nil), // 215: lnrpc.StreamAuth + (*RPCMessage)(nil), // 216: lnrpc.RPCMessage + (*RPCMiddlewareResponse)(nil), // 217: lnrpc.RPCMiddlewareResponse + (*MiddlewareRegistration)(nil), // 218: lnrpc.MiddlewareRegistration + (*InterceptFeedback)(nil), // 219: lnrpc.InterceptFeedback + nil, // 220: lnrpc.SendRequest.DestCustomRecordsEntry + nil, // 221: lnrpc.EstimateFeeRequest.AddrToAmountEntry + nil, // 222: lnrpc.SendManyRequest.AddrToAmountEntry + nil, // 223: lnrpc.Peer.FeaturesEntry + nil, // 224: lnrpc.GetInfoResponse.FeaturesEntry + nil, // 225: lnrpc.GetDebugInfoResponse.ConfigEntry + (*PendingChannelsResponse_PendingChannel)(nil), // 226: lnrpc.PendingChannelsResponse.PendingChannel + (*PendingChannelsResponse_PendingOpenChannel)(nil), // 227: lnrpc.PendingChannelsResponse.PendingOpenChannel + (*PendingChannelsResponse_WaitingCloseChannel)(nil), // 228: lnrpc.PendingChannelsResponse.WaitingCloseChannel + (*PendingChannelsResponse_Commitments)(nil), // 229: lnrpc.PendingChannelsResponse.Commitments + (*PendingChannelsResponse_ClosedChannel)(nil), // 230: lnrpc.PendingChannelsResponse.ClosedChannel + (*PendingChannelsResponse_ForceClosedChannel)(nil), // 231: lnrpc.PendingChannelsResponse.ForceClosedChannel + nil, // 232: lnrpc.WalletBalanceResponse.AccountBalanceEntry + nil, // 233: lnrpc.QueryRoutesRequest.DestCustomRecordsEntry + nil, // 234: lnrpc.Hop.CustomRecordsEntry + nil, // 235: lnrpc.LightningNode.FeaturesEntry + nil, // 236: lnrpc.LightningNode.CustomRecordsEntry + nil, // 237: lnrpc.RoutingPolicy.CustomRecordsEntry + nil, // 238: lnrpc.ChannelEdge.CustomRecordsEntry + nil, // 239: lnrpc.NodeMetricsResponse.BetweennessCentralityEntry + nil, // 240: lnrpc.NodeUpdate.FeaturesEntry + nil, // 241: lnrpc.Invoice.FeaturesEntry + nil, // 242: lnrpc.Invoice.AmpInvoiceStateEntry + nil, // 243: lnrpc.InvoiceHTLC.CustomRecordsEntry + nil, // 244: lnrpc.PayReq.FeaturesEntry + nil, // 245: lnrpc.ListPermissionsResponse.MethodPermissionsEntry } var file_lightning_proto_depIdxs = []int32{ 2, // 0: lnrpc.Utxo.address_type:type_name -> lnrpc.AddressType @@ -21318,14 +21374,14 @@ var file_lightning_proto_depIdxs = []int32{ 40, // 4: lnrpc.Transaction.previous_outpoints:type_name -> lnrpc.PreviousOutPoint 29, // 5: lnrpc.TransactionDetails.transactions:type_name -> lnrpc.Transaction 32, // 6: lnrpc.SendRequest.fee_limit:type_name -> lnrpc.FeeLimit - 219, // 7: lnrpc.SendRequest.dest_custom_records:type_name -> lnrpc.SendRequest.DestCustomRecordsEntry + 220, // 7: lnrpc.SendRequest.dest_custom_records:type_name -> lnrpc.SendRequest.DestCustomRecordsEntry 10, // 8: lnrpc.SendRequest.dest_features:type_name -> lnrpc.FeatureBit 126, // 9: lnrpc.SendResponse.payment_route:type_name -> lnrpc.Route 126, // 10: lnrpc.SendToRouteRequest.route:type_name -> lnrpc.Route 3, // 11: lnrpc.ChannelAcceptRequest.commitment_type:type_name -> lnrpc.CommitmentType - 220, // 12: lnrpc.EstimateFeeRequest.AddrToAmount:type_name -> lnrpc.EstimateFeeRequest.AddrToAmountEntry + 221, // 12: lnrpc.EstimateFeeRequest.AddrToAmount:type_name -> lnrpc.EstimateFeeRequest.AddrToAmountEntry 1, // 13: lnrpc.EstimateFeeRequest.coin_selection_strategy:type_name -> lnrpc.CoinSelectionStrategy - 221, // 14: lnrpc.SendManyRequest.AddrToAmount:type_name -> lnrpc.SendManyRequest.AddrToAmountEntry + 222, // 14: lnrpc.SendManyRequest.AddrToAmount:type_name -> lnrpc.SendManyRequest.AddrToAmountEntry 1, // 15: lnrpc.SendManyRequest.coin_selection_strategy:type_name -> lnrpc.CoinSelectionStrategy 1, // 16: lnrpc.SendCoinsRequest.coin_selection_strategy:type_name -> lnrpc.CoinSelectionStrategy 27, // 17: lnrpc.ListUnspentResponse.utxos:type_name -> lnrpc.Utxo @@ -21346,13 +21402,13 @@ var file_lightning_proto_depIdxs = []int32{ 39, // 32: lnrpc.Resolution.outpoint:type_name -> lnrpc.OutPoint 68, // 33: lnrpc.ClosedChannelsResponse.channels:type_name -> lnrpc.ChannelCloseSummary 13, // 34: lnrpc.Peer.sync_type:type_name -> lnrpc.Peer.SyncType - 222, // 35: lnrpc.Peer.features:type_name -> lnrpc.Peer.FeaturesEntry + 223, // 35: lnrpc.Peer.features:type_name -> lnrpc.Peer.FeaturesEntry 73, // 36: lnrpc.Peer.errors:type_name -> lnrpc.TimestampedError 72, // 37: lnrpc.ListPeersResponse.peers:type_name -> lnrpc.Peer 14, // 38: lnrpc.PeerEvent.type:type_name -> lnrpc.PeerEvent.EventType 84, // 39: lnrpc.GetInfoResponse.chains:type_name -> lnrpc.Chain - 223, // 40: lnrpc.GetInfoResponse.features:type_name -> lnrpc.GetInfoResponse.FeaturesEntry - 224, // 41: lnrpc.GetDebugInfoResponse.config:type_name -> lnrpc.GetDebugInfoResponse.ConfigEntry + 224, // 40: lnrpc.GetInfoResponse.features:type_name -> lnrpc.GetInfoResponse.FeaturesEntry + 225, // 41: lnrpc.GetDebugInfoResponse.config:type_name -> lnrpc.GetDebugInfoResponse.ConfigEntry 38, // 42: lnrpc.ChannelOpenUpdate.channel_point:type_name -> lnrpc.ChannelPoint 38, // 43: lnrpc.CloseChannelRequest.channel_point:type_name -> lnrpc.ChannelPoint 90, // 44: lnrpc.CloseStatusUpdate.close_pending:type_name -> lnrpc.PendingUpdate @@ -21377,10 +21433,10 @@ var file_lightning_proto_depIdxs = []int32{ 103, // 63: lnrpc.FundingTransitionMsg.shim_cancel:type_name -> lnrpc.FundingShimCancel 104, // 64: lnrpc.FundingTransitionMsg.psbt_verify:type_name -> lnrpc.FundingPsbtVerify 105, // 65: lnrpc.FundingTransitionMsg.psbt_finalize:type_name -> lnrpc.FundingPsbtFinalize - 226, // 66: lnrpc.PendingChannelsResponse.pending_open_channels:type_name -> lnrpc.PendingChannelsResponse.PendingOpenChannel - 229, // 67: lnrpc.PendingChannelsResponse.pending_closing_channels:type_name -> lnrpc.PendingChannelsResponse.ClosedChannel - 230, // 68: lnrpc.PendingChannelsResponse.pending_force_closing_channels:type_name -> lnrpc.PendingChannelsResponse.ForceClosedChannel - 227, // 69: lnrpc.PendingChannelsResponse.waiting_close_channels:type_name -> lnrpc.PendingChannelsResponse.WaitingCloseChannel + 227, // 66: lnrpc.PendingChannelsResponse.pending_open_channels:type_name -> lnrpc.PendingChannelsResponse.PendingOpenChannel + 230, // 67: lnrpc.PendingChannelsResponse.pending_closing_channels:type_name -> lnrpc.PendingChannelsResponse.ClosedChannel + 231, // 68: lnrpc.PendingChannelsResponse.pending_force_closing_channels:type_name -> lnrpc.PendingChannelsResponse.ForceClosedChannel + 228, // 69: lnrpc.PendingChannelsResponse.waiting_close_channels:type_name -> lnrpc.PendingChannelsResponse.WaitingCloseChannel 62, // 70: lnrpc.ChannelEventUpdate.open_channel:type_name -> lnrpc.Channel 68, // 71: lnrpc.ChannelEventUpdate.closed_channel:type_name -> lnrpc.ChannelCloseSummary 38, // 72: lnrpc.ChannelEventUpdate.active_channel:type_name -> lnrpc.ChannelPoint @@ -21388,7 +21444,7 @@ var file_lightning_proto_depIdxs = []int32{ 90, // 74: lnrpc.ChannelEventUpdate.pending_open_channel:type_name -> lnrpc.PendingUpdate 38, // 75: lnrpc.ChannelEventUpdate.fully_resolved_channel:type_name -> lnrpc.ChannelPoint 16, // 76: lnrpc.ChannelEventUpdate.type:type_name -> lnrpc.ChannelEventUpdate.UpdateType - 231, // 77: lnrpc.WalletBalanceResponse.account_balance:type_name -> lnrpc.WalletBalanceResponse.AccountBalanceEntry + 232, // 77: lnrpc.WalletBalanceResponse.account_balance:type_name -> lnrpc.WalletBalanceResponse.AccountBalanceEntry 116, // 78: lnrpc.ChannelBalanceResponse.local_balance:type_name -> lnrpc.Amount 116, // 79: lnrpc.ChannelBalanceResponse.remote_balance:type_name -> lnrpc.Amount 116, // 80: lnrpc.ChannelBalanceResponse.unsettled_local_balance:type_name -> lnrpc.Amount @@ -21398,33 +21454,33 @@ var file_lightning_proto_depIdxs = []int32{ 32, // 84: lnrpc.QueryRoutesRequest.fee_limit:type_name -> lnrpc.FeeLimit 121, // 85: lnrpc.QueryRoutesRequest.ignored_edges:type_name -> lnrpc.EdgeLocator 120, // 86: lnrpc.QueryRoutesRequest.ignored_pairs:type_name -> lnrpc.NodePair - 232, // 87: lnrpc.QueryRoutesRequest.dest_custom_records:type_name -> lnrpc.QueryRoutesRequest.DestCustomRecordsEntry + 233, // 87: lnrpc.QueryRoutesRequest.dest_custom_records:type_name -> lnrpc.QueryRoutesRequest.DestCustomRecordsEntry 150, // 88: lnrpc.QueryRoutesRequest.route_hints:type_name -> lnrpc.RouteHint 151, // 89: lnrpc.QueryRoutesRequest.blinded_payment_paths:type_name -> lnrpc.BlindedPaymentPath 10, // 90: lnrpc.QueryRoutesRequest.dest_features:type_name -> lnrpc.FeatureBit 126, // 91: lnrpc.QueryRoutesResponse.routes:type_name -> lnrpc.Route 124, // 92: lnrpc.Hop.mpp_record:type_name -> lnrpc.MPPRecord 125, // 93: lnrpc.Hop.amp_record:type_name -> lnrpc.AMPRecord - 233, // 94: lnrpc.Hop.custom_records:type_name -> lnrpc.Hop.CustomRecordsEntry + 234, // 94: lnrpc.Hop.custom_records:type_name -> lnrpc.Hop.CustomRecordsEntry 123, // 95: lnrpc.Route.hops:type_name -> lnrpc.Hop 129, // 96: lnrpc.NodeInfo.node:type_name -> lnrpc.LightningNode 132, // 97: lnrpc.NodeInfo.channels:type_name -> lnrpc.ChannelEdge 130, // 98: lnrpc.LightningNode.addresses:type_name -> lnrpc.NodeAddress - 234, // 99: lnrpc.LightningNode.features:type_name -> lnrpc.LightningNode.FeaturesEntry - 235, // 100: lnrpc.LightningNode.custom_records:type_name -> lnrpc.LightningNode.CustomRecordsEntry - 236, // 101: lnrpc.RoutingPolicy.custom_records:type_name -> lnrpc.RoutingPolicy.CustomRecordsEntry + 235, // 99: lnrpc.LightningNode.features:type_name -> lnrpc.LightningNode.FeaturesEntry + 236, // 100: lnrpc.LightningNode.custom_records:type_name -> lnrpc.LightningNode.CustomRecordsEntry + 237, // 101: lnrpc.RoutingPolicy.custom_records:type_name -> lnrpc.RoutingPolicy.CustomRecordsEntry 131, // 102: lnrpc.ChannelEdge.node1_policy:type_name -> lnrpc.RoutingPolicy 131, // 103: lnrpc.ChannelEdge.node2_policy:type_name -> lnrpc.RoutingPolicy - 237, // 104: lnrpc.ChannelEdge.custom_records:type_name -> lnrpc.ChannelEdge.CustomRecordsEntry + 238, // 104: lnrpc.ChannelEdge.custom_records:type_name -> lnrpc.ChannelEdge.CustomRecordsEntry 129, // 105: lnrpc.ChannelGraph.nodes:type_name -> lnrpc.LightningNode 132, // 106: lnrpc.ChannelGraph.edges:type_name -> lnrpc.ChannelEdge 7, // 107: lnrpc.NodeMetricsRequest.types:type_name -> lnrpc.NodeMetricType - 238, // 108: lnrpc.NodeMetricsResponse.betweenness_centrality:type_name -> lnrpc.NodeMetricsResponse.BetweennessCentralityEntry + 239, // 108: lnrpc.NodeMetricsResponse.betweenness_centrality:type_name -> lnrpc.NodeMetricsResponse.BetweennessCentralityEntry 145, // 109: lnrpc.GraphTopologyUpdate.node_updates:type_name -> lnrpc.NodeUpdate 146, // 110: lnrpc.GraphTopologyUpdate.channel_updates:type_name -> lnrpc.ChannelEdgeUpdate 147, // 111: lnrpc.GraphTopologyUpdate.closed_chans:type_name -> lnrpc.ClosedChannelUpdate 130, // 112: lnrpc.NodeUpdate.node_addresses:type_name -> lnrpc.NodeAddress - 239, // 113: lnrpc.NodeUpdate.features:type_name -> lnrpc.NodeUpdate.FeaturesEntry + 240, // 113: lnrpc.NodeUpdate.features:type_name -> lnrpc.NodeUpdate.FeaturesEntry 38, // 114: lnrpc.ChannelEdgeUpdate.chan_point:type_name -> lnrpc.ChannelPoint 131, // 115: lnrpc.ChannelEdgeUpdate.routing_policy:type_name -> lnrpc.RoutingPolicy 38, // 116: lnrpc.ClosedChannelUpdate.chan_point:type_name -> lnrpc.ChannelPoint @@ -21436,10 +21492,10 @@ var file_lightning_proto_depIdxs = []int32{ 150, // 122: lnrpc.Invoice.route_hints:type_name -> lnrpc.RouteHint 17, // 123: lnrpc.Invoice.state:type_name -> lnrpc.Invoice.InvoiceState 156, // 124: lnrpc.Invoice.htlcs:type_name -> lnrpc.InvoiceHTLC - 240, // 125: lnrpc.Invoice.features:type_name -> lnrpc.Invoice.FeaturesEntry - 241, // 126: lnrpc.Invoice.amp_invoice_state:type_name -> lnrpc.Invoice.AmpInvoiceStateEntry + 241, // 125: lnrpc.Invoice.features:type_name -> lnrpc.Invoice.FeaturesEntry + 242, // 126: lnrpc.Invoice.amp_invoice_state:type_name -> lnrpc.Invoice.AmpInvoiceStateEntry 8, // 127: lnrpc.InvoiceHTLC.state:type_name -> lnrpc.InvoiceHTLCState - 242, // 128: lnrpc.InvoiceHTLC.custom_records:type_name -> lnrpc.InvoiceHTLC.CustomRecordsEntry + 243, // 128: lnrpc.InvoiceHTLC.custom_records:type_name -> lnrpc.InvoiceHTLC.CustomRecordsEntry 157, // 129: lnrpc.InvoiceHTLC.amp:type_name -> lnrpc.AMP 155, // 130: lnrpc.ListInvoiceResponse.invoices:type_name -> lnrpc.Invoice 18, // 131: lnrpc.Payment.status:type_name -> lnrpc.Payment.PaymentStatus @@ -21447,196 +21503,197 @@ var file_lightning_proto_depIdxs = []int32{ 9, // 133: lnrpc.Payment.failure_reason:type_name -> lnrpc.PaymentFailureReason 19, // 134: lnrpc.HTLCAttempt.status:type_name -> lnrpc.HTLCAttempt.HTLCStatus 126, // 135: lnrpc.HTLCAttempt.route:type_name -> lnrpc.Route - 207, // 136: lnrpc.HTLCAttempt.failure:type_name -> lnrpc.Failure + 208, // 136: lnrpc.HTLCAttempt.failure:type_name -> lnrpc.Failure 163, // 137: lnrpc.ListPaymentsResponse.payments:type_name -> lnrpc.Payment 38, // 138: lnrpc.AbandonChannelRequest.channel_point:type_name -> lnrpc.ChannelPoint 150, // 139: lnrpc.PayReq.route_hints:type_name -> lnrpc.RouteHint - 243, // 140: lnrpc.PayReq.features:type_name -> lnrpc.PayReq.FeaturesEntry + 244, // 140: lnrpc.PayReq.features:type_name -> lnrpc.PayReq.FeaturesEntry 179, // 141: lnrpc.FeeReportResponse.channel_fees:type_name -> lnrpc.ChannelFeeReport 38, // 142: lnrpc.PolicyUpdateRequest.chan_point:type_name -> lnrpc.ChannelPoint - 39, // 143: lnrpc.FailedUpdate.outpoint:type_name -> lnrpc.OutPoint - 11, // 144: lnrpc.FailedUpdate.reason:type_name -> lnrpc.UpdateFailure - 182, // 145: lnrpc.PolicyUpdateResponse.failed_updates:type_name -> lnrpc.FailedUpdate - 185, // 146: lnrpc.ForwardingHistoryResponse.forwarding_events:type_name -> lnrpc.ForwardingEvent - 38, // 147: lnrpc.ExportChannelBackupRequest.chan_point:type_name -> lnrpc.ChannelPoint - 38, // 148: lnrpc.ChannelBackup.chan_point:type_name -> lnrpc.ChannelPoint - 38, // 149: lnrpc.MultiChanBackup.chan_points:type_name -> lnrpc.ChannelPoint - 192, // 150: lnrpc.ChanBackupSnapshot.single_chan_backups:type_name -> lnrpc.ChannelBackups - 189, // 151: lnrpc.ChanBackupSnapshot.multi_chan_backup:type_name -> lnrpc.MultiChanBackup - 188, // 152: lnrpc.ChannelBackups.chan_backups:type_name -> lnrpc.ChannelBackup - 192, // 153: lnrpc.RestoreChanBackupRequest.chan_backups:type_name -> lnrpc.ChannelBackups - 197, // 154: lnrpc.BakeMacaroonRequest.permissions:type_name -> lnrpc.MacaroonPermission - 197, // 155: lnrpc.MacaroonPermissionList.permissions:type_name -> lnrpc.MacaroonPermission - 244, // 156: lnrpc.ListPermissionsResponse.method_permissions:type_name -> lnrpc.ListPermissionsResponse.MethodPermissionsEntry - 20, // 157: lnrpc.Failure.code:type_name -> lnrpc.Failure.FailureCode - 208, // 158: lnrpc.Failure.channel_update:type_name -> lnrpc.ChannelUpdate - 210, // 159: lnrpc.MacaroonId.ops:type_name -> lnrpc.Op - 197, // 160: lnrpc.CheckMacPermRequest.permissions:type_name -> lnrpc.MacaroonPermission - 214, // 161: lnrpc.RPCMiddlewareRequest.stream_auth:type_name -> lnrpc.StreamAuth - 215, // 162: lnrpc.RPCMiddlewareRequest.request:type_name -> lnrpc.RPCMessage - 215, // 163: lnrpc.RPCMiddlewareRequest.response:type_name -> lnrpc.RPCMessage - 217, // 164: lnrpc.RPCMiddlewareResponse.register:type_name -> lnrpc.MiddlewareRegistration - 218, // 165: lnrpc.RPCMiddlewareResponse.feedback:type_name -> lnrpc.InterceptFeedback - 177, // 166: lnrpc.Peer.FeaturesEntry.value:type_name -> lnrpc.Feature - 177, // 167: lnrpc.GetInfoResponse.FeaturesEntry.value:type_name -> lnrpc.Feature - 4, // 168: lnrpc.PendingChannelsResponse.PendingChannel.initiator:type_name -> lnrpc.Initiator - 3, // 169: lnrpc.PendingChannelsResponse.PendingChannel.commitment_type:type_name -> lnrpc.CommitmentType - 225, // 170: lnrpc.PendingChannelsResponse.PendingOpenChannel.channel:type_name -> lnrpc.PendingChannelsResponse.PendingChannel - 225, // 171: lnrpc.PendingChannelsResponse.WaitingCloseChannel.channel:type_name -> lnrpc.PendingChannelsResponse.PendingChannel - 228, // 172: lnrpc.PendingChannelsResponse.WaitingCloseChannel.commitments:type_name -> lnrpc.PendingChannelsResponse.Commitments - 225, // 173: lnrpc.PendingChannelsResponse.ClosedChannel.channel:type_name -> lnrpc.PendingChannelsResponse.PendingChannel - 225, // 174: lnrpc.PendingChannelsResponse.ForceClosedChannel.channel:type_name -> lnrpc.PendingChannelsResponse.PendingChannel - 108, // 175: lnrpc.PendingChannelsResponse.ForceClosedChannel.pending_htlcs:type_name -> lnrpc.PendingHTLC - 15, // 176: lnrpc.PendingChannelsResponse.ForceClosedChannel.anchor:type_name -> lnrpc.PendingChannelsResponse.ForceClosedChannel.AnchorState - 113, // 177: lnrpc.WalletBalanceResponse.AccountBalanceEntry.value:type_name -> lnrpc.WalletAccountBalance - 177, // 178: lnrpc.LightningNode.FeaturesEntry.value:type_name -> lnrpc.Feature - 137, // 179: lnrpc.NodeMetricsResponse.BetweennessCentralityEntry.value:type_name -> lnrpc.FloatMetric - 177, // 180: lnrpc.NodeUpdate.FeaturesEntry.value:type_name -> lnrpc.Feature - 177, // 181: lnrpc.Invoice.FeaturesEntry.value:type_name -> lnrpc.Feature - 154, // 182: lnrpc.Invoice.AmpInvoiceStateEntry.value:type_name -> lnrpc.AMPInvoiceState - 177, // 183: lnrpc.PayReq.FeaturesEntry.value:type_name -> lnrpc.Feature - 204, // 184: lnrpc.ListPermissionsResponse.MethodPermissionsEntry.value:type_name -> lnrpc.MacaroonPermissionList - 114, // 185: lnrpc.Lightning.WalletBalance:input_type -> lnrpc.WalletBalanceRequest - 117, // 186: lnrpc.Lightning.ChannelBalance:input_type -> lnrpc.ChannelBalanceRequest - 30, // 187: lnrpc.Lightning.GetTransactions:input_type -> lnrpc.GetTransactionsRequest - 42, // 188: lnrpc.Lightning.EstimateFee:input_type -> lnrpc.EstimateFeeRequest - 46, // 189: lnrpc.Lightning.SendCoins:input_type -> lnrpc.SendCoinsRequest - 48, // 190: lnrpc.Lightning.ListUnspent:input_type -> lnrpc.ListUnspentRequest - 30, // 191: lnrpc.Lightning.SubscribeTransactions:input_type -> lnrpc.GetTransactionsRequest - 44, // 192: lnrpc.Lightning.SendMany:input_type -> lnrpc.SendManyRequest - 50, // 193: lnrpc.Lightning.NewAddress:input_type -> lnrpc.NewAddressRequest - 52, // 194: lnrpc.Lightning.SignMessage:input_type -> lnrpc.SignMessageRequest - 54, // 195: lnrpc.Lightning.VerifyMessage:input_type -> lnrpc.VerifyMessageRequest - 56, // 196: lnrpc.Lightning.ConnectPeer:input_type -> lnrpc.ConnectPeerRequest - 58, // 197: lnrpc.Lightning.DisconnectPeer:input_type -> lnrpc.DisconnectPeerRequest - 74, // 198: lnrpc.Lightning.ListPeers:input_type -> lnrpc.ListPeersRequest - 76, // 199: lnrpc.Lightning.SubscribePeerEvents:input_type -> lnrpc.PeerEventSubscription - 78, // 200: lnrpc.Lightning.GetInfo:input_type -> lnrpc.GetInfoRequest - 80, // 201: lnrpc.Lightning.GetDebugInfo:input_type -> lnrpc.GetDebugInfoRequest - 82, // 202: lnrpc.Lightning.GetRecoveryInfo:input_type -> lnrpc.GetRecoveryInfoRequest - 109, // 203: lnrpc.Lightning.PendingChannels:input_type -> lnrpc.PendingChannelsRequest - 63, // 204: lnrpc.Lightning.ListChannels:input_type -> lnrpc.ListChannelsRequest - 111, // 205: lnrpc.Lightning.SubscribeChannelEvents:input_type -> lnrpc.ChannelEventSubscription - 70, // 206: lnrpc.Lightning.ClosedChannels:input_type -> lnrpc.ClosedChannelsRequest - 96, // 207: lnrpc.Lightning.OpenChannelSync:input_type -> lnrpc.OpenChannelRequest - 96, // 208: lnrpc.Lightning.OpenChannel:input_type -> lnrpc.OpenChannelRequest - 93, // 209: lnrpc.Lightning.BatchOpenChannel:input_type -> lnrpc.BatchOpenChannelRequest - 106, // 210: lnrpc.Lightning.FundingStateStep:input_type -> lnrpc.FundingTransitionMsg - 37, // 211: lnrpc.Lightning.ChannelAcceptor:input_type -> lnrpc.ChannelAcceptResponse - 88, // 212: lnrpc.Lightning.CloseChannel:input_type -> lnrpc.CloseChannelRequest - 171, // 213: lnrpc.Lightning.AbandonChannel:input_type -> lnrpc.AbandonChannelRequest - 33, // 214: lnrpc.Lightning.SendPayment:input_type -> lnrpc.SendRequest - 33, // 215: lnrpc.Lightning.SendPaymentSync:input_type -> lnrpc.SendRequest - 35, // 216: lnrpc.Lightning.SendToRoute:input_type -> lnrpc.SendToRouteRequest - 35, // 217: lnrpc.Lightning.SendToRouteSync:input_type -> lnrpc.SendToRouteRequest - 155, // 218: lnrpc.Lightning.AddInvoice:input_type -> lnrpc.Invoice - 160, // 219: lnrpc.Lightning.ListInvoices:input_type -> lnrpc.ListInvoiceRequest - 159, // 220: lnrpc.Lightning.LookupInvoice:input_type -> lnrpc.PaymentHash - 162, // 221: lnrpc.Lightning.SubscribeInvoices:input_type -> lnrpc.InvoiceSubscription - 175, // 222: lnrpc.Lightning.DecodePayReq:input_type -> lnrpc.PayReqString - 165, // 223: lnrpc.Lightning.ListPayments:input_type -> lnrpc.ListPaymentsRequest - 167, // 224: lnrpc.Lightning.DeletePayment:input_type -> lnrpc.DeletePaymentRequest - 168, // 225: lnrpc.Lightning.DeleteAllPayments:input_type -> lnrpc.DeleteAllPaymentsRequest - 133, // 226: lnrpc.Lightning.DescribeGraph:input_type -> lnrpc.ChannelGraphRequest - 135, // 227: lnrpc.Lightning.GetNodeMetrics:input_type -> lnrpc.NodeMetricsRequest - 138, // 228: lnrpc.Lightning.GetChanInfo:input_type -> lnrpc.ChanInfoRequest - 127, // 229: lnrpc.Lightning.GetNodeInfo:input_type -> lnrpc.NodeInfoRequest - 119, // 230: lnrpc.Lightning.QueryRoutes:input_type -> lnrpc.QueryRoutesRequest - 139, // 231: lnrpc.Lightning.GetNetworkInfo:input_type -> lnrpc.NetworkInfoRequest - 141, // 232: lnrpc.Lightning.StopDaemon:input_type -> lnrpc.StopRequest - 143, // 233: lnrpc.Lightning.SubscribeChannelGraph:input_type -> lnrpc.GraphTopologySubscription - 173, // 234: lnrpc.Lightning.DebugLevel:input_type -> lnrpc.DebugLevelRequest - 178, // 235: lnrpc.Lightning.FeeReport:input_type -> lnrpc.FeeReportRequest - 181, // 236: lnrpc.Lightning.UpdateChannelPolicy:input_type -> lnrpc.PolicyUpdateRequest - 184, // 237: lnrpc.Lightning.ForwardingHistory:input_type -> lnrpc.ForwardingHistoryRequest - 187, // 238: lnrpc.Lightning.ExportChannelBackup:input_type -> lnrpc.ExportChannelBackupRequest - 190, // 239: lnrpc.Lightning.ExportAllChannelBackups:input_type -> lnrpc.ChanBackupExportRequest - 191, // 240: lnrpc.Lightning.VerifyChanBackup:input_type -> lnrpc.ChanBackupSnapshot - 193, // 241: lnrpc.Lightning.RestoreChannelBackups:input_type -> lnrpc.RestoreChanBackupRequest - 195, // 242: lnrpc.Lightning.SubscribeChannelBackups:input_type -> lnrpc.ChannelBackupSubscription - 198, // 243: lnrpc.Lightning.BakeMacaroon:input_type -> lnrpc.BakeMacaroonRequest - 200, // 244: lnrpc.Lightning.ListMacaroonIDs:input_type -> lnrpc.ListMacaroonIDsRequest - 202, // 245: lnrpc.Lightning.DeleteMacaroonID:input_type -> lnrpc.DeleteMacaroonIDRequest - 205, // 246: lnrpc.Lightning.ListPermissions:input_type -> lnrpc.ListPermissionsRequest - 211, // 247: lnrpc.Lightning.CheckMacaroonPermissions:input_type -> lnrpc.CheckMacPermRequest - 216, // 248: lnrpc.Lightning.RegisterRPCMiddleware:input_type -> lnrpc.RPCMiddlewareResponse - 25, // 249: lnrpc.Lightning.SendCustomMessage:input_type -> lnrpc.SendCustomMessageRequest - 23, // 250: lnrpc.Lightning.SubscribeCustomMessages:input_type -> lnrpc.SubscribeCustomMessagesRequest - 66, // 251: lnrpc.Lightning.ListAliases:input_type -> lnrpc.ListAliasesRequest - 21, // 252: lnrpc.Lightning.LookupHtlcResolution:input_type -> lnrpc.LookupHtlcResolutionRequest - 115, // 253: lnrpc.Lightning.WalletBalance:output_type -> lnrpc.WalletBalanceResponse - 118, // 254: lnrpc.Lightning.ChannelBalance:output_type -> lnrpc.ChannelBalanceResponse - 31, // 255: lnrpc.Lightning.GetTransactions:output_type -> lnrpc.TransactionDetails - 43, // 256: lnrpc.Lightning.EstimateFee:output_type -> lnrpc.EstimateFeeResponse - 47, // 257: lnrpc.Lightning.SendCoins:output_type -> lnrpc.SendCoinsResponse - 49, // 258: lnrpc.Lightning.ListUnspent:output_type -> lnrpc.ListUnspentResponse - 29, // 259: lnrpc.Lightning.SubscribeTransactions:output_type -> lnrpc.Transaction - 45, // 260: lnrpc.Lightning.SendMany:output_type -> lnrpc.SendManyResponse - 51, // 261: lnrpc.Lightning.NewAddress:output_type -> lnrpc.NewAddressResponse - 53, // 262: lnrpc.Lightning.SignMessage:output_type -> lnrpc.SignMessageResponse - 55, // 263: lnrpc.Lightning.VerifyMessage:output_type -> lnrpc.VerifyMessageResponse - 57, // 264: lnrpc.Lightning.ConnectPeer:output_type -> lnrpc.ConnectPeerResponse - 59, // 265: lnrpc.Lightning.DisconnectPeer:output_type -> lnrpc.DisconnectPeerResponse - 75, // 266: lnrpc.Lightning.ListPeers:output_type -> lnrpc.ListPeersResponse - 77, // 267: lnrpc.Lightning.SubscribePeerEvents:output_type -> lnrpc.PeerEvent - 79, // 268: lnrpc.Lightning.GetInfo:output_type -> lnrpc.GetInfoResponse - 81, // 269: lnrpc.Lightning.GetDebugInfo:output_type -> lnrpc.GetDebugInfoResponse - 83, // 270: lnrpc.Lightning.GetRecoveryInfo:output_type -> lnrpc.GetRecoveryInfoResponse - 110, // 271: lnrpc.Lightning.PendingChannels:output_type -> lnrpc.PendingChannelsResponse - 64, // 272: lnrpc.Lightning.ListChannels:output_type -> lnrpc.ListChannelsResponse - 112, // 273: lnrpc.Lightning.SubscribeChannelEvents:output_type -> lnrpc.ChannelEventUpdate - 71, // 274: lnrpc.Lightning.ClosedChannels:output_type -> lnrpc.ClosedChannelsResponse - 38, // 275: lnrpc.Lightning.OpenChannelSync:output_type -> lnrpc.ChannelPoint - 97, // 276: lnrpc.Lightning.OpenChannel:output_type -> lnrpc.OpenStatusUpdate - 95, // 277: lnrpc.Lightning.BatchOpenChannel:output_type -> lnrpc.BatchOpenChannelResponse - 107, // 278: lnrpc.Lightning.FundingStateStep:output_type -> lnrpc.FundingStateStepResp - 36, // 279: lnrpc.Lightning.ChannelAcceptor:output_type -> lnrpc.ChannelAcceptRequest - 89, // 280: lnrpc.Lightning.CloseChannel:output_type -> lnrpc.CloseStatusUpdate - 172, // 281: lnrpc.Lightning.AbandonChannel:output_type -> lnrpc.AbandonChannelResponse - 34, // 282: lnrpc.Lightning.SendPayment:output_type -> lnrpc.SendResponse - 34, // 283: lnrpc.Lightning.SendPaymentSync:output_type -> lnrpc.SendResponse - 34, // 284: lnrpc.Lightning.SendToRoute:output_type -> lnrpc.SendResponse - 34, // 285: lnrpc.Lightning.SendToRouteSync:output_type -> lnrpc.SendResponse - 158, // 286: lnrpc.Lightning.AddInvoice:output_type -> lnrpc.AddInvoiceResponse - 161, // 287: lnrpc.Lightning.ListInvoices:output_type -> lnrpc.ListInvoiceResponse - 155, // 288: lnrpc.Lightning.LookupInvoice:output_type -> lnrpc.Invoice - 155, // 289: lnrpc.Lightning.SubscribeInvoices:output_type -> lnrpc.Invoice - 176, // 290: lnrpc.Lightning.DecodePayReq:output_type -> lnrpc.PayReq - 166, // 291: lnrpc.Lightning.ListPayments:output_type -> lnrpc.ListPaymentsResponse - 169, // 292: lnrpc.Lightning.DeletePayment:output_type -> lnrpc.DeletePaymentResponse - 170, // 293: lnrpc.Lightning.DeleteAllPayments:output_type -> lnrpc.DeleteAllPaymentsResponse - 134, // 294: lnrpc.Lightning.DescribeGraph:output_type -> lnrpc.ChannelGraph - 136, // 295: lnrpc.Lightning.GetNodeMetrics:output_type -> lnrpc.NodeMetricsResponse - 132, // 296: lnrpc.Lightning.GetChanInfo:output_type -> lnrpc.ChannelEdge - 128, // 297: lnrpc.Lightning.GetNodeInfo:output_type -> lnrpc.NodeInfo - 122, // 298: lnrpc.Lightning.QueryRoutes:output_type -> lnrpc.QueryRoutesResponse - 140, // 299: lnrpc.Lightning.GetNetworkInfo:output_type -> lnrpc.NetworkInfo - 142, // 300: lnrpc.Lightning.StopDaemon:output_type -> lnrpc.StopResponse - 144, // 301: lnrpc.Lightning.SubscribeChannelGraph:output_type -> lnrpc.GraphTopologyUpdate - 174, // 302: lnrpc.Lightning.DebugLevel:output_type -> lnrpc.DebugLevelResponse - 180, // 303: lnrpc.Lightning.FeeReport:output_type -> lnrpc.FeeReportResponse - 183, // 304: lnrpc.Lightning.UpdateChannelPolicy:output_type -> lnrpc.PolicyUpdateResponse - 186, // 305: lnrpc.Lightning.ForwardingHistory:output_type -> lnrpc.ForwardingHistoryResponse - 188, // 306: lnrpc.Lightning.ExportChannelBackup:output_type -> lnrpc.ChannelBackup - 191, // 307: lnrpc.Lightning.ExportAllChannelBackups:output_type -> lnrpc.ChanBackupSnapshot - 196, // 308: lnrpc.Lightning.VerifyChanBackup:output_type -> lnrpc.VerifyChanBackupResponse - 194, // 309: lnrpc.Lightning.RestoreChannelBackups:output_type -> lnrpc.RestoreBackupResponse - 191, // 310: lnrpc.Lightning.SubscribeChannelBackups:output_type -> lnrpc.ChanBackupSnapshot - 199, // 311: lnrpc.Lightning.BakeMacaroon:output_type -> lnrpc.BakeMacaroonResponse - 201, // 312: lnrpc.Lightning.ListMacaroonIDs:output_type -> lnrpc.ListMacaroonIDsResponse - 203, // 313: lnrpc.Lightning.DeleteMacaroonID:output_type -> lnrpc.DeleteMacaroonIDResponse - 206, // 314: lnrpc.Lightning.ListPermissions:output_type -> lnrpc.ListPermissionsResponse - 212, // 315: lnrpc.Lightning.CheckMacaroonPermissions:output_type -> lnrpc.CheckMacPermResponse - 213, // 316: lnrpc.Lightning.RegisterRPCMiddleware:output_type -> lnrpc.RPCMiddlewareRequest - 26, // 317: lnrpc.Lightning.SendCustomMessage:output_type -> lnrpc.SendCustomMessageResponse - 24, // 318: lnrpc.Lightning.SubscribeCustomMessages:output_type -> lnrpc.CustomMessage - 67, // 319: lnrpc.Lightning.ListAliases:output_type -> lnrpc.ListAliasesResponse - 22, // 320: lnrpc.Lightning.LookupHtlcResolution:output_type -> lnrpc.LookupHtlcResolutionResponse - 253, // [253:321] is the sub-list for method output_type - 185, // [185:253] is the sub-list for method input_type - 185, // [185:185] is the sub-list for extension type_name - 185, // [185:185] is the sub-list for extension extendee - 0, // [0:185] is the sub-list for field type_name + 181, // 143: lnrpc.PolicyUpdateRequest.inbound_fee:type_name -> lnrpc.InboundFee + 39, // 144: lnrpc.FailedUpdate.outpoint:type_name -> lnrpc.OutPoint + 11, // 145: lnrpc.FailedUpdate.reason:type_name -> lnrpc.UpdateFailure + 183, // 146: lnrpc.PolicyUpdateResponse.failed_updates:type_name -> lnrpc.FailedUpdate + 186, // 147: lnrpc.ForwardingHistoryResponse.forwarding_events:type_name -> lnrpc.ForwardingEvent + 38, // 148: lnrpc.ExportChannelBackupRequest.chan_point:type_name -> lnrpc.ChannelPoint + 38, // 149: lnrpc.ChannelBackup.chan_point:type_name -> lnrpc.ChannelPoint + 38, // 150: lnrpc.MultiChanBackup.chan_points:type_name -> lnrpc.ChannelPoint + 193, // 151: lnrpc.ChanBackupSnapshot.single_chan_backups:type_name -> lnrpc.ChannelBackups + 190, // 152: lnrpc.ChanBackupSnapshot.multi_chan_backup:type_name -> lnrpc.MultiChanBackup + 189, // 153: lnrpc.ChannelBackups.chan_backups:type_name -> lnrpc.ChannelBackup + 193, // 154: lnrpc.RestoreChanBackupRequest.chan_backups:type_name -> lnrpc.ChannelBackups + 198, // 155: lnrpc.BakeMacaroonRequest.permissions:type_name -> lnrpc.MacaroonPermission + 198, // 156: lnrpc.MacaroonPermissionList.permissions:type_name -> lnrpc.MacaroonPermission + 245, // 157: lnrpc.ListPermissionsResponse.method_permissions:type_name -> lnrpc.ListPermissionsResponse.MethodPermissionsEntry + 20, // 158: lnrpc.Failure.code:type_name -> lnrpc.Failure.FailureCode + 209, // 159: lnrpc.Failure.channel_update:type_name -> lnrpc.ChannelUpdate + 211, // 160: lnrpc.MacaroonId.ops:type_name -> lnrpc.Op + 198, // 161: lnrpc.CheckMacPermRequest.permissions:type_name -> lnrpc.MacaroonPermission + 215, // 162: lnrpc.RPCMiddlewareRequest.stream_auth:type_name -> lnrpc.StreamAuth + 216, // 163: lnrpc.RPCMiddlewareRequest.request:type_name -> lnrpc.RPCMessage + 216, // 164: lnrpc.RPCMiddlewareRequest.response:type_name -> lnrpc.RPCMessage + 218, // 165: lnrpc.RPCMiddlewareResponse.register:type_name -> lnrpc.MiddlewareRegistration + 219, // 166: lnrpc.RPCMiddlewareResponse.feedback:type_name -> lnrpc.InterceptFeedback + 177, // 167: lnrpc.Peer.FeaturesEntry.value:type_name -> lnrpc.Feature + 177, // 168: lnrpc.GetInfoResponse.FeaturesEntry.value:type_name -> lnrpc.Feature + 4, // 169: lnrpc.PendingChannelsResponse.PendingChannel.initiator:type_name -> lnrpc.Initiator + 3, // 170: lnrpc.PendingChannelsResponse.PendingChannel.commitment_type:type_name -> lnrpc.CommitmentType + 226, // 171: lnrpc.PendingChannelsResponse.PendingOpenChannel.channel:type_name -> lnrpc.PendingChannelsResponse.PendingChannel + 226, // 172: lnrpc.PendingChannelsResponse.WaitingCloseChannel.channel:type_name -> lnrpc.PendingChannelsResponse.PendingChannel + 229, // 173: lnrpc.PendingChannelsResponse.WaitingCloseChannel.commitments:type_name -> lnrpc.PendingChannelsResponse.Commitments + 226, // 174: lnrpc.PendingChannelsResponse.ClosedChannel.channel:type_name -> lnrpc.PendingChannelsResponse.PendingChannel + 226, // 175: lnrpc.PendingChannelsResponse.ForceClosedChannel.channel:type_name -> lnrpc.PendingChannelsResponse.PendingChannel + 108, // 176: lnrpc.PendingChannelsResponse.ForceClosedChannel.pending_htlcs:type_name -> lnrpc.PendingHTLC + 15, // 177: lnrpc.PendingChannelsResponse.ForceClosedChannel.anchor:type_name -> lnrpc.PendingChannelsResponse.ForceClosedChannel.AnchorState + 113, // 178: lnrpc.WalletBalanceResponse.AccountBalanceEntry.value:type_name -> lnrpc.WalletAccountBalance + 177, // 179: lnrpc.LightningNode.FeaturesEntry.value:type_name -> lnrpc.Feature + 137, // 180: lnrpc.NodeMetricsResponse.BetweennessCentralityEntry.value:type_name -> lnrpc.FloatMetric + 177, // 181: lnrpc.NodeUpdate.FeaturesEntry.value:type_name -> lnrpc.Feature + 177, // 182: lnrpc.Invoice.FeaturesEntry.value:type_name -> lnrpc.Feature + 154, // 183: lnrpc.Invoice.AmpInvoiceStateEntry.value:type_name -> lnrpc.AMPInvoiceState + 177, // 184: lnrpc.PayReq.FeaturesEntry.value:type_name -> lnrpc.Feature + 205, // 185: lnrpc.ListPermissionsResponse.MethodPermissionsEntry.value:type_name -> lnrpc.MacaroonPermissionList + 114, // 186: lnrpc.Lightning.WalletBalance:input_type -> lnrpc.WalletBalanceRequest + 117, // 187: lnrpc.Lightning.ChannelBalance:input_type -> lnrpc.ChannelBalanceRequest + 30, // 188: lnrpc.Lightning.GetTransactions:input_type -> lnrpc.GetTransactionsRequest + 42, // 189: lnrpc.Lightning.EstimateFee:input_type -> lnrpc.EstimateFeeRequest + 46, // 190: lnrpc.Lightning.SendCoins:input_type -> lnrpc.SendCoinsRequest + 48, // 191: lnrpc.Lightning.ListUnspent:input_type -> lnrpc.ListUnspentRequest + 30, // 192: lnrpc.Lightning.SubscribeTransactions:input_type -> lnrpc.GetTransactionsRequest + 44, // 193: lnrpc.Lightning.SendMany:input_type -> lnrpc.SendManyRequest + 50, // 194: lnrpc.Lightning.NewAddress:input_type -> lnrpc.NewAddressRequest + 52, // 195: lnrpc.Lightning.SignMessage:input_type -> lnrpc.SignMessageRequest + 54, // 196: lnrpc.Lightning.VerifyMessage:input_type -> lnrpc.VerifyMessageRequest + 56, // 197: lnrpc.Lightning.ConnectPeer:input_type -> lnrpc.ConnectPeerRequest + 58, // 198: lnrpc.Lightning.DisconnectPeer:input_type -> lnrpc.DisconnectPeerRequest + 74, // 199: lnrpc.Lightning.ListPeers:input_type -> lnrpc.ListPeersRequest + 76, // 200: lnrpc.Lightning.SubscribePeerEvents:input_type -> lnrpc.PeerEventSubscription + 78, // 201: lnrpc.Lightning.GetInfo:input_type -> lnrpc.GetInfoRequest + 80, // 202: lnrpc.Lightning.GetDebugInfo:input_type -> lnrpc.GetDebugInfoRequest + 82, // 203: lnrpc.Lightning.GetRecoveryInfo:input_type -> lnrpc.GetRecoveryInfoRequest + 109, // 204: lnrpc.Lightning.PendingChannels:input_type -> lnrpc.PendingChannelsRequest + 63, // 205: lnrpc.Lightning.ListChannels:input_type -> lnrpc.ListChannelsRequest + 111, // 206: lnrpc.Lightning.SubscribeChannelEvents:input_type -> lnrpc.ChannelEventSubscription + 70, // 207: lnrpc.Lightning.ClosedChannels:input_type -> lnrpc.ClosedChannelsRequest + 96, // 208: lnrpc.Lightning.OpenChannelSync:input_type -> lnrpc.OpenChannelRequest + 96, // 209: lnrpc.Lightning.OpenChannel:input_type -> lnrpc.OpenChannelRequest + 93, // 210: lnrpc.Lightning.BatchOpenChannel:input_type -> lnrpc.BatchOpenChannelRequest + 106, // 211: lnrpc.Lightning.FundingStateStep:input_type -> lnrpc.FundingTransitionMsg + 37, // 212: lnrpc.Lightning.ChannelAcceptor:input_type -> lnrpc.ChannelAcceptResponse + 88, // 213: lnrpc.Lightning.CloseChannel:input_type -> lnrpc.CloseChannelRequest + 171, // 214: lnrpc.Lightning.AbandonChannel:input_type -> lnrpc.AbandonChannelRequest + 33, // 215: lnrpc.Lightning.SendPayment:input_type -> lnrpc.SendRequest + 33, // 216: lnrpc.Lightning.SendPaymentSync:input_type -> lnrpc.SendRequest + 35, // 217: lnrpc.Lightning.SendToRoute:input_type -> lnrpc.SendToRouteRequest + 35, // 218: lnrpc.Lightning.SendToRouteSync:input_type -> lnrpc.SendToRouteRequest + 155, // 219: lnrpc.Lightning.AddInvoice:input_type -> lnrpc.Invoice + 160, // 220: lnrpc.Lightning.ListInvoices:input_type -> lnrpc.ListInvoiceRequest + 159, // 221: lnrpc.Lightning.LookupInvoice:input_type -> lnrpc.PaymentHash + 162, // 222: lnrpc.Lightning.SubscribeInvoices:input_type -> lnrpc.InvoiceSubscription + 175, // 223: lnrpc.Lightning.DecodePayReq:input_type -> lnrpc.PayReqString + 165, // 224: lnrpc.Lightning.ListPayments:input_type -> lnrpc.ListPaymentsRequest + 167, // 225: lnrpc.Lightning.DeletePayment:input_type -> lnrpc.DeletePaymentRequest + 168, // 226: lnrpc.Lightning.DeleteAllPayments:input_type -> lnrpc.DeleteAllPaymentsRequest + 133, // 227: lnrpc.Lightning.DescribeGraph:input_type -> lnrpc.ChannelGraphRequest + 135, // 228: lnrpc.Lightning.GetNodeMetrics:input_type -> lnrpc.NodeMetricsRequest + 138, // 229: lnrpc.Lightning.GetChanInfo:input_type -> lnrpc.ChanInfoRequest + 127, // 230: lnrpc.Lightning.GetNodeInfo:input_type -> lnrpc.NodeInfoRequest + 119, // 231: lnrpc.Lightning.QueryRoutes:input_type -> lnrpc.QueryRoutesRequest + 139, // 232: lnrpc.Lightning.GetNetworkInfo:input_type -> lnrpc.NetworkInfoRequest + 141, // 233: lnrpc.Lightning.StopDaemon:input_type -> lnrpc.StopRequest + 143, // 234: lnrpc.Lightning.SubscribeChannelGraph:input_type -> lnrpc.GraphTopologySubscription + 173, // 235: lnrpc.Lightning.DebugLevel:input_type -> lnrpc.DebugLevelRequest + 178, // 236: lnrpc.Lightning.FeeReport:input_type -> lnrpc.FeeReportRequest + 182, // 237: lnrpc.Lightning.UpdateChannelPolicy:input_type -> lnrpc.PolicyUpdateRequest + 185, // 238: lnrpc.Lightning.ForwardingHistory:input_type -> lnrpc.ForwardingHistoryRequest + 188, // 239: lnrpc.Lightning.ExportChannelBackup:input_type -> lnrpc.ExportChannelBackupRequest + 191, // 240: lnrpc.Lightning.ExportAllChannelBackups:input_type -> lnrpc.ChanBackupExportRequest + 192, // 241: lnrpc.Lightning.VerifyChanBackup:input_type -> lnrpc.ChanBackupSnapshot + 194, // 242: lnrpc.Lightning.RestoreChannelBackups:input_type -> lnrpc.RestoreChanBackupRequest + 196, // 243: lnrpc.Lightning.SubscribeChannelBackups:input_type -> lnrpc.ChannelBackupSubscription + 199, // 244: lnrpc.Lightning.BakeMacaroon:input_type -> lnrpc.BakeMacaroonRequest + 201, // 245: lnrpc.Lightning.ListMacaroonIDs:input_type -> lnrpc.ListMacaroonIDsRequest + 203, // 246: lnrpc.Lightning.DeleteMacaroonID:input_type -> lnrpc.DeleteMacaroonIDRequest + 206, // 247: lnrpc.Lightning.ListPermissions:input_type -> lnrpc.ListPermissionsRequest + 212, // 248: lnrpc.Lightning.CheckMacaroonPermissions:input_type -> lnrpc.CheckMacPermRequest + 217, // 249: lnrpc.Lightning.RegisterRPCMiddleware:input_type -> lnrpc.RPCMiddlewareResponse + 25, // 250: lnrpc.Lightning.SendCustomMessage:input_type -> lnrpc.SendCustomMessageRequest + 23, // 251: lnrpc.Lightning.SubscribeCustomMessages:input_type -> lnrpc.SubscribeCustomMessagesRequest + 66, // 252: lnrpc.Lightning.ListAliases:input_type -> lnrpc.ListAliasesRequest + 21, // 253: lnrpc.Lightning.LookupHtlcResolution:input_type -> lnrpc.LookupHtlcResolutionRequest + 115, // 254: lnrpc.Lightning.WalletBalance:output_type -> lnrpc.WalletBalanceResponse + 118, // 255: lnrpc.Lightning.ChannelBalance:output_type -> lnrpc.ChannelBalanceResponse + 31, // 256: lnrpc.Lightning.GetTransactions:output_type -> lnrpc.TransactionDetails + 43, // 257: lnrpc.Lightning.EstimateFee:output_type -> lnrpc.EstimateFeeResponse + 47, // 258: lnrpc.Lightning.SendCoins:output_type -> lnrpc.SendCoinsResponse + 49, // 259: lnrpc.Lightning.ListUnspent:output_type -> lnrpc.ListUnspentResponse + 29, // 260: lnrpc.Lightning.SubscribeTransactions:output_type -> lnrpc.Transaction + 45, // 261: lnrpc.Lightning.SendMany:output_type -> lnrpc.SendManyResponse + 51, // 262: lnrpc.Lightning.NewAddress:output_type -> lnrpc.NewAddressResponse + 53, // 263: lnrpc.Lightning.SignMessage:output_type -> lnrpc.SignMessageResponse + 55, // 264: lnrpc.Lightning.VerifyMessage:output_type -> lnrpc.VerifyMessageResponse + 57, // 265: lnrpc.Lightning.ConnectPeer:output_type -> lnrpc.ConnectPeerResponse + 59, // 266: lnrpc.Lightning.DisconnectPeer:output_type -> lnrpc.DisconnectPeerResponse + 75, // 267: lnrpc.Lightning.ListPeers:output_type -> lnrpc.ListPeersResponse + 77, // 268: lnrpc.Lightning.SubscribePeerEvents:output_type -> lnrpc.PeerEvent + 79, // 269: lnrpc.Lightning.GetInfo:output_type -> lnrpc.GetInfoResponse + 81, // 270: lnrpc.Lightning.GetDebugInfo:output_type -> lnrpc.GetDebugInfoResponse + 83, // 271: lnrpc.Lightning.GetRecoveryInfo:output_type -> lnrpc.GetRecoveryInfoResponse + 110, // 272: lnrpc.Lightning.PendingChannels:output_type -> lnrpc.PendingChannelsResponse + 64, // 273: lnrpc.Lightning.ListChannels:output_type -> lnrpc.ListChannelsResponse + 112, // 274: lnrpc.Lightning.SubscribeChannelEvents:output_type -> lnrpc.ChannelEventUpdate + 71, // 275: lnrpc.Lightning.ClosedChannels:output_type -> lnrpc.ClosedChannelsResponse + 38, // 276: lnrpc.Lightning.OpenChannelSync:output_type -> lnrpc.ChannelPoint + 97, // 277: lnrpc.Lightning.OpenChannel:output_type -> lnrpc.OpenStatusUpdate + 95, // 278: lnrpc.Lightning.BatchOpenChannel:output_type -> lnrpc.BatchOpenChannelResponse + 107, // 279: lnrpc.Lightning.FundingStateStep:output_type -> lnrpc.FundingStateStepResp + 36, // 280: lnrpc.Lightning.ChannelAcceptor:output_type -> lnrpc.ChannelAcceptRequest + 89, // 281: lnrpc.Lightning.CloseChannel:output_type -> lnrpc.CloseStatusUpdate + 172, // 282: lnrpc.Lightning.AbandonChannel:output_type -> lnrpc.AbandonChannelResponse + 34, // 283: lnrpc.Lightning.SendPayment:output_type -> lnrpc.SendResponse + 34, // 284: lnrpc.Lightning.SendPaymentSync:output_type -> lnrpc.SendResponse + 34, // 285: lnrpc.Lightning.SendToRoute:output_type -> lnrpc.SendResponse + 34, // 286: lnrpc.Lightning.SendToRouteSync:output_type -> lnrpc.SendResponse + 158, // 287: lnrpc.Lightning.AddInvoice:output_type -> lnrpc.AddInvoiceResponse + 161, // 288: lnrpc.Lightning.ListInvoices:output_type -> lnrpc.ListInvoiceResponse + 155, // 289: lnrpc.Lightning.LookupInvoice:output_type -> lnrpc.Invoice + 155, // 290: lnrpc.Lightning.SubscribeInvoices:output_type -> lnrpc.Invoice + 176, // 291: lnrpc.Lightning.DecodePayReq:output_type -> lnrpc.PayReq + 166, // 292: lnrpc.Lightning.ListPayments:output_type -> lnrpc.ListPaymentsResponse + 169, // 293: lnrpc.Lightning.DeletePayment:output_type -> lnrpc.DeletePaymentResponse + 170, // 294: lnrpc.Lightning.DeleteAllPayments:output_type -> lnrpc.DeleteAllPaymentsResponse + 134, // 295: lnrpc.Lightning.DescribeGraph:output_type -> lnrpc.ChannelGraph + 136, // 296: lnrpc.Lightning.GetNodeMetrics:output_type -> lnrpc.NodeMetricsResponse + 132, // 297: lnrpc.Lightning.GetChanInfo:output_type -> lnrpc.ChannelEdge + 128, // 298: lnrpc.Lightning.GetNodeInfo:output_type -> lnrpc.NodeInfo + 122, // 299: lnrpc.Lightning.QueryRoutes:output_type -> lnrpc.QueryRoutesResponse + 140, // 300: lnrpc.Lightning.GetNetworkInfo:output_type -> lnrpc.NetworkInfo + 142, // 301: lnrpc.Lightning.StopDaemon:output_type -> lnrpc.StopResponse + 144, // 302: lnrpc.Lightning.SubscribeChannelGraph:output_type -> lnrpc.GraphTopologyUpdate + 174, // 303: lnrpc.Lightning.DebugLevel:output_type -> lnrpc.DebugLevelResponse + 180, // 304: lnrpc.Lightning.FeeReport:output_type -> lnrpc.FeeReportResponse + 184, // 305: lnrpc.Lightning.UpdateChannelPolicy:output_type -> lnrpc.PolicyUpdateResponse + 187, // 306: lnrpc.Lightning.ForwardingHistory:output_type -> lnrpc.ForwardingHistoryResponse + 189, // 307: lnrpc.Lightning.ExportChannelBackup:output_type -> lnrpc.ChannelBackup + 192, // 308: lnrpc.Lightning.ExportAllChannelBackups:output_type -> lnrpc.ChanBackupSnapshot + 197, // 309: lnrpc.Lightning.VerifyChanBackup:output_type -> lnrpc.VerifyChanBackupResponse + 195, // 310: lnrpc.Lightning.RestoreChannelBackups:output_type -> lnrpc.RestoreBackupResponse + 192, // 311: lnrpc.Lightning.SubscribeChannelBackups:output_type -> lnrpc.ChanBackupSnapshot + 200, // 312: lnrpc.Lightning.BakeMacaroon:output_type -> lnrpc.BakeMacaroonResponse + 202, // 313: lnrpc.Lightning.ListMacaroonIDs:output_type -> lnrpc.ListMacaroonIDsResponse + 204, // 314: lnrpc.Lightning.DeleteMacaroonID:output_type -> lnrpc.DeleteMacaroonIDResponse + 207, // 315: lnrpc.Lightning.ListPermissions:output_type -> lnrpc.ListPermissionsResponse + 213, // 316: lnrpc.Lightning.CheckMacaroonPermissions:output_type -> lnrpc.CheckMacPermResponse + 214, // 317: lnrpc.Lightning.RegisterRPCMiddleware:output_type -> lnrpc.RPCMiddlewareRequest + 26, // 318: lnrpc.Lightning.SendCustomMessage:output_type -> lnrpc.SendCustomMessageResponse + 24, // 319: lnrpc.Lightning.SubscribeCustomMessages:output_type -> lnrpc.CustomMessage + 67, // 320: lnrpc.Lightning.ListAliases:output_type -> lnrpc.ListAliasesResponse + 22, // 321: lnrpc.Lightning.LookupHtlcResolution:output_type -> lnrpc.LookupHtlcResolutionResponse + 254, // [254:322] is the sub-list for method output_type + 186, // [186:254] is the sub-list for method input_type + 186, // [186:186] is the sub-list for extension type_name + 186, // [186:186] is the sub-list for extension extendee + 0, // [0:186] is the sub-list for field type_name } func init() { file_lightning_proto_init() } @@ -23566,7 +23623,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[160].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PolicyUpdateRequest); i { + switch v := v.(*InboundFee); i { case 0: return &v.state case 1: @@ -23578,7 +23635,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[161].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FailedUpdate); i { + switch v := v.(*PolicyUpdateRequest); i { case 0: return &v.state case 1: @@ -23590,7 +23647,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[162].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PolicyUpdateResponse); i { + switch v := v.(*FailedUpdate); i { case 0: return &v.state case 1: @@ -23602,7 +23659,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[163].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ForwardingHistoryRequest); i { + switch v := v.(*PolicyUpdateResponse); i { case 0: return &v.state case 1: @@ -23614,7 +23671,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[164].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ForwardingEvent); i { + switch v := v.(*ForwardingHistoryRequest); i { case 0: return &v.state case 1: @@ -23626,7 +23683,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[165].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ForwardingHistoryResponse); i { + switch v := v.(*ForwardingEvent); i { case 0: return &v.state case 1: @@ -23638,7 +23695,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[166].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ExportChannelBackupRequest); i { + switch v := v.(*ForwardingHistoryResponse); i { case 0: return &v.state case 1: @@ -23650,7 +23707,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[167].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ChannelBackup); i { + switch v := v.(*ExportChannelBackupRequest); i { case 0: return &v.state case 1: @@ -23662,7 +23719,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[168].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MultiChanBackup); i { + switch v := v.(*ChannelBackup); i { case 0: return &v.state case 1: @@ -23674,7 +23731,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[169].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ChanBackupExportRequest); i { + switch v := v.(*MultiChanBackup); i { case 0: return &v.state case 1: @@ -23686,7 +23743,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[170].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ChanBackupSnapshot); i { + switch v := v.(*ChanBackupExportRequest); i { case 0: return &v.state case 1: @@ -23698,7 +23755,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[171].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ChannelBackups); i { + switch v := v.(*ChanBackupSnapshot); i { case 0: return &v.state case 1: @@ -23710,7 +23767,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[172].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RestoreChanBackupRequest); i { + switch v := v.(*ChannelBackups); i { case 0: return &v.state case 1: @@ -23722,7 +23779,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[173].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RestoreBackupResponse); i { + switch v := v.(*RestoreChanBackupRequest); i { case 0: return &v.state case 1: @@ -23734,7 +23791,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[174].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ChannelBackupSubscription); i { + switch v := v.(*RestoreBackupResponse); i { case 0: return &v.state case 1: @@ -23746,7 +23803,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[175].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*VerifyChanBackupResponse); i { + switch v := v.(*ChannelBackupSubscription); i { case 0: return &v.state case 1: @@ -23758,7 +23815,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[176].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MacaroonPermission); i { + switch v := v.(*VerifyChanBackupResponse); i { case 0: return &v.state case 1: @@ -23770,7 +23827,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[177].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BakeMacaroonRequest); i { + switch v := v.(*MacaroonPermission); i { case 0: return &v.state case 1: @@ -23782,7 +23839,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[178].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BakeMacaroonResponse); i { + switch v := v.(*BakeMacaroonRequest); i { case 0: return &v.state case 1: @@ -23794,7 +23851,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[179].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListMacaroonIDsRequest); i { + switch v := v.(*BakeMacaroonResponse); i { case 0: return &v.state case 1: @@ -23806,7 +23863,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[180].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListMacaroonIDsResponse); i { + switch v := v.(*ListMacaroonIDsRequest); i { case 0: return &v.state case 1: @@ -23818,7 +23875,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[181].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeleteMacaroonIDRequest); i { + switch v := v.(*ListMacaroonIDsResponse); i { case 0: return &v.state case 1: @@ -23830,7 +23887,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[182].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeleteMacaroonIDResponse); i { + switch v := v.(*DeleteMacaroonIDRequest); i { case 0: return &v.state case 1: @@ -23842,7 +23899,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[183].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MacaroonPermissionList); i { + switch v := v.(*DeleteMacaroonIDResponse); i { case 0: return &v.state case 1: @@ -23854,7 +23911,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[184].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListPermissionsRequest); i { + switch v := v.(*MacaroonPermissionList); i { case 0: return &v.state case 1: @@ -23866,7 +23923,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[185].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListPermissionsResponse); i { + switch v := v.(*ListPermissionsRequest); i { case 0: return &v.state case 1: @@ -23878,7 +23935,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[186].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Failure); i { + switch v := v.(*ListPermissionsResponse); i { case 0: return &v.state case 1: @@ -23890,7 +23947,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[187].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ChannelUpdate); i { + switch v := v.(*Failure); i { case 0: return &v.state case 1: @@ -23902,7 +23959,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[188].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MacaroonId); i { + switch v := v.(*ChannelUpdate); i { case 0: return &v.state case 1: @@ -23914,7 +23971,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[189].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Op); i { + switch v := v.(*MacaroonId); i { case 0: return &v.state case 1: @@ -23926,7 +23983,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[190].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CheckMacPermRequest); i { + switch v := v.(*Op); i { case 0: return &v.state case 1: @@ -23938,7 +23995,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[191].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CheckMacPermResponse); i { + switch v := v.(*CheckMacPermRequest); i { case 0: return &v.state case 1: @@ -23950,7 +24007,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[192].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RPCMiddlewareRequest); i { + switch v := v.(*CheckMacPermResponse); i { case 0: return &v.state case 1: @@ -23962,7 +24019,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[193].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StreamAuth); i { + switch v := v.(*RPCMiddlewareRequest); i { case 0: return &v.state case 1: @@ -23974,7 +24031,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[194].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RPCMessage); i { + switch v := v.(*StreamAuth); i { case 0: return &v.state case 1: @@ -23986,7 +24043,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[195].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RPCMiddlewareResponse); i { + switch v := v.(*RPCMessage); i { case 0: return &v.state case 1: @@ -23998,7 +24055,7 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[196].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MiddlewareRegistration); i { + switch v := v.(*RPCMiddlewareResponse); i { case 0: return &v.state case 1: @@ -24010,6 +24067,18 @@ func file_lightning_proto_init() { } } file_lightning_proto_msgTypes[197].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MiddlewareRegistration); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_lightning_proto_msgTypes[198].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*InterceptFeedback); i { case 0: return &v.state @@ -24021,7 +24090,7 @@ func file_lightning_proto_init() { return nil } } - file_lightning_proto_msgTypes[204].Exporter = func(v interface{}, i int) interface{} { + file_lightning_proto_msgTypes[205].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PendingChannelsResponse_PendingChannel); i { case 0: return &v.state @@ -24033,7 +24102,7 @@ func file_lightning_proto_init() { return nil } } - file_lightning_proto_msgTypes[205].Exporter = func(v interface{}, i int) interface{} { + file_lightning_proto_msgTypes[206].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PendingChannelsResponse_PendingOpenChannel); i { case 0: return &v.state @@ -24045,7 +24114,7 @@ func file_lightning_proto_init() { return nil } } - file_lightning_proto_msgTypes[206].Exporter = func(v interface{}, i int) interface{} { + file_lightning_proto_msgTypes[207].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PendingChannelsResponse_WaitingCloseChannel); i { case 0: return &v.state @@ -24057,7 +24126,7 @@ func file_lightning_proto_init() { return nil } } - file_lightning_proto_msgTypes[207].Exporter = func(v interface{}, i int) interface{} { + file_lightning_proto_msgTypes[208].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PendingChannelsResponse_Commitments); i { case 0: return &v.state @@ -24069,7 +24138,7 @@ func file_lightning_proto_init() { return nil } } - file_lightning_proto_msgTypes[208].Exporter = func(v interface{}, i int) interface{} { + file_lightning_proto_msgTypes[209].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PendingChannelsResponse_ClosedChannel); i { case 0: return &v.state @@ -24081,7 +24150,7 @@ func file_lightning_proto_init() { return nil } } - file_lightning_proto_msgTypes[209].Exporter = func(v interface{}, i int) interface{} { + file_lightning_proto_msgTypes[210].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PendingChannelsResponse_ForceClosedChannel); i { case 0: return &v.state @@ -24131,21 +24200,21 @@ func file_lightning_proto_init() { (*ChannelEventUpdate_PendingOpenChannel)(nil), (*ChannelEventUpdate_FullyResolvedChannel)(nil), } - file_lightning_proto_msgTypes[160].OneofWrappers = []interface{}{ + file_lightning_proto_msgTypes[161].OneofWrappers = []interface{}{ (*PolicyUpdateRequest_Global)(nil), (*PolicyUpdateRequest_ChanPoint)(nil), } - file_lightning_proto_msgTypes[172].OneofWrappers = []interface{}{ + file_lightning_proto_msgTypes[173].OneofWrappers = []interface{}{ (*RestoreChanBackupRequest_ChanBackups)(nil), (*RestoreChanBackupRequest_MultiChanBackup)(nil), } - file_lightning_proto_msgTypes[192].OneofWrappers = []interface{}{ + file_lightning_proto_msgTypes[193].OneofWrappers = []interface{}{ (*RPCMiddlewareRequest_StreamAuth)(nil), (*RPCMiddlewareRequest_Request)(nil), (*RPCMiddlewareRequest_Response)(nil), (*RPCMiddlewareRequest_RegComplete)(nil), } - file_lightning_proto_msgTypes[195].OneofWrappers = []interface{}{ + file_lightning_proto_msgTypes[196].OneofWrappers = []interface{}{ (*RPCMiddlewareResponse_Register)(nil), (*RPCMiddlewareResponse_Feedback)(nil), } @@ -24155,7 +24224,7 @@ func file_lightning_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_lightning_proto_rawDesc, NumEnums: 21, - NumMessages: 224, + NumMessages: 225, NumExtensions: 0, NumServices: 1, }, diff --git a/lnrpc/lightning.proto b/lnrpc/lightning.proto index 2ad22e089..6356a6b47 100644 --- a/lnrpc/lightning.proto +++ b/lnrpc/lightning.proto @@ -4369,6 +4369,16 @@ message FeeReportResponse { uint64 month_fee_sum = 4; } +message InboundFee { + // The inbound base fee charged regardless of the number of milli-satoshis + // received in the channel. By default, only negative values are accepted. + int32 base_fee_msat = 1; + + // The effective inbound fee rate in micro-satoshis (parts per million). + // By default, only negative values are accepted. + int32 fee_rate_ppm = 2; +} + message PolicyUpdateRequest { oneof scope { // If set, then this update applies to all currently active channels. @@ -4402,8 +4412,9 @@ message PolicyUpdateRequest { // If true, min_htlc_msat is applied. bool min_htlc_msat_specified = 8; - int32 inbound_base_fee_msat = 10; - int32 inbound_fee_rate_ppm = 11; + // Optional inbound fee. If unset, the previously set value will be + // retained [EXPERIMENTAL]. + InboundFee inbound_fee = 10; } enum UpdateFailure { diff --git a/lnrpc/lightning.swagger.json b/lnrpc/lightning.swagger.json index 3a7132fc0..c79958080 100644 --- a/lnrpc/lightning.swagger.json +++ b/lnrpc/lightning.swagger.json @@ -5297,6 +5297,21 @@ } } }, + "lnrpcInboundFee": { + "type": "object", + "properties": { + "base_fee_msat": { + "type": "integer", + "format": "int32", + "description": "The inbound base fee charged regardless of the number of milli-satoshis\nreceived in the channel. By default, only negative values are accepted." + }, + "fee_rate_ppm": { + "type": "integer", + "format": "int32", + "description": "The effective inbound fee rate in micro-satoshis (parts per million).\nBy default, only negative values are accepted." + } + } + }, "lnrpcInitiator": { "type": "string", "enum": [ @@ -6585,13 +6600,9 @@ "type": "boolean", "description": "If true, min_htlc_msat is applied." }, - "inbound_base_fee_msat": { - "type": "integer", - "format": "int32" - }, - "inbound_fee_rate_ppm": { - "type": "integer", - "format": "int32" + "inbound_fee": { + "$ref": "#/definitions/lnrpcInboundFee", + "description": "Optional inbound fee. If unset, the previously set value will be\nretained [EXPERIMENTAL]." } } }, diff --git a/routing/localchans/manager.go b/routing/localchans/manager.go index 141e4359b..930b4c96b 100644 --- a/routing/localchans/manager.go +++ b/routing/localchans/manager.go @@ -9,6 +9,7 @@ import ( "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/discovery" + "github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/kvdb" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnwire" @@ -105,6 +106,14 @@ func (r *Manager) UpdatePolicy(newSchema routing.ChannelPolicy, Edge: edge, }) + // Extract inbound fees from the ExtraOpaqueData. + var inboundWireFee lnwire.Fee + _, err = edge.ExtraOpaqueData.ExtractRecords(&inboundWireFee) + if err != nil { + return err + } + inboundFee := models.NewInboundFeeFromWire(inboundWireFee) + // Add updated policy to list of policies to send to switch. policiesToUpdate[info.ChannelPoint] = models.ForwardingPolicy{ BaseFee: edge.FeeBaseMSat, @@ -112,7 +121,7 @@ func (r *Manager) UpdatePolicy(newSchema routing.ChannelPolicy, TimeLockDelta: uint32(edge.TimeLockDelta), MinHTLCOut: edge.MinHTLC, MaxHTLC: edge.MaxHTLC, - InboundFee: newSchema.InboundFee, + InboundFee: inboundFee, } return nil @@ -182,8 +191,15 @@ func (r *Manager) updateEdge(tx kvdb.RTx, chanPoint wire.OutPoint, newSchema.FeeRate, ) - inboundFee := newSchema.InboundFee.ToWire() - if err := edge.ExtraOpaqueData.PackRecords(&inboundFee); err != nil { + // If inbound fees are set, we update the edge with them. + err := fn.MapOptionZ(newSchema.InboundFee, + func(f models.InboundFee) error { + inboundWireFee := f.ToWire() + return edge.ExtraOpaqueData.PackRecords( + &inboundWireFee, + ) + }) + if err != nil { return err } diff --git a/routing/router.go b/routing/router.go index 04502d49b..e7c24acf1 100644 --- a/routing/router.go +++ b/routing/router.go @@ -22,6 +22,7 @@ import ( "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/clock" + "github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/kvdb" @@ -290,7 +291,7 @@ type FeeSchema struct { // InboundFee is the inbound fee schedule that applies to forwards // coming in through a channel to which this FeeSchema pertains. - InboundFee models.InboundFee + InboundFee fn.Option[models.InboundFee] } // ChannelPolicy holds the parameters that determine the policy we enforce diff --git a/rpcserver.go b/rpcserver.go index 1e9f0be08..9f3ad24b5 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -46,6 +46,7 @@ import ( "github.com/lightningnetwork/lnd/contractcourt" "github.com/lightningnetwork/lnd/discovery" "github.com/lightningnetwork/lnd/feature" + "github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/funding" "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/htlcswitch/hop" @@ -7216,27 +7217,35 @@ func (r *rpcServer) UpdateChannelPolicy(ctx context.Context, } // By default, positive inbound fees are rejected. - if !r.cfg.AcceptPositiveInboundFees { - if req.InboundBaseFeeMsat > 0 { + if !r.cfg.AcceptPositiveInboundFees && req.InboundFee != nil { + if req.InboundFee.BaseFeeMsat > 0 { return nil, fmt.Errorf("positive values for inbound "+ "base fee msat are not supported: %v", - req.InboundBaseFeeMsat) + req.InboundFee.BaseFeeMsat) } - if req.InboundFeeRatePpm > 0 { + if req.InboundFee.FeeRatePpm > 0 { return nil, fmt.Errorf("positive values for inbound "+ "fee rate ppm are not supported: %v", - req.InboundFeeRatePpm) + req.InboundFee.FeeRatePpm) } } + // If no inbound fees have been specified, we indicate with an empty + // option that the previous inbound fee should be retained during the + // edge update. + inboundFee := fn.None[models.InboundFee]() + if req.InboundFee != nil { + inboundFee = fn.Some(models.InboundFee{ + Base: req.InboundFee.BaseFeeMsat, + Rate: req.InboundFee.FeeRatePpm, + }) + } + baseFeeMsat := lnwire.MilliSatoshi(req.BaseFeeMsat) feeSchema := routing.FeeSchema{ - BaseFee: baseFeeMsat, - FeeRate: feeRateFixed, - InboundFee: models.InboundFee{ - Base: req.InboundBaseFeeMsat, - Rate: req.InboundFeeRatePpm, - }, + BaseFee: baseFeeMsat, + FeeRate: feeRateFixed, + InboundFee: inboundFee, } maxHtlc := lnwire.MilliSatoshi(req.MaxHtlcMsat) From dc4ec45423d0e1eae72fe42c22e2f575a22ddd18 Mon Sep 17 00:00:00 2001 From: feelancer21 <2828397+feelancer21@users.noreply.github.com> Date: Mon, 20 May 2024 21:17:53 +0200 Subject: [PATCH 103/109] itest: add more tests related to inbound fees Add tests for setting inbound fees in channel policies, including tests where no inbound fees are set in the PolicyUpdateRequest. --- itest/lnd_channel_policy_test.go | 23 ++++++++++++++---- itest/lnd_multi-hop-payments_test.go | 35 ++++++++++++++++++++-------- lntest/node/watcher.go | 12 ++++++++++ 3 files changed, 55 insertions(+), 15 deletions(-) diff --git a/itest/lnd_channel_policy_test.go b/itest/lnd_channel_policy_test.go index 85527a082..108397453 100644 --- a/itest/lnd_channel_policy_test.go +++ b/itest/lnd_channel_policy_test.go @@ -45,7 +45,9 @@ func testUpdateChannelPolicy(ht *lntest.HarnessTest) { nodes := []*node.HarnessNode{alice, bob} // Alice and Bob should see each other's ChannelUpdates, advertising the - // default routing policies. + // default routing policies. We do not currently set any inbound fees. + // The inbound base and inbound fee rate are advertised with a default + // of 0. expectedPolicy := &lnrpc.RoutingPolicy{ FeeBaseMsat: defaultFeeBase, FeeRateMilliMsat: defaultFeeRate, @@ -227,9 +229,9 @@ func testUpdateChannelPolicy(ht *lntest.HarnessTest) { require.NoError(ht, err, "unable to receive payment stream") require.Empty(ht, sendResp.PaymentError, "expected payment to succeed") - // With our little cluster set up, we'll update the fees and the max - // htlc size for the Bob side of the Alice->Bob channel, and make sure - // all nodes learn about it. + // With our little cluster set up, we'll update the outbound fees and + // the max htlc size for the Bob side of the Alice->Bob channel, and + // make sure all nodes learn about it. Inbound fees remain at 0. baseFee := int64(1500) feeRate := int64(12) timeLockDelta := uint32(66) @@ -298,17 +300,25 @@ func testUpdateChannelPolicy(ht *lntest.HarnessTest) { feeRate = int64(123) timeLockDelta = uint32(22) maxHtlc *= 2 + inboundBaseFee := int32(-400) + inboundFeeRatePpm := int32(-60) expectedPolicy.FeeBaseMsat = baseFee expectedPolicy.FeeRateMilliMsat = testFeeBase * feeRate expectedPolicy.TimeLockDelta = timeLockDelta expectedPolicy.MaxHtlcMsat = maxHtlc + expectedPolicy.InboundFeeBaseMsat = inboundBaseFee + expectedPolicy.InboundFeeRateMilliMsat = inboundFeeRatePpm req = &lnrpc.PolicyUpdateRequest{ BaseFeeMsat: baseFee, FeeRate: float64(feeRate), TimeLockDelta: timeLockDelta, MaxHtlcMsat: maxHtlc, + InboundFee: &lnrpc.InboundFee{ + BaseFeeMsat: inboundBaseFee, + FeeRatePpm: inboundFeeRatePpm, + }, } req.Scope = &lnrpc.PolicyUpdateRequest_Global{} alice.RPC.UpdateChannelPolicy(req) @@ -370,10 +380,13 @@ func testUpdateChannelPolicy(ht *lntest.HarnessTest) { ) } - // Double the base fee and attach to the policy. + // Double the base fee and attach to the policy. Moreover, we set the + // inbound fee to nil and test that it does not change the propagated + // inbound fee. baseFee1 := baseFee * 2 expectedPolicy.FeeBaseMsat = baseFee1 req.BaseFeeMsat = baseFee1 + req.InboundFee = nil assertAliceAndBob(req, expectedPolicy) // Check that Carol has both heard the policy and updated it in her diff --git a/itest/lnd_multi-hop-payments_test.go b/itest/lnd_multi-hop-payments_test.go index 665b54cab..ee07d6f8c 100644 --- a/itest/lnd_multi-hop-payments_test.go +++ b/itest/lnd_multi-hop-payments_test.go @@ -74,8 +74,8 @@ func testMultiHopPayments(ht *lntest.HarnessTest) { const aliceFeeRatePPM = 100000 updateChannelPolicy( ht, alice, chanPointAlice, aliceBaseFeeSat*1000, - aliceFeeRatePPM, 0, 0, chainreg.DefaultBitcoinTimeLockDelta, - maxHtlc, carol, + aliceFeeRatePPM, 0, 0, false, + chainreg.DefaultBitcoinTimeLockDelta, maxHtlc, carol, ) // Define a negative inbound fee for Alice, to verify that this is @@ -85,9 +85,19 @@ func testMultiHopPayments(ht *lntest.HarnessTest) { aliceInboundFeeRate = -50000 // 5% ) + // We update the channel twice. The first time we set the inbound fee, + // the second time we don't. This is done to test whether the switch is + // still aware of the inbound fees. updateChannelPolicy( ht, alice, chanPointDave, 0, 0, - aliceInboundBaseFeeMsat, aliceInboundFeeRate, + aliceInboundBaseFeeMsat, aliceInboundFeeRate, true, + chainreg.DefaultBitcoinTimeLockDelta, maxHtlc, + dave, + ) + + updateChannelPolicy( + ht, alice, chanPointDave, 0, 0, + aliceInboundBaseFeeMsat, aliceInboundFeeRate, false, chainreg.DefaultBitcoinTimeLockDelta, maxHtlc, dave, ) @@ -96,7 +106,7 @@ func testMultiHopPayments(ht *lntest.HarnessTest) { const daveFeeRatePPM = 150000 updateChannelPolicy( ht, dave, chanPointDave, daveBaseFeeSat*1000, daveFeeRatePPM, - 0, 0, + 0, 0, true, chainreg.DefaultBitcoinTimeLockDelta, maxHtlc, carol, ) @@ -236,8 +246,8 @@ func testMultiHopPayments(ht *lntest.HarnessTest) { // // NOTE: only used in current test. func updateChannelPolicy(ht *lntest.HarnessTest, hn *node.HarnessNode, - chanPoint *lnrpc.ChannelPoint, baseFee int64, - feeRate int64, inboundBaseFee, inboundFeeRate int32, + chanPoint *lnrpc.ChannelPoint, baseFee int64, feeRate int64, + inboundBaseFee, inboundFeeRate int32, updateInboundFee bool, timeLockDelta uint32, maxHtlc uint64, listenerNode *node.HarnessNode) { expectedPolicy := &lnrpc.RoutingPolicy{ @@ -250,6 +260,14 @@ func updateChannelPolicy(ht *lntest.HarnessTest, hn *node.HarnessNode, InboundFeeRateMilliMsat: inboundFeeRate, } + var inboundFee *lnrpc.InboundFee + if updateInboundFee { + inboundFee = &lnrpc.InboundFee{ + BaseFeeMsat: inboundBaseFee, + FeeRatePpm: inboundFeeRate, + } + } + updateFeeReq := &lnrpc.PolicyUpdateRequest{ BaseFeeMsat: baseFee, FeeRate: float64(feeRate) / testFeeBase, @@ -258,10 +276,7 @@ func updateChannelPolicy(ht *lntest.HarnessTest, hn *node.HarnessNode, ChanPoint: chanPoint, }, MaxHtlcMsat: maxHtlc, - InboundFee: &lnrpc.InboundFee{ - BaseFeeMsat: inboundBaseFee, - FeeRatePpm: inboundFeeRate, - }, + InboundFee: inboundFee, } hn.RPC.UpdateChannelPolicy(updateFeeReq) diff --git a/lntest/node/watcher.go b/lntest/node/watcher.go index a87e6c2ba..7656cb3c5 100644 --- a/lntest/node/watcher.go +++ b/lntest/node/watcher.go @@ -681,6 +681,18 @@ func CheckChannelPolicy(policy, expectedPolicy *lnrpc.RoutingPolicy) error { return fmt.Errorf("expected max htlc %v, got %v", expectedPolicy.MaxHtlcMsat, policy.MaxHtlcMsat) } + if policy.InboundFeeBaseMsat != expectedPolicy.InboundFeeBaseMsat { + return fmt.Errorf("expected inbound base fee %v, got %v", + expectedPolicy.InboundFeeBaseMsat, + policy.InboundFeeBaseMsat) + } + if policy.InboundFeeRateMilliMsat != + expectedPolicy.InboundFeeRateMilliMsat { + + return fmt.Errorf("expected inbound fee rate %v, got %v", + expectedPolicy.InboundFeeRateMilliMsat, + policy.InboundFeeRateMilliMsat) + } if policy.Disabled != expectedPolicy.Disabled { return errors.New("edge should be disabled but isn't") } From 634967c5c8091f72fa8c08fa19c3e0d52004c23a Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 24 May 2024 22:49:20 +0800 Subject: [PATCH 104/109] chainfee: add `FeeForVByte` on `SatPerKWeight` --- lnwallet/chainfee/rates.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lnwallet/chainfee/rates.go b/lnwallet/chainfee/rates.go index 98cefc13b..49711e31b 100644 --- a/lnwallet/chainfee/rates.go +++ b/lnwallet/chainfee/rates.go @@ -70,6 +70,12 @@ func (s SatPerKWeight) FeeForWeight(wu int64) btcutil.Amount { return btcutil.Amount(s) * btcutil.Amount(wu) / 1000 } +// FeeForVByte calculates the fee resulting from this fee rate and the given +// size in vbytes (vb). +func (s SatPerKWeight) FeeForVByte(vb int64) btcutil.Amount { + return s.FeePerKVByte().FeeForVSize(vb) +} + // FeePerKVByte converts the current fee rate from sat/kw to sat/kb. func (s SatPerKWeight) FeePerKVByte() SatPerKVByte { return SatPerKVByte(s * blockchain.WitnessScaleFactor) From dc9a0b31c0ed67f6e52cc50002b1a3f0e43d5248 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 24 May 2024 19:55:21 +0800 Subject: [PATCH 105/109] lntypes: add new units `WeightUnit` and `VByte` --- lntypes/txsize.go | 42 ++++++++++++++++++++++++++++++++++++++++++ lntypes/txsize_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 lntypes/txsize.go create mode 100644 lntypes/txsize_test.go diff --git a/lntypes/txsize.go b/lntypes/txsize.go new file mode 100644 index 000000000..0618bfc51 --- /dev/null +++ b/lntypes/txsize.go @@ -0,0 +1,42 @@ +package lntypes + +import ( + "fmt" + "math" +) + +// WeightUnit defines a unit to express the transaction size. One weight unit +// is 1/4_000_000 of the max block size. The tx weight is calculated using +// `Base tx size * 3 + Total tx size`. +// - Base tx size is size of the transaction serialized without the witness +// data. +// - Total tx size is the transaction size in bytes serialized according +// #BIP144. +type WeightUnit uint64 + +// ToVB converts a value expressed in weight units to virtual bytes. +func (wu WeightUnit) ToVB() VByte { + // According to BIP141: Virtual transaction size is defined as + // Transaction weight / 4 (rounded up to the next integer). + return VByte(math.Ceil(float64(wu) / 4)) +} + +// String returns the string representation of the weight unit. +func (wu WeightUnit) String() string { + return fmt.Sprintf("%d wu", wu) +} + +// VByte defines a unit to express the transaction size. One virtual byte is +// 1/4th of a weight unit. The tx virtual bytes is calculated using `TxWeight / +// 4`. +type VByte uint64 + +// ToWU converts a value expressed in virtual bytes to weight units. +func (vb VByte) ToWU() WeightUnit { + return WeightUnit(vb * 4) +} + +// String returns the string representation of the virtual byte. +func (vb VByte) String() string { + return fmt.Sprintf("%d vb", vb) +} diff --git a/lntypes/txsize_test.go b/lntypes/txsize_test.go new file mode 100644 index 000000000..a68a45b23 --- /dev/null +++ b/lntypes/txsize_test.go @@ -0,0 +1,28 @@ +package lntypes + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +// TestTxSizeUnit tests the conversion of tx size to different units. +func TestTxSizeUnit(t *testing.T) { + t.Parallel() + + // Test normal conversion from 100wu to 25vb. + wu := WeightUnit(100) + vb := VByte(25) + require.Equal(t, vb, wu.ToVB(), "wu -> vb conversion "+ + "failed: want %v, got %v", vb, wu.ToVB()) + require.Equal(t, wu, vb.ToWU(), "vb -> wu conversion "+ + "failed: want %v, got %v", wu, vb.ToWU()) + + // Test rounding up conversion from 99wu to 25vb. + wu = WeightUnit(99) + vb = VByte(25) + require.Equal(t, vb, wu.ToVB(), "wu -> vb conversion "+ + "failed: want %v, got %v", vb, wu.ToVB()) + require.Equal(t, WeightUnit(100), vb.ToWU(), "vb -> wu conversion "+ + "failed: want %v, got %v", 100, vb.ToWU()) +} From 8da68bb7dbf0423bb8c9e13dcfa982f80a9aabe3 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 24 May 2024 21:56:30 +0800 Subject: [PATCH 106/109] multi: apply the new type `lntypes.WeightUnit` --- contractcourt/breach_arbitrator.go | 5 ++- htlcswitch/link_test.go | 44 +++++++++---------- input/input.go | 2 +- input/mocks.go | 5 ++- input/size.go | 25 +++++++---- input/size_test.go | 11 ++--- input/witnessgen.go | 19 +++++--- itest/lnd_channel_funding_fund_max_test.go | 2 +- itest/lnd_recovery_test.go | 2 +- itest/lnd_sweep_test.go | 13 +++--- itest/lnd_taproot_test.go | 24 +++++----- lnrpc/walletrpc/walletkit_server.go | 6 +-- lnrpc/walletrpc/walletkit_server_test.go | 2 +- lntest/harness.go | 7 +-- lntest/utils.go | 10 +++-- lnwallet/chainfee/rates.go | 7 +-- lnwallet/chancloser/chancloser.go | 2 +- lnwallet/chanfunding/coin_select.go | 4 +- lnwallet/chanfunding/coin_select_test.go | 2 +- lnwallet/channel.go | 22 +++++----- lnwallet/channel_test.go | 10 ++--- lnwallet/commitment.go | 5 ++- lnwallet/reservation.go | 9 ++-- lnwallet/test_utils.go | 8 ++-- lnwallet/transactions_test.go | 2 +- sweep/aggregator.go | 4 +- sweep/aggregator_test.go | 8 ++-- sweep/fee_bumper.go | 5 ++- sweep/tx_input_set.go | 3 +- sweep/weight_estimator.go | 9 ++-- sweep/weight_estimator_test.go | 9 ++-- watchtower/blob/commitments.go | 5 ++- watchtower/lookout/justice_descriptor.go | 5 ++- watchtower/lookout/justice_descriptor_test.go | 2 +- watchtower/wtclient/backup_task.go | 2 +- watchtower/wtpolicy/policy.go | 11 +++-- 36 files changed, 178 insertions(+), 133 deletions(-) diff --git a/contractcourt/breach_arbitrator.go b/contractcourt/breach_arbitrator.go index 89927b6e1..96fa689c3 100644 --- a/contractcourt/breach_arbitrator.go +++ b/contractcourt/breach_arbitrator.go @@ -19,6 +19,7 @@ import ( "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/kvdb" "github.com/lightningnetwork/lnd/labels" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/chainfee" ) @@ -1497,14 +1498,14 @@ func (b *BreachArbitrator) createSweepTx(inputs ...input.Input) (*wire.MsgTx, spendableOutputs = append(spendableOutputs, inp) } - txWeight := int64(weightEstimate.Weight()) + txWeight := weightEstimate.Weight() return b.sweepSpendableOutputsTxn(txWeight, spendableOutputs...) } // sweepSpendableOutputsTxn creates a signed transaction from a sequence of // spendable outputs by sweeping the funds into a single p2wkh output. -func (b *BreachArbitrator) sweepSpendableOutputsTxn(txWeight int64, +func (b *BreachArbitrator) sweepSpendableOutputsTxn(txWeight lntypes.WeightUnit, inputs ...input.Input) (*wire.MsgTx, error) { // First, we obtain a new public key script from the wallet which we'll diff --git a/htlcswitch/link_test.go b/htlcswitch/link_test.go index 6963bf708..93c76bd40 100644 --- a/htlcswitch/link_test.go +++ b/htlcswitch/link_test.go @@ -2480,7 +2480,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight := int64(1) * input.HTLCWeight + htlcWeight := lntypes.WeightUnit(1) * input.HTLCWeight feeBuffer := lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -2517,7 +2517,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight = int64(2) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(2) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -2578,7 +2578,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight = int64(1) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(1) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -2609,7 +2609,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight = int64(2) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(2) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -2675,7 +2675,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight = int64(1) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(1) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -2721,7 +2721,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight = int64(2) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(2) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -2771,7 +2771,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight = int64(1) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(1) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -2835,7 +2835,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight = int64(2) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(2) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -2880,7 +2880,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight = int64(1) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(1) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -2976,7 +2976,7 @@ func TestChannelLinkTrimCircuitsPending(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight := int64(1) * input.HTLCWeight + htlcWeight := lntypes.WeightUnit(1) * input.HTLCWeight feeBuffer := lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -3022,7 +3022,7 @@ func TestChannelLinkTrimCircuitsPending(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight = int64(1+halfHtlcs) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(1+halfHtlcs) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -3113,7 +3113,7 @@ func TestChannelLinkTrimCircuitsPending(t *testing.T) { // With two HTLCs on the pending commit, and two added to the in-memory // commitment state, the resulting bandwidth should reflect that Alice // is paying the all htlc amounts in addition to all htlc fees. - htlcWeight = int64(1+numHtlcs) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(1+numHtlcs) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -3205,7 +3205,7 @@ func TestChannelLinkTrimCircuitsPending(t *testing.T) { // Since the latter two HTLCs have been completely dropped from memory, // only the first two HTLCs we added should still be reflected in the // channel bandwidth. - htlcWeight = int64(1+halfHtlcs) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(1+halfHtlcs) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -3264,7 +3264,7 @@ func TestChannelLinkTrimCircuitsNoCommit(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight := int64(1) * input.HTLCWeight + htlcWeight := lntypes.WeightUnit(1) * input.HTLCWeight feeBuffer := lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -3309,7 +3309,7 @@ func TestChannelLinkTrimCircuitsNoCommit(t *testing.T) { // We account for the 2 htlcs and the additional one which would be // needed when sending and htlc. - htlcWeight = int64(1+halfHtlcs) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(1+halfHtlcs) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -3387,7 +3387,7 @@ func TestChannelLinkTrimCircuitsNoCommit(t *testing.T) { } // Alice's bandwidth should have reverted back to her starting value. - htlcWeight = int64(1) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(1) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -3414,7 +3414,7 @@ func TestChannelLinkTrimCircuitsNoCommit(t *testing.T) { // We account for the 2 htlcs and the additional one which would be // needed when sending and htlc. - htlcWeight = int64(1+halfHtlcs) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(1+halfHtlcs) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -3492,7 +3492,7 @@ func TestChannelLinkTrimCircuitsNoCommit(t *testing.T) { t.Fatalf("expected %d packet to be failed", halfHtlcs) } - htlcWeight = int64(1) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(1) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -3540,7 +3540,7 @@ func TestChannelLinkTrimCircuitsRemoteCommit(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight := int64(1) * input.HTLCWeight + htlcWeight := lntypes.WeightUnit(1) * input.HTLCWeight feeBuffer := lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -3602,7 +3602,7 @@ func TestChannelLinkTrimCircuitsRemoteCommit(t *testing.T) { // The resulting bandwidth should reflect that Alice is paying both // htlc amounts, in addition to both htlc fees. - htlcWeight = int64(1+numHtlcs) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(1+numHtlcs) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) @@ -3700,7 +3700,7 @@ func TestChannelLinkBandwidthChanReserve(t *testing.T) { // Calculate the fee buffer for a channel state. Account for htlcs on // the potential channel state as well. - htlcWeight := int64(1) * input.HTLCWeight + htlcWeight := lntypes.WeightUnit(1) * input.HTLCWeight feeBuffer := lnwallet.CalcFeeBuffer(feePerKw, commitWeight+htlcWeight) // The starting bandwidth of the channel should be exactly the amount @@ -3727,7 +3727,7 @@ func TestChannelLinkBandwidthChanReserve(t *testing.T) { _ = harness.aliceLink.handleSwitchPacket(addPkt) time.Sleep(time.Millisecond * 100) - htlcWeight = int64(2) * input.HTLCWeight + htlcWeight = lntypes.WeightUnit(2) * input.HTLCWeight feeBuffer = lnwallet.CalcFeeBuffer( feePerKw, commitWeight+htlcWeight, ) diff --git a/input/input.go b/input/input.go index a6d3fa5b4..aef524a4c 100644 --- a/input/input.go +++ b/input/input.go @@ -71,7 +71,7 @@ type TxInfo struct { Fee btcutil.Amount // Weight is the weight of the tx. - Weight int64 + Weight lntypes.WeightUnit } // String returns a human readable version of the tx info. diff --git a/input/mocks.go b/input/mocks.go index 915e4ea69..2f38400d8 100644 --- a/input/mocks.go +++ b/input/mocks.go @@ -9,6 +9,7 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/keychain" + "github.com/lightningnetwork/lnd/lntypes" "github.com/stretchr/testify/mock" ) @@ -157,10 +158,10 @@ func (m *MockWitnessType) WitnessGenerator(signer Signer, // if it would be included in a tx. It also returns if the output itself is a // nested p2sh output, if so then we need to take into account the extra // sigScript data size. -func (m *MockWitnessType) SizeUpperBound() (int, bool, error) { +func (m *MockWitnessType) SizeUpperBound() (lntypes.WeightUnit, bool, error) { args := m.Called() - return args.Int(0), args.Bool(1), args.Error(2) + return args.Get(0).(lntypes.WeightUnit), args.Bool(1), args.Error(2) } // AddWeightEstimation adds the estimated size of the witness in bytes to the diff --git a/input/size.go b/input/size.go index e71e4190b..8260baae0 100644 --- a/input/size.go +++ b/input/size.go @@ -5,6 +5,7 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcwallet/waddrmgr" + "github.com/lightningnetwork/lnd/lntypes" ) const ( @@ -863,7 +864,7 @@ type TxWeightEstimator struct { inputCount uint32 outputCount uint32 inputSize int - inputWitnessSize int + inputWitnessSize lntypes.WeightUnit outputSize int } @@ -888,7 +889,9 @@ func (twe *TxWeightEstimator) AddP2WKHInput() *TxWeightEstimator { // AddWitnessInput updates the weight estimate to account for an additional // input spending a native pay-to-witness output. This accepts the total size // of the witness as a parameter. -func (twe *TxWeightEstimator) AddWitnessInput(witnessSize int) *TxWeightEstimator { +func (twe *TxWeightEstimator) AddWitnessInput( + witnessSize lntypes.WeightUnit) *TxWeightEstimator { + twe.inputSize += InputSize twe.inputWitnessSize += witnessSize twe.inputCount++ @@ -905,7 +908,8 @@ func (twe *TxWeightEstimator) AddWitnessInput(witnessSize int) *TxWeightEstimato // NOTE: The leaf witness size must be calculated without the byte that accounts // for the number of witness elements, only the total size of all elements on // the stack that are consumed by the revealed script should be counted. -func (twe *TxWeightEstimator) AddTapscriptInput(leafWitnessSize int, +func (twe *TxWeightEstimator) AddTapscriptInput( + leafWitnessSize lntypes.WeightUnit, tapscript *waddrmgr.Tapscript) *TxWeightEstimator { // We add 1 byte for the total number of witness elements. @@ -915,7 +919,9 @@ func (twe *TxWeightEstimator) AddTapscriptInput(leafWitnessSize int, 1 + len(tapscript.ControlBlock.InclusionProof) twe.inputSize += InputSize - twe.inputWitnessSize += leafWitnessSize + controlBlockWitnessSize + twe.inputWitnessSize += leafWitnessSize + lntypes.WeightUnit( + controlBlockWitnessSize, + ) twe.inputCount++ twe.hasWitness = true @@ -956,7 +962,9 @@ func (twe *TxWeightEstimator) AddNestedP2WKHInput() *TxWeightEstimator { // AddNestedP2WSHInput updates the weight estimate to account for an additional // input spending a P2SH output with a nested P2WSH redeem script. -func (twe *TxWeightEstimator) AddNestedP2WSHInput(witnessSize int) *TxWeightEstimator { +func (twe *TxWeightEstimator) AddNestedP2WSHInput( + witnessSize lntypes.WeightUnit) *TxWeightEstimator { + twe.inputSize += InputSize + NestedP2WSHSize twe.inputWitnessSize += witnessSize twe.inputCount++ @@ -1027,11 +1035,12 @@ func (twe *TxWeightEstimator) AddOutput(pkScript []byte) *TxWeightEstimator { } // Weight gets the estimated weight of the transaction. -func (twe *TxWeightEstimator) Weight() int { +func (twe *TxWeightEstimator) Weight() lntypes.WeightUnit { txSizeStripped := BaseTxSize + wire.VarIntSerializeSize(uint64(twe.inputCount)) + twe.inputSize + wire.VarIntSerializeSize(uint64(twe.outputCount)) + twe.outputSize - weight := txSizeStripped * witnessScaleFactor + weight := lntypes.WeightUnit(txSizeStripped * witnessScaleFactor) + if twe.hasWitness { weight += WitnessHeaderSize + twe.inputWitnessSize } @@ -1041,5 +1050,5 @@ func (twe *TxWeightEstimator) Weight() int { // VSize gets the estimated virtual size of the transactions, in vbytes. func (twe *TxWeightEstimator) VSize() int { // A tx's vsize is 1/4 of the weight, rounded up. - return (twe.Weight() + witnessScaleFactor - 1) / witnessScaleFactor + return int(twe.Weight().ToVB()) } diff --git a/input/size_test.go b/input/size_test.go index 1f447cf89..9c3446afb 100644 --- a/input/size_test.go +++ b/input/size_test.go @@ -297,11 +297,12 @@ func TestTxWeightEstimator(t *testing.T) { tx.AddTxOut(&wire.TxOut{PkScript: p2shScript}) } - expectedWeight := blockchain.GetTransactionWeight(btcutil.NewTx(tx)) - if weightEstimate.Weight() != int(expectedWeight) { - t.Errorf("Case %d: Got wrong weight: expected %d, got %d", - i, expectedWeight, weightEstimate.Weight()) - } + expectedWeight := blockchain.GetTransactionWeight( + btcutil.NewTx(tx), + ) + require.EqualValuesf(t, expectedWeight, weightEstimate.Weight(), + "Case %d: Got wrong weight: expected %d, got %d", + i, expectedWeight, weightEstimate.Weight()) } } diff --git a/input/witnessgen.go b/input/witnessgen.go index 66b5ef90e..c49328afc 100644 --- a/input/witnessgen.go +++ b/input/witnessgen.go @@ -5,6 +5,7 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" + "github.com/lightningnetwork/lnd/lntypes" ) // WitnessGenerator represents a function that is able to generate the final @@ -32,7 +33,7 @@ type WitnessType interface { // WitnessType if it would be included in a tx. It also returns if the // output itself is a nested p2sh output, if so then we need to take // into account the extra sigScript data size. - SizeUpperBound() (int, bool, error) + SizeUpperBound() (lntypes.WeightUnit, bool, error) // AddWeightEstimation adds the estimated size of the witness in bytes // to the given weight estimator. @@ -726,7 +727,9 @@ func (wt StandardWitnessType) WitnessGenerator(signer Signer, // sigScript data size. // // NOTE: This is part of the WitnessType interface. -func (wt StandardWitnessType) SizeUpperBound() (int, bool, error) { +func (wt StandardWitnessType) SizeUpperBound() (lntypes.WeightUnit, + bool, error) { + switch wt { // Outputs on a remote commitment transaction that pay directly to us. case CommitSpendNoDelayTweakless: @@ -743,7 +746,8 @@ func (wt StandardWitnessType) SizeUpperBound() (int, bool, error) { case LeaseCommitmentTimeLock: size := ToLocalTimeoutWitnessSize + LeaseWitnessScriptSizeOverhead - return size, false, nil + + return lntypes.WeightUnit(size), false, nil // 1 CSV time locked output to us on remote commitment. case CommitmentToRemoteConfirmed: @@ -751,7 +755,8 @@ func (wt StandardWitnessType) SizeUpperBound() (int, bool, error) { case LeaseCommitmentToRemoteConfirmed: size := ToRemoteConfirmedWitnessSize + LeaseWitnessScriptSizeOverhead - return size, false, nil + + return lntypes.WeightUnit(size), false, nil // Anchor output on the commitment transaction. case CommitmentAnchor: @@ -765,7 +770,8 @@ func (wt StandardWitnessType) SizeUpperBound() (int, bool, error) { case LeaseHtlcOfferedTimeoutSecondLevel: size := ToLocalTimeoutWitnessSize + LeaseWitnessScriptSizeOverhead - return size, false, nil + + return lntypes.WeightUnit(size), false, nil // Input to the outgoing HTLC second layer timeout transaction. case HtlcOfferedTimeoutSecondLevelInputConfirmed: @@ -779,7 +785,8 @@ func (wt StandardWitnessType) SizeUpperBound() (int, bool, error) { case LeaseHtlcAcceptedSuccessSecondLevel: size := ToLocalTimeoutWitnessSize + LeaseWitnessScriptSizeOverhead - return size, false, nil + + return lntypes.WeightUnit(size), false, nil // Input to the incoming second-layer HTLC success transaction. case HtlcAcceptedSuccessSecondLevelInputConfirmed: diff --git a/itest/lnd_channel_funding_fund_max_test.go b/itest/lnd_channel_funding_fund_max_test.go index 63d4d471d..fb1987705 100644 --- a/itest/lnd_channel_funding_fund_max_test.go +++ b/itest/lnd_channel_funding_fund_max_test.go @@ -309,7 +309,7 @@ func fundingFee(numInput int, change bool) btcutil.Amount { weightEstimate.AddP2TROutput() } - totalWeight := int64(weightEstimate.Weight()) + totalWeight := weightEstimate.Weight() return feeRate.FeeForWeight(totalWeight) } diff --git a/itest/lnd_recovery_test.go b/itest/lnd_recovery_test.go index c3e6efccd..766d10956 100644 --- a/itest/lnd_recovery_test.go +++ b/itest/lnd_recovery_test.go @@ -379,7 +379,7 @@ func testRescanAddressDetection(ht *lntest.HarnessTest) { estimator := input.TxWeightEstimator{} estimator.AddP2WKHInput() estimator.AddP2WKHOutput() - estimatedWeight := int64(estimator.Weight()) + estimatedWeight := estimator.Weight() requiredFee := feeRate.FeeForWeight(estimatedWeight) tx := wire.NewMsgTx(2) diff --git a/itest/lnd_sweep_test.go b/itest/lnd_sweep_test.go index 4702def38..27ad13266 100644 --- a/itest/lnd_sweep_test.go +++ b/itest/lnd_sweep_test.go @@ -271,7 +271,7 @@ func testSweepCPFPAnchorOutgoingTimeout(ht *lntest.HarnessTest) { // We expect the fees to increase by i*delta. expectedFee := startFeeAnchor + feeDelta.MulF64(float64(i)) expectedFeeRate := chainfee.NewSatPerKWeight( - expectedFee, uint64(txWeight), + expectedFee, txWeight, ) // We should see Bob's anchor sweeping tx being fee bumped @@ -608,7 +608,7 @@ func testSweepCPFPAnchorIncomingTimeout(ht *lntest.HarnessTest) { // We expect the fees to increase by i*delta. expectedFee := startFeeAnchor + feeDelta.MulF64(float64(i)) expectedFeeRate := chainfee.NewSatPerKWeight( - expectedFee, uint64(txWeight), + expectedFee, txWeight, ) // We should see Bob's anchor sweeping tx being fee bumped @@ -929,7 +929,7 @@ func testSweepHTLCs(ht *lntest.HarnessTest) { outgoingBudget := 2 * invoiceAmt outgoingTxSize := ht.CalculateTxWeight(outgoingSweep) outgoingEndFeeRate := chainfee.NewSatPerKWeight( - outgoingBudget, uint64(outgoingTxSize), + outgoingBudget, outgoingTxSize, ) // Assert the initial sweeping tx is using the start fee rate. @@ -950,7 +950,8 @@ func testSweepHTLCs(ht *lntest.HarnessTest) { // assertSweepFeeRate is a helper closure that asserts the expected fee // rate is used at the given position for a sweeping tx. assertSweepFeeRate := func(sweepTx *wire.MsgTx, - startFeeRate, delta chainfee.SatPerKWeight, txSize int64, + startFeeRate, delta chainfee.SatPerKWeight, + txSize lntypes.WeightUnit, deadline, position int32, desc string) { // Bob's HTLC sweeping tx should be fee bumped. @@ -1068,7 +1069,7 @@ func testSweepHTLCs(ht *lntest.HarnessTest) { incomingBudget := invoiceAmt.MulF64(contractcourt.DefaultBudgetRatio) incomingTxSize := ht.CalculateTxWeight(incomingSweep) incomingEndFeeRate := chainfee.NewSatPerKWeight( - incomingBudget, uint64(incomingTxSize), + incomingBudget, incomingTxSize, ) // Assert the initial sweeping tx is using the start fee rate. @@ -1415,7 +1416,7 @@ func testSweepCommitOutputAndAnchor(ht *lntest.HarnessTest) { // Calculate the ending fee rate and fee rate delta used in his fee // function. - bobTxWeight := uint64(ht.CalculateTxWeight(bobSweepTx)) + bobTxWeight := ht.CalculateTxWeight(bobSweepTx) bobEndingFeeRate := chainfee.NewSatPerKWeight(bobBudget, bobTxWeight) bobFeeRateDelta := (bobEndingFeeRate - bobStartFeeRate) / chainfee.SatPerKWeight(deadlineB-1) diff --git a/itest/lnd_taproot_test.go b/itest/lnd_taproot_test.go index ed37e04e8..3b5cb4799 100644 --- a/itest/lnd_taproot_test.go +++ b/itest/lnd_taproot_test.go @@ -22,6 +22,7 @@ import ( "github.com/lightningnetwork/lnd/lnrpc/walletrpc" "github.com/lightningnetwork/lnd/lntest" "github.com/lightningnetwork/lnd/lntest/node" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/stretchr/testify/require" ) @@ -187,7 +188,7 @@ func testTaprootComputeInputScriptKeySpendBip86(ht *lntest.HarnessTest, estimator := input.TxWeightEstimator{} estimator.AddTaprootKeySpendInput(txscript.SigHashDefault) estimator.AddP2WKHOutput() - estimatedWeight := int64(estimator.Weight()) + estimatedWeight := estimator.Weight() requiredFee := feeRate.FeeForWeight(estimatedWeight) tx := wire.NewMsgTx(2) @@ -278,7 +279,7 @@ func testTaprootSignOutputRawScriptSpend(ht *lntest.HarnessTest, ) estimator.AddP2WKHOutput() - estimatedWeight := int64(estimator.Weight()) + estimatedWeight := estimator.Weight() sigHash := txscript.SigHashDefault if len(sigHashType) != 0 { sigHash = sigHashType[0] @@ -431,7 +432,7 @@ func testTaprootSignOutputRawKeySpendBip86(ht *lntest.HarnessTest, estimator := input.TxWeightEstimator{} estimator.AddTaprootKeySpendInput(sigHash) estimator.AddP2WKHOutput() - estimatedWeight := int64(estimator.Weight()) + estimatedWeight := estimator.Weight() requiredFee := feeRate.FeeForWeight(estimatedWeight) tx := wire.NewMsgTx(2) @@ -525,7 +526,7 @@ func testTaprootSignOutputRawKeySpendRootHash(ht *lntest.HarnessTest, estimator := input.TxWeightEstimator{} estimator.AddTaprootKeySpendInput(txscript.SigHashDefault) estimator.AddP2WKHOutput() - estimatedWeight := int64(estimator.Weight()) + estimatedWeight := estimator.Weight() requiredFee := feeRate.FeeForWeight(estimatedWeight) tx := wire.NewMsgTx(2) @@ -610,7 +611,7 @@ func testTaprootMuSig2KeySpendBip86(ht *lntest.HarnessTest, estimator := input.TxWeightEstimator{} estimator.AddTaprootKeySpendInput(txscript.SigHashDefault) estimator.AddP2WKHOutput() - estimatedWeight := int64(estimator.Weight()) + estimatedWeight := estimator.Weight() requiredFee := feeRate.FeeForWeight(estimatedWeight) tx := wire.NewMsgTx(2) @@ -740,7 +741,7 @@ func testTaprootMuSig2KeySpendRootHash(ht *lntest.HarnessTest, estimator := input.TxWeightEstimator{} estimator.AddTaprootKeySpendInput(txscript.SigHashDefault) estimator.AddP2WKHOutput() - estimatedWeight := int64(estimator.Weight()) + estimatedWeight := estimator.Weight() requiredFee := feeRate.FeeForWeight(estimatedWeight) tx := wire.NewMsgTx(2) @@ -874,10 +875,11 @@ func testTaprootMuSig2ScriptSpend(ht *lntest.HarnessTest, feeRate := chainfee.SatPerKWeight(12500) estimator := input.TxWeightEstimator{} estimator.AddTapscriptInput( - len([]byte("foobar"))+len(leaf1.Script)+1, tapscript, + lntypes.WeightUnit(len([]byte("foobar"))+len(leaf1.Script)+1), + tapscript, ) estimator.AddP2WKHOutput() - estimatedWeight := int64(estimator.Weight()) + estimatedWeight := estimator.Weight() requiredFee := feeRate.FeeForWeight(estimatedWeight) tx := wire.NewMsgTx(2) @@ -956,7 +958,7 @@ func testTaprootMuSig2CombinedLeafKeySpend(ht *lntest.HarnessTest, input.TaprootSignatureWitnessSize, tapscript, ) estimator.AddP2WKHOutput() - estimatedWeight := int64(estimator.Weight()) + estimatedWeight := estimator.Weight() requiredFee := feeRate.FeeForWeight(estimatedWeight) tx := wire.NewMsgTx(2) @@ -1525,7 +1527,7 @@ func sendToTaprootOutput(ht *lntest.HarnessTest, hn *node.HarnessNode, // spend request, the given sweep address' balance is verified to be seen as // funds belonging to the wallet. func publishTxAndConfirmSweep(ht *lntest.HarnessTest, node *node.HarnessNode, - tx *wire.MsgTx, estimatedWeight int64, + tx *wire.MsgTx, estimatedWeight lntypes.WeightUnit, spendRequest *chainrpc.SpendRequest, sweepAddr string) { ht.Helper() @@ -1564,7 +1566,7 @@ func publishTxAndConfirmSweep(ht *lntest.HarnessTest, node *node.HarnessNode, // Since Schnorr signatures are fixed size, we must be able to estimate // the size of this transaction exactly. txWeight := blockchain.GetTransactionWeight(btcutil.NewTx(tx)) - require.Equal(ht, estimatedWeight, txWeight) + require.EqualValues(ht, estimatedWeight, txWeight) txReq := &walletrpc.Transaction{ TxHex: buf.Bytes(), diff --git a/lnrpc/walletrpc/walletkit_server.go b/lnrpc/walletrpc/walletkit_server.go index a00c38207..f5ac051b3 100644 --- a/lnrpc/walletrpc/walletkit_server.go +++ b/lnrpc/walletrpc/walletkit_server.go @@ -1737,7 +1737,7 @@ func (w *WalletKit) fundPsbtCoinSelect(account string, changeIndex int32, // Do we already have enough inputs specified to pay for the TX as it // is? In that case we only need to allocate any change, if there is // any. - packetFeeNoChange := feeRate.FeeForWeight(int64(estimator.Weight())) + packetFeeNoChange := feeRate.FeeForWeight(estimator.Weight()) if inputSum >= outputSum+packetFeeNoChange { // Calculate the packet's fee with a change output so, so we can // let the coin selection algorithm decide whether to use a @@ -1749,9 +1749,7 @@ func (w *WalletKit) fundPsbtCoinSelect(account string, changeIndex int32, case chanfunding.P2WKHChangeAddress: estimator.AddP2WKHOutput() } - packetFeeWithChange := feeRate.FeeForWeight( - int64(estimator.Weight()), - ) + packetFeeWithChange := feeRate.FeeForWeight(estimator.Weight()) changeAmt, needMore, err := chanfunding.CalculateChangeAmount( inputSum, outputSum, packetFeeNoChange, diff --git a/lnrpc/walletrpc/walletkit_server_test.go b/lnrpc/walletrpc/walletkit_server_test.go index d47a55981..115ccf96e 100644 --- a/lnrpc/walletrpc/walletkit_server_test.go +++ b/lnrpc/walletrpc/walletkit_server_test.go @@ -132,7 +132,7 @@ func TestFundPsbtCoinSelect(t *testing.T) { } weight := estimator.Weight() - fee := chainfee.FeePerKwFloor.FeeForWeight(int64(weight)) + fee := chainfee.FeePerKwFloor.FeeForWeight(weight) return fee + dust } diff --git a/lntest/harness.go b/lntest/harness.go index 889bb156e..ba61b0ac3 100644 --- a/lntest/harness.go +++ b/lntest/harness.go @@ -21,6 +21,7 @@ import ( "github.com/lightningnetwork/lnd/lntest/node" "github.com/lightningnetwork/lnd/lntest/rpc" "github.com/lightningnetwork/lnd/lntest/wait" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwire" "github.com/stretchr/testify/require" @@ -2041,9 +2042,9 @@ func (h *HarnessTest) CalculateTxFee(tx *wire.MsgTx) btcutil.Amount { // CalculateTxWeight calculates the weight for a given tx. // // TODO(yy): use weight estimator to get more accurate result. -func (h *HarnessTest) CalculateTxWeight(tx *wire.MsgTx) int64 { +func (h *HarnessTest) CalculateTxWeight(tx *wire.MsgTx) lntypes.WeightUnit { utx := btcutil.NewTx(tx) - return blockchain.GetTransactionWeight(utx) + return lntypes.WeightUnit(blockchain.GetTransactionWeight(utx)) } // CalculateTxFeeRate calculates the fee rate for a given tx. @@ -2053,7 +2054,7 @@ func (h *HarnessTest) CalculateTxFeeRate( w := h.CalculateTxWeight(tx) fee := h.CalculateTxFee(tx) - return chainfee.NewSatPerKWeight(fee, uint64(w)) + return chainfee.NewSatPerKWeight(fee, w) } // CalculateTxesFeeRate takes a list of transactions and estimates the fee rate diff --git a/lntest/utils.go b/lntest/utils.go index 660c42ef9..d230b6b61 100644 --- a/lntest/utils.go +++ b/lntest/utils.go @@ -13,6 +13,7 @@ import ( "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lntest/wait" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwire" @@ -212,8 +213,9 @@ func CalcStaticFee(c lnrpc.CommitmentType, numHTLCs int) btcutil.Amount { anchors = anchorSize } - return feePerKw.FeeForWeight(int64(commitWeight+htlcWeight*numHTLCs)) + - anchors + totalWeight := commitWeight + htlcWeight*numHTLCs + + return feePerKw.FeeForWeight(lntypes.WeightUnit(totalWeight)) + anchors } // CalculateMaxHtlc re-implements the RequiredRemoteChannelReserve of the @@ -266,8 +268,10 @@ func CalcStaticFeeBuffer(c lnrpc.CommitmentType, numHTLCs int) btcutil.Amount { // Account for the HTLC which will be required when sending an htlc. numHTLCs++ + + totalWeight := commitWeight + numHTLCs*htlcWeight feeBuffer := lnwallet.CalcFeeBuffer( - feePerKw, int64(commitWeight+numHTLCs*htlcWeight), + feePerKw, lntypes.WeightUnit(totalWeight), ) return feeBuffer.ToSatoshis() diff --git a/lnwallet/chainfee/rates.go b/lnwallet/chainfee/rates.go index 49711e31b..0ea0a277d 100644 --- a/lnwallet/chainfee/rates.go +++ b/lnwallet/chainfee/rates.go @@ -5,6 +5,7 @@ import ( "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/btcutil" + "github.com/lightningnetwork/lnd/lntypes" ) const ( @@ -59,13 +60,13 @@ func (s SatPerKVByte) String() string { type SatPerKWeight btcutil.Amount // NewSatPerKWeight creates a new fee rate in sat/kw. -func NewSatPerKWeight(fee btcutil.Amount, weight uint64) SatPerKWeight { - return SatPerKWeight(fee.MulF64(1000 / float64(weight))) +func NewSatPerKWeight(fee btcutil.Amount, wu lntypes.WeightUnit) SatPerKWeight { + return SatPerKWeight(fee.MulF64(1000 / float64(wu))) } // FeeForWeight calculates the fee resulting from this fee rate and the given // weight in weight units (wu). -func (s SatPerKWeight) FeeForWeight(wu int64) btcutil.Amount { +func (s SatPerKWeight) FeeForWeight(wu lntypes.WeightUnit) btcutil.Amount { // The resulting fee is rounded down, as specified in BOLT#03. return btcutil.Amount(s) * btcutil.Amount(wu) / 1000 } diff --git a/lnwallet/chancloser/chancloser.go b/lnwallet/chancloser/chancloser.go index bc9a1c903..47635c3af 100644 --- a/lnwallet/chancloser/chancloser.go +++ b/lnwallet/chancloser/chancloser.go @@ -240,7 +240,7 @@ func calcCoopCloseFee(chanType channeldb.ChannelType, weightEstimator.AddTxOutput(remoteOutput) } - totalWeight := int64(weightEstimator.Weight()) + totalWeight := weightEstimator.Weight() return idealFeeRate.FeeForWeight(totalWeight) } diff --git a/lnwallet/chanfunding/coin_select.go b/lnwallet/chanfunding/coin_select.go index 4cf50c574..9bf7f2dc0 100644 --- a/lnwallet/chanfunding/coin_select.go +++ b/lnwallet/chanfunding/coin_select.go @@ -116,7 +116,7 @@ func calculateFees(utxos []wallet.Coin, feeRate chainfee.SatPerKWeight, // Estimate the fee required for a transaction without a change // output. - totalWeight := int64(weightEstimate.Weight()) + totalWeight := weightEstimate.Weight() requiredFeeNoChange := feeRate.FeeForWeight(totalWeight) // Estimate the fee required for a transaction with a change output. @@ -137,7 +137,7 @@ func calculateFees(utxos []wallet.Coin, feeRate chainfee.SatPerKWeight, // Now that we have added the change output, redo the fee // estimate. - totalWeight = int64(weightEstimate.Weight()) + totalWeight = weightEstimate.Weight() requiredFeeWithChange := feeRate.FeeForWeight(totalWeight) return requiredFeeNoChange, requiredFeeWithChange, nil diff --git a/lnwallet/chanfunding/coin_select_test.go b/lnwallet/chanfunding/coin_select_test.go index 43027f32f..a6ff18bae 100644 --- a/lnwallet/chanfunding/coin_select_test.go +++ b/lnwallet/chanfunding/coin_select_test.go @@ -50,7 +50,7 @@ func fundingFee(feeRate chainfee.SatPerKWeight, numInput int, // nolint:unparam weightEstimate.AddP2TROutput() } - totalWeight := int64(weightEstimate.Weight()) + totalWeight := weightEstimate.Weight() return feeRate.FeeForWeight(totalWeight) } diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 1af0e4b5f..0e0d762c1 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -28,6 +28,7 @@ import ( "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/keychain" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/shachain" @@ -3800,7 +3801,7 @@ func (lc *LightningChannel) getUnsignedAckedUpdates() []channeldb.LogUpdate { // an htlc even if our channel is drained locally. // See: https://github.com/lightning/bolts/blob/master/02-peer-protocol.md func CalcFeeBuffer(feePerKw chainfee.SatPerKWeight, - commitWeight int64) lnwire.MilliSatoshi { + commitWeight lntypes.WeightUnit) lnwire.MilliSatoshi { // Account for a 100% in fee rate increase. bufferFeePerKw := 2 * feePerKw @@ -3873,7 +3874,7 @@ func (b BufferType) String() string { // and verifies that it does not become negative. This function returns the new // balance and the exact buffer amount (excluding the commitment fee). func (lc *LightningChannel) applyCommitFee( - balance lnwire.MilliSatoshi, commitWeight int64, + balance lnwire.MilliSatoshi, commitWeight lntypes.WeightUnit, feePerKw chainfee.SatPerKWeight, buffer BufferType) (lnwire.MilliSatoshi, lnwire.MilliSatoshi, error) { @@ -4730,8 +4731,8 @@ func (lc *LightningChannel) ProcessChanSyncMsg( // If the updateState boolean is set true, the add and remove heights of the // HTLCs will be set to the next commitment height. func (lc *LightningChannel) computeView(view *htlcView, remoteChain bool, - updateState bool) (lnwire.MilliSatoshi, lnwire.MilliSatoshi, int64, - *htlcView, error) { + updateState bool) (lnwire.MilliSatoshi, lnwire.MilliSatoshi, + lntypes.WeightUnit, *htlcView, error) { commitChain := lc.localCommitChain dustLimit := lc.channelState.LocalChanCfg.DustLimit @@ -4792,7 +4793,7 @@ func (lc *LightningChannel) computeView(view *htlcView, remoteChain bool, // Now go through all HTLCs at this stage, to calculate the total // weight, needed to calculate the transaction fee. - var totalHtlcWeight int64 + var totalHtlcWeight lntypes.WeightUnit for _, htlc := range filteredHTLCView.ourUpdates { if HtlcIsDust( lc.channelState.ChanType, false, !remoteChain, @@ -7522,7 +7523,7 @@ type AnchorResolution struct { CommitFee btcutil.Amount // CommitWeight is the weight of the commit tx. - CommitWeight int64 + CommitWeight lntypes.WeightUnit } // LocalForceCloseSummary describes the final commitment state before the @@ -8200,7 +8201,7 @@ func NewAnchorResolution(chanState *channeldb.OpenChannel, return &AnchorResolution{ CommitAnchor: *outPoint, AnchorSignDescriptor: *signDesc, - CommitWeight: weight, + CommitWeight: lntypes.WeightUnit(weight), CommitFee: fee, }, nil } @@ -8226,7 +8227,7 @@ func (lc *LightningChannel) AvailableBalance() lnwire.MilliSatoshi { // this method. Additionally, the total weight of the next to be created // commitment is returned for accounting purposes. func (lc *LightningChannel) availableBalance( - buffer BufferType) (lnwire.MilliSatoshi, int64) { + buffer BufferType) (lnwire.MilliSatoshi, lntypes.WeightUnit) { // We'll grab the current set of log updates that the remote has // ACKed. @@ -8265,8 +8266,9 @@ func (lc *LightningChannel) availableBalance( // commitment, increasing the commitment fee we must pay as an initiator, // eating into our balance. It will make sure we won't violate the channel // reserve constraints for this amount. -func (lc *LightningChannel) availableCommitmentBalance(view *htlcView, - remoteChain bool, buffer BufferType) (lnwire.MilliSatoshi, int64) { +func (lc *LightningChannel) availableCommitmentBalance( + view *htlcView, remoteChain bool, + buffer BufferType) (lnwire.MilliSatoshi, lntypes.WeightUnit) { // Compute the current balances for this commitment. This will take // into account HTLCs to determine the commit weight, which the diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index 7ef5c118a..4accf1262 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -832,7 +832,7 @@ func TestForceClose(t *testing.T) { type forceCloseTestCase struct { chanType channeldb.ChannelType - expectedCommitWeight int64 + expectedCommitWeight lntypes.WeightUnit anchorAmt btcutil.Amount } @@ -4803,7 +4803,7 @@ func TestChanAvailableBandwidth(t *testing.T) { ) assertBandwidthEstimateCorrect := func(aliceInitiate bool, - numNonDustHtlcsOnCommit int64) { + numNonDustHtlcsOnCommit lntypes.WeightUnit) { // With the HTLC's added, we'll now query the AvailableBalance // method for the current available channel bandwidth from @@ -5189,7 +5189,7 @@ func TestChanCommitWeightDustHtlcs(t *testing.T) { // fromt the given channel's POV. // When sending htlcs we enforce the feebuffer on the commitment // transaction. - remoteCommitWeight := func(lc *LightningChannel) int64 { + remoteCommitWeight := func(lc *LightningChannel) lntypes.WeightUnit { remoteACKedIndex := lc.localCommitChain.tip().theirMessageIndex htlcView := lc.fetchHTLCView(remoteACKedIndex, lc.localUpdateLog.logIndex) @@ -10454,8 +10454,8 @@ func TestApplyCommitmentFee(t *testing.T) { balanceBelowReserve = lnwire.NewMSatFromSatoshis(5_000) // commitment weight with an additional htlc. - commitWeight int64 = input.BaseAnchorCommitmentTxWeight + - input.HTLCWeight + commitWeight lntypes.WeightUnit = input. + BaseAnchorCommitmentTxWeight + input.HTLCWeight // fee rate of 10 sat/vbyte. feePerKw = chainfee.SatPerKWeight(2500) diff --git a/lnwallet/commitment.go b/lnwallet/commitment.go index 6ecef795b..96af8d7cf 100644 --- a/lnwallet/commitment.go +++ b/lnwallet/commitment.go @@ -12,6 +12,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwire" ) @@ -471,7 +472,7 @@ func SecondLevelHtlcScript(chanType channeldb.ChannelType, initiator bool, } // CommitWeight returns the base commitment weight before adding HTLCs. -func CommitWeight(chanType channeldb.ChannelType) int64 { +func CommitWeight(chanType channeldb.ChannelType) lntypes.WeightUnit { switch { case chanType.IsTaproot(): return input.TaprootCommitWeight @@ -724,7 +725,7 @@ func (cb *CommitmentBuilder) createUnsignedCommitmentTx(ourBalance, // by the current fee-per-kw, then divide by 1000 to get the proper // fee. totalCommitWeight := CommitWeight(cb.chanState.ChanType) + - input.HTLCWeight*numHTLCs + lntypes.WeightUnit(input.HTLCWeight*numHTLCs) // With the weight known, we can now calculate the commitment fee, // ensuring that we account for any dust outputs trimmed above. diff --git a/lnwallet/reservation.go b/lnwallet/reservation.go index a99448768..1c6dbbabe 100644 --- a/lnwallet/reservation.go +++ b/lnwallet/reservation.go @@ -13,6 +13,7 @@ import ( "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/keychain" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet/chanfunding" "github.com/lightningnetwork/lnd/lnwire" ) @@ -241,13 +242,15 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount, // Based on the channel type, we determine the initial commit weight // and fee. - commitWeight := int64(input.CommitWeight) + commitWeight := input.CommitWeight if req.CommitType.IsTaproot() { commitWeight = input.TaprootCommitWeight } else if req.CommitType.HasAnchors() { - commitWeight = int64(input.AnchorCommitWeight) + commitWeight = input.AnchorCommitWeight } - commitFee := req.CommitFeePerKw.FeeForWeight(commitWeight) + commitFee := req.CommitFeePerKw.FeeForWeight( + lntypes.WeightUnit(commitWeight), + ) localFundingMSat := lnwire.NewMSatFromSatoshis(localFundingAmt) // TODO(halseth): make method take remote funding amount directly diff --git a/lnwallet/test_utils.go b/lnwallet/test_utils.go index e33d563c3..29213bb7f 100644 --- a/lnwallet/test_utils.go +++ b/lnwallet/test_utils.go @@ -16,6 +16,7 @@ import ( "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/keychain" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/shachain" @@ -506,9 +507,10 @@ func calcStaticFee(chanType channeldb.ChannelType, numHTLCs int) btcutil.Amount htlcWeight = 172 feePerKw = btcutil.Amount(24/4) * 1000 ) - return feePerKw * - (btcutil.Amount(CommitWeight(chanType) + - htlcWeight*int64(numHTLCs))) / 1000 + htlcsWeight := htlcWeight * int64(numHTLCs) + totalWeight := CommitWeight(chanType) + lntypes.WeightUnit(htlcsWeight) + + return feePerKw * (btcutil.Amount(totalWeight)) / 1000 } // ForceStateTransition executes the necessary interaction between the two diff --git a/lnwallet/transactions_test.go b/lnwallet/transactions_test.go index 1f15523c4..d2a2a448b 100644 --- a/lnwallet/transactions_test.go +++ b/lnwallet/transactions_test.go @@ -913,7 +913,7 @@ func createTestChannelsForVectors(tc *testContext, chanType channeldb.ChannelTyp // Create the initial commitment transactions for the channel. feePerKw := chainfee.SatPerKWeight(feeRate) - commitWeight := int64(input.CommitWeight) + commitWeight := lntypes.WeightUnit(input.CommitWeight) if chanType.HasAnchors() { commitWeight = input.AnchorCommitWeight } diff --git a/sweep/aggregator.go b/sweep/aggregator.go index c812cbe2b..801ac6b83 100644 --- a/sweep/aggregator.go +++ b/sweep/aggregator.go @@ -211,7 +211,7 @@ func (b *BudgetAggregator) filterInputs(inputs InputsMap) InputsMap { } // Skip inputs that has too little budget. - minFee := minFeeRate.FeeForWeight(int64(size)) + minFee := minFeeRate.FeeForWeight(size) if pi.params.Budget < minFee { log.Warnf("Skipped input=%v: has budget=%v, but the "+ "min fee requires %v", op, pi.params.Budget, @@ -224,7 +224,7 @@ func (b *BudgetAggregator) filterInputs(inputs InputsMap) InputsMap { startingFeeRate := pi.params.StartingFeeRate.UnwrapOr( chainfee.SatPerKWeight(0), ) - startingFee := startingFeeRate.FeeForWeight(int64(size)) + startingFee := startingFeeRate.FeeForWeight(size) if pi.params.Budget < startingFee { log.Errorf("Skipped input=%v: has budget=%v, but the "+ "starting fee requires %v", op, diff --git a/sweep/aggregator_test.go b/sweep/aggregator_test.go index 289f2780e..0b60bc3a7 100644 --- a/sweep/aggregator_test.go +++ b/sweep/aggregator_test.go @@ -10,6 +10,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/stretchr/testify/require" ) @@ -34,14 +35,15 @@ func TestBudgetAggregatorFilterInputs(t *testing.T) { // Mock the `SizeUpperBound` method to return an error exactly once. dummyErr := errors.New("dummy error") - wtErr.On("SizeUpperBound").Return(0, false, dummyErr).Once() + wtErr.On("SizeUpperBound").Return( + lntypes.WeightUnit(0), false, dummyErr).Once() // Create a mock WitnessType that gives the size. wt := &input.MockWitnessType{} defer wt.AssertExpectations(t) // Mock the `SizeUpperBound` method to return the size four times. - const wtSize = 100 + const wtSize lntypes.WeightUnit = 100 wt.On("SizeUpperBound").Return(wtSize, true, nil).Times(4) // Create a mock input that will be filtered out due to error. @@ -396,7 +398,7 @@ func TestBudgetInputSetClusterInputs(t *testing.T) { // Mock the `SizeUpperBound` method to return the size 10 times since // we are using ten inputs. - const wtSize = 100 + const wtSize lntypes.WeightUnit = 100 wt.On("SizeUpperBound").Return(wtSize, true, nil).Times(10) wt.On("String").Return("mock witness type") diff --git a/sweep/fee_bumper.go b/sweep/fee_bumper.go index dd471efff..b4d429894 100644 --- a/sweep/fee_bumper.go +++ b/sweep/fee_bumper.go @@ -17,6 +17,7 @@ import ( "github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/labels" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnutils" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/chainfee" @@ -155,7 +156,7 @@ func (r *BumpRequest) MaxFeeRateAllowed() (chainfee.SatPerKWeight, error) { // calcSweepTxWeight calculates the weight of the sweep tx. It assumes a // sweeping tx always has a single output(change). func calcSweepTxWeight(inputs []input.Input, - outputPkScript []byte) (uint64, error) { + outputPkScript []byte) (lntypes.WeightUnit, error) { // Use a const fee rate as we only use the weight estimator to // calculate the size. @@ -175,7 +176,7 @@ func calcSweepTxWeight(inputs []input.Input, return 0, err } - return uint64(estimator.weight()), nil + return estimator.weight(), nil } // BumpResult is used by the Bumper to send updates about the tx being diff --git a/sweep/tx_input_set.go b/sweep/tx_input_set.go index 27cdafada..31f20b7db 100644 --- a/sweep/tx_input_set.go +++ b/sweep/tx_input_set.go @@ -314,7 +314,8 @@ func (b *BudgetInputSet) AddWalletInputs(wallet Wallet) error { } b.addInput(pi) - log.Debugf("Added wallet input %v to input set", pi) + log.Debugf("Added wallet input to input set: op=%v, amt=%v", + pi.OutPoint(), utxo.Value) // Return if we've reached the minimum output amount. if !b.NeedWalletInput() { diff --git a/sweep/weight_estimator.go b/sweep/weight_estimator.go index f705c826e..429b36ee5 100644 --- a/sweep/weight_estimator.go +++ b/sweep/weight_estimator.go @@ -5,6 +5,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet/chainfee" ) @@ -15,7 +16,7 @@ type weightEstimator struct { feeRate chainfee.SatPerKWeight parents map[chainhash.Hash]struct{} parentsFee btcutil.Amount - parentsWeight int64 + parentsWeight lntypes.WeightUnit // maxFeeRate is the max allowed fee rate configured by the user. maxFeeRate chainfee.SatPerKWeight @@ -102,7 +103,7 @@ func (w *weightEstimator) addOutput(txOut *wire.TxOut) { } // weight gets the estimated weight of the transaction. -func (w *weightEstimator) weight() int { +func (w *weightEstimator) weight() lntypes.WeightUnit { return w.estimator.Weight() } @@ -111,7 +112,7 @@ func (w *weightEstimator) weight() int { // parent transactions. func (w *weightEstimator) fee() btcutil.Amount { // Calculate the weight of the transaction. - weight := int64(w.estimator.Weight()) + weight := w.estimator.Weight() // Calculate the fee. fee := w.feeRate.FeeForWeight(weight) @@ -123,7 +124,7 @@ func (w *weightEstimator) fee() btcutil.Amount { // outputs, taking into account unconfirmed parent transactions (cpfp). func (w *weightEstimator) feeWithParent() btcutil.Amount { // Calculate fee and weight for just this tx. - childWeight := int64(w.estimator.Weight()) + childWeight := w.estimator.Weight() // Add combined weight of unconfirmed parent txes. totalWeight := childWeight + w.parentsWeight diff --git a/sweep/weight_estimator_test.go b/sweep/weight_estimator_test.go index d5beb5174..513aa01cc 100644 --- a/sweep/weight_estimator_test.go +++ b/sweep/weight_estimator_test.go @@ -8,6 +8,7 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/stretchr/testify/require" ) @@ -28,7 +29,7 @@ func TestWeightEstimator(t *testing.T) { require.NoError(t, w.add(&input1)) // The expectations is that this input is added. - const expectedWeight1 = 322 + const expectedWeight1 lntypes.WeightUnit = 322 require.Equal(t, expectedWeight1, w.weight()) require.Equal(t, testFeeRate.FeeForWeight(expectedWeight1), w.feeWithParent()) @@ -50,7 +51,7 @@ func TestWeightEstimator(t *testing.T) { // Pay for parent isn't possible because the parent pays a higher fee // rate than the child. We expect no additional fee on the child. - const expectedWeight2 = expectedWeight1 + 280 + const expectedWeight2 lntypes.WeightUnit = expectedWeight1 + 280 require.Equal(t, expectedWeight2, w.weight()) require.Equal(t, testFeeRate.FeeForWeight(expectedWeight2), w.feeWithParent()) @@ -70,7 +71,7 @@ func TestWeightEstimator(t *testing.T) { require.NoError(t, w.add(&input3)) // Expect the weight to increase because of the third input. - const expectedWeight3 = expectedWeight2 + 280 + const expectedWeight3 lntypes.WeightUnit = expectedWeight2 + 280 require.Equal(t, expectedWeight3, w.weight()) // Expect the fee to cover the child and the parent transaction at 20 @@ -107,7 +108,7 @@ func TestWeightEstimatorMaxFee(t *testing.T) { require.NoError(t, w.add(&childInput)) // The child weight should be 322 weight uints. - const childWeight = 322 + const childWeight lntypes.WeightUnit = 322 require.Equal(t, childWeight, w.weight()) // Check the fee is capped at the maximum allowed fee. The diff --git a/watchtower/blob/commitments.go b/watchtower/blob/commitments.go index f86240447..994c55caf 100644 --- a/watchtower/blob/commitments.go +++ b/watchtower/blob/commitments.go @@ -5,6 +5,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwire" ) @@ -115,7 +116,7 @@ func (c CommitmentType) ToRemoteWitnessType() (input.WitnessType, error) { // ToRemoteWitnessSize is the size of the witness that will be required to spend // the to_remote output. -func (c CommitmentType) ToRemoteWitnessSize() (int, error) { +func (c CommitmentType) ToRemoteWitnessSize() (lntypes.WeightUnit, error) { switch c { // Legacy channels (both tweaked and non-tweaked) spend from P2WKH // output. @@ -137,7 +138,7 @@ func (c CommitmentType) ToRemoteWitnessSize() (int, error) { // ToLocalWitnessSize is the size of the witness that will be required to spend // the to_local output. -func (c CommitmentType) ToLocalWitnessSize() (int, error) { +func (c CommitmentType) ToLocalWitnessSize() (lntypes.WeightUnit, error) { switch c { // An older ToLocalPenaltyWitnessSize constant used to underestimate the // size by one byte. The difference in weight can cause different output diff --git a/watchtower/lookout/justice_descriptor.go b/watchtower/lookout/justice_descriptor.go index 2c0623e65..96b414470 100644 --- a/watchtower/lookout/justice_descriptor.go +++ b/watchtower/lookout/justice_descriptor.go @@ -11,6 +11,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/watchtower/blob" "github.com/lightningnetwork/lnd/watchtower/wtdb" ) @@ -123,7 +124,7 @@ func (p *JusticeDescriptor) commitToRemoteInput() (*breachedInput, error) { // assembleJusticeTxn accepts the breached inputs recovered from state update // and attempts to construct the justice transaction that sweeps the victims // funds to their wallet and claims the watchtower's reward. -func (p *JusticeDescriptor) assembleJusticeTxn(txWeight int64, +func (p *JusticeDescriptor) assembleJusticeTxn(txWeight lntypes.WeightUnit, inputs ...*breachedInput) (*wire.MsgTx, error) { justiceTxn := wire.NewMsgTx(2) @@ -287,7 +288,7 @@ func (p *JusticeDescriptor) CreateJusticeTxn() (*wire.MsgTx, error) { // TODO(conner): sweep htlc outputs - txWeight := int64(weightEstimate.Weight()) + txWeight := weightEstimate.Weight() return p.assembleJusticeTxn(txWeight, sweepInputs...) } diff --git a/watchtower/lookout/justice_descriptor_test.go b/watchtower/lookout/justice_descriptor_test.go index 2ca187fdc..a07b440ad 100644 --- a/watchtower/lookout/justice_descriptor_test.go +++ b/watchtower/lookout/justice_descriptor_test.go @@ -317,7 +317,7 @@ func testJusticeDescriptor(t *testing.T, blobType blob.Type) { } outputs, err := policy.ComputeJusticeTxOuts( - totalAmount, int64(txWeight), justiceKit.SweepAddress(), + totalAmount, txWeight, justiceKit.SweepAddress(), sessionInfo.RewardAddress, ) require.NoError(t, err) diff --git a/watchtower/wtclient/backup_task.go b/watchtower/wtclient/backup_task.go index 49f917514..1e90d7b37 100644 --- a/watchtower/wtclient/backup_task.go +++ b/watchtower/wtclient/backup_task.go @@ -216,7 +216,7 @@ func (t *backupTask) bindSession(session *wtdb.ClientSessionBody, // Now, compute the output values depending on whether FlagReward is set // in the current session's policy. outputs, err := session.Policy.ComputeJusticeTxOuts( - t.totalAmt, int64(weightEstimate.Weight()), + t.totalAmt, weightEstimate.Weight(), t.sweepPkScript, session.RewardPkScript, ) if err != nil { diff --git a/watchtower/wtpolicy/policy.go b/watchtower/wtpolicy/policy.go index 9d5763fb2..89804685b 100644 --- a/watchtower/wtpolicy/policy.go +++ b/watchtower/wtpolicy/policy.go @@ -6,6 +6,7 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/wire" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwire" @@ -180,8 +181,9 @@ func (p *Policy) Validate() error { // that pays no reward to the tower. The value is computed using the weight of // of the justice transaction and subtracting an amount that satisfies the // policy's fee rate. -func (p *Policy) ComputeAltruistOutput(totalAmt btcutil.Amount, - txWeight int64, sweepScript []byte) (btcutil.Amount, error) { +func (p *Policy) ComputeAltruistOutput( + totalAmt btcutil.Amount, txWeight lntypes.WeightUnit, + sweepScript []byte) (btcutil.Amount, error) { txFee := p.SweepFeeRate.FeeForWeight(txWeight) if txFee > totalAmt { @@ -204,7 +206,7 @@ func (p *Policy) ComputeAltruistOutput(totalAmt btcutil.Amount, // and reward rate. The reward to he tower is subtracted first, before // splitting the remaining balance amongst the victim and fees. func (p *Policy) ComputeRewardOutputs(totalAmt btcutil.Amount, - txWeight int64, + txWeight lntypes.WeightUnit, rewardScript []byte) (btcutil.Amount, btcutil.Amount, error) { txFee := p.SweepFeeRate.FeeForWeight(txWeight) @@ -266,7 +268,8 @@ func ComputeRewardAmount(total btcutil.Amount, base, rate uint32) btcutil.Amount // rewardPkScript is the pkScript of the tower where its reward will be // deposited, and will be // ignored if the blob type does not specify a reward. -func (p *Policy) ComputeJusticeTxOuts(totalAmt btcutil.Amount, txWeight int64, +func (p *Policy) ComputeJusticeTxOuts( + totalAmt btcutil.Amount, txWeight lntypes.WeightUnit, sweepPkScript, rewardPkScript []byte) ([]*wire.TxOut, error) { var outputs []*wire.TxOut From 17a089c8999b4663cefa3aba1f7b4ad8b5566a8f Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 24 May 2024 23:03:51 +0800 Subject: [PATCH 107/109] input+lnwallet: apply the new type `lntypes.VByte` --- input/size.go | 15 ++++++++------- lnwallet/chainfee/rates.go | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/input/size.go b/input/size.go index 8260baae0..5d4b15ec1 100644 --- a/input/size.go +++ b/input/size.go @@ -863,9 +863,9 @@ type TxWeightEstimator struct { hasWitness bool inputCount uint32 outputCount uint32 - inputSize int + inputSize lntypes.VByte inputWitnessSize lntypes.WeightUnit - outputSize int + outputSize lntypes.VByte } // AddP2PKHInput updates the weight estimate to account for an additional input @@ -975,7 +975,7 @@ func (twe *TxWeightEstimator) AddNestedP2WSHInput( // AddTxOutput adds a known TxOut to the weight estimator. func (twe *TxWeightEstimator) AddTxOutput(txOut *wire.TxOut) *TxWeightEstimator { - twe.outputSize += txOut.SerializeSize() + twe.outputSize += lntypes.VByte(txOut.SerializeSize()) twe.outputCount++ return twe @@ -1028,7 +1028,7 @@ func (twe *TxWeightEstimator) AddP2SHOutput() *TxWeightEstimator { // AddOutput estimates the weight of an output based on the pkScript. func (twe *TxWeightEstimator) AddOutput(pkScript []byte) *TxWeightEstimator { - twe.outputSize += BaseOutputSize + len(pkScript) + twe.outputSize += BaseOutputSize + lntypes.VByte(len(pkScript)) twe.outputCount++ return twe @@ -1036,9 +1036,10 @@ func (twe *TxWeightEstimator) AddOutput(pkScript []byte) *TxWeightEstimator { // Weight gets the estimated weight of the transaction. func (twe *TxWeightEstimator) Weight() lntypes.WeightUnit { - txSizeStripped := BaseTxSize + - wire.VarIntSerializeSize(uint64(twe.inputCount)) + twe.inputSize + - wire.VarIntSerializeSize(uint64(twe.outputCount)) + twe.outputSize + inputCount := wire.VarIntSerializeSize(uint64(twe.inputCount)) + outputCount := wire.VarIntSerializeSize(uint64(twe.outputCount)) + txSizeStripped := BaseTxSize + lntypes.VByte(inputCount) + + twe.inputSize + lntypes.VByte(outputCount) + twe.outputSize weight := lntypes.WeightUnit(txSizeStripped * witnessScaleFactor) if twe.hasWitness { diff --git a/lnwallet/chainfee/rates.go b/lnwallet/chainfee/rates.go index 0ea0a277d..f5294e4d1 100644 --- a/lnwallet/chainfee/rates.go +++ b/lnwallet/chainfee/rates.go @@ -42,7 +42,7 @@ type SatPerKVByte btcutil.Amount // FeeForVSize calculates the fee resulting from this fee rate and the given // vsize in vbytes. -func (s SatPerKVByte) FeeForVSize(vbytes int64) btcutil.Amount { +func (s SatPerKVByte) FeeForVSize(vbytes lntypes.VByte) btcutil.Amount { return btcutil.Amount(s) * btcutil.Amount(vbytes) / 1000 } @@ -73,7 +73,7 @@ func (s SatPerKWeight) FeeForWeight(wu lntypes.WeightUnit) btcutil.Amount { // FeeForVByte calculates the fee resulting from this fee rate and the given // size in vbytes (vb). -func (s SatPerKWeight) FeeForVByte(vb int64) btcutil.Amount { +func (s SatPerKWeight) FeeForVByte(vb lntypes.VByte) btcutil.Amount { return s.FeePerKVByte().FeeForVSize(vb) } From 5e8452cc5d6395d2290860721b94e1ec0dbf69d8 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 24 May 2024 23:47:04 +0800 Subject: [PATCH 108/109] sweep: make sure the full input is accounted Fix the case where previously only the witness data is taken into account when calculating the fees. --- sweep/aggregator.go | 34 ++++++++++++++++++++++++++-------- sweep/aggregator_test.go | 25 ++++++++++++++++--------- 2 files changed, 42 insertions(+), 17 deletions(-) diff --git a/sweep/aggregator.go b/sweep/aggregator.go index 801ac6b83..6028adca3 100644 --- a/sweep/aggregator.go +++ b/sweep/aggregator.go @@ -5,6 +5,8 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/wire" + "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/chainfee" ) @@ -201,8 +203,8 @@ func (b *BudgetAggregator) filterInputs(inputs InputsMap) InputsMap { for _, pi := range inputs { op := pi.OutPoint() - // Get the size and skip if there's an error. - size, _, err := pi.WitnessType().SizeUpperBound() + // Get the size of the witness and skip if there's an error. + witnessSize, _, err := pi.WitnessType().SizeUpperBound() if err != nil { log.Warnf("Skipped input=%v: cannot get its size: %v", op, err) @@ -210,12 +212,27 @@ func (b *BudgetAggregator) filterInputs(inputs InputsMap) InputsMap { continue } + //nolint:lll + // Calculate the size if the input is included in the tx. + // + // NOTE: When including this input, we need to account the + // non-witness data which is expressed in vb. + // + // TODO(yy): This is not accurate for tapscript input. We need + // to unify calculations used in the `TxWeightEstimator` inside + // `input/size.go` and `weightEstimator` in + // `weight_estimator.go`. And calculate the expected weights + // similar to BOLT-3: + // https://github.com/lightning/bolts/blob/master/03-transactions.md#appendix-a-expected-weights + wu := lntypes.VByte(input.InputSize).ToWU() + witnessSize + // Skip inputs that has too little budget. - minFee := minFeeRate.FeeForWeight(size) + minFee := minFeeRate.FeeForWeight(wu) if pi.params.Budget < minFee { log.Warnf("Skipped input=%v: has budget=%v, but the "+ - "min fee requires %v", op, pi.params.Budget, - minFee) + "min fee requires %v (feerate=%v), size=%v", op, + pi.params.Budget, minFee, + minFeeRate.FeePerVByte(), wu.ToVB()) continue } @@ -224,11 +241,12 @@ func (b *BudgetAggregator) filterInputs(inputs InputsMap) InputsMap { startingFeeRate := pi.params.StartingFeeRate.UnwrapOr( chainfee.SatPerKWeight(0), ) - startingFee := startingFeeRate.FeeForWeight(size) + startingFee := startingFeeRate.FeeForWeight(wu) if pi.params.Budget < startingFee { log.Errorf("Skipped input=%v: has budget=%v, but the "+ - "starting fee requires %v", op, - pi.params.Budget, minFee) + "starting fee requires %v (feerate=%v), "+ + "size=%v", op, pi.params.Budget, startingFee, + startingFeeRate.FeePerVByte(), wu.ToVB()) continue } diff --git a/sweep/aggregator_test.go b/sweep/aggregator_test.go index 0b60bc3a7..a32c849a0 100644 --- a/sweep/aggregator_test.go +++ b/sweep/aggregator_test.go @@ -43,8 +43,11 @@ func TestBudgetAggregatorFilterInputs(t *testing.T) { defer wt.AssertExpectations(t) // Mock the `SizeUpperBound` method to return the size four times. - const wtSize lntypes.WeightUnit = 100 - wt.On("SizeUpperBound").Return(wtSize, true, nil).Times(4) + const wu lntypes.WeightUnit = 100 + wt.On("SizeUpperBound").Return(wu, true, nil).Times(4) + + // Calculate the input size. + inpSize := lntypes.VByte(input.InputSize).ToWU() + wu // Create a mock input that will be filtered out due to error. inpErr := &input.MockInput{} @@ -64,9 +67,9 @@ func TestBudgetAggregatorFilterInputs(t *testing.T) { var ( // Define three budget values, one below the min fee rate, one // above and one equal to it. - budgetLow = minFeeRate.FeeForWeight(wtSize) - 1 - budgetEqual = minFeeRate.FeeForWeight(wtSize) - budgetHigh = minFeeRate.FeeForWeight(wtSize) + 1 + budgetLow = minFeeRate.FeeForWeight(inpSize) - 1 + budgetEqual = minFeeRate.FeeForWeight(inpSize) + budgetHigh = minFeeRate.FeeForWeight(inpSize) + 1 // Define three outpoints with different budget values. opLow = wire.OutPoint{Hash: chainhash.Hash{2}} @@ -398,8 +401,12 @@ func TestBudgetInputSetClusterInputs(t *testing.T) { // Mock the `SizeUpperBound` method to return the size 10 times since // we are using ten inputs. - const wtSize lntypes.WeightUnit = 100 - wt.On("SizeUpperBound").Return(wtSize, true, nil).Times(10) + const wu lntypes.WeightUnit = 100 + wt.On("SizeUpperBound").Return(wu, true, nil).Times(10) + + // Calculate the input size. + inpSize := lntypes.VByte(input.InputSize).ToWU() + wu + wt.On("String").Return("mock witness type") // Mock the estimator to return a constant fee rate. @@ -409,8 +416,8 @@ func TestBudgetInputSetClusterInputs(t *testing.T) { var ( // Define two budget values, one below the min fee rate and one // above it. - budgetLow = minFeeRate.FeeForWeight(wtSize) - 1 - budgetHigh = minFeeRate.FeeForWeight(wtSize) + 1 + budgetLow = minFeeRate.FeeForWeight(inpSize) - 1 + budgetHigh = minFeeRate.FeeForWeight(inpSize) + 1 // Create three deadline heights, which means there are three // groups of inputs to be expected. From 2e40a23146384c4030f66e4f069c0b10d81afee2 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Sat, 25 May 2024 00:08:54 +0800 Subject: [PATCH 109/109] lnrpc: fix linter --- lnrpc/walletrpc/walletkit_server.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/lnrpc/walletrpc/walletkit_server.go b/lnrpc/walletrpc/walletkit_server.go index f5ac051b3..4c3996515 100644 --- a/lnrpc/walletrpc/walletkit_server.go +++ b/lnrpc/walletrpc/walletkit_server.go @@ -1660,8 +1660,6 @@ func (w *WalletKit) fundPsbtInternalWallet(account string, // fundPsbtCoinSelect uses the "new" PSBT funding method using the channel // funding coin selection algorithm that allows specifying custom inputs while // selecting coins. -// -//nolint:funlen func (w *WalletKit) fundPsbtCoinSelect(account string, changeIndex int32, packet *psbt.Packet, minConfs int32, changeType chanfunding.ChangeAddressType,