From c7d216015375189f6ba1dabf9068e7c92eea50cd Mon Sep 17 00:00:00 2001 From: Slyghtning Date: Thu, 11 Apr 2024 14:31:10 +0200 Subject: [PATCH] add all in one commit for the moment --- cmd/loop/staticaddr.go | 116 +++ loopd/daemon.go | 47 ++ loopd/perms/perms.go | 7 + loopd/swapclient_server.go | 64 ++ .../000008_static_address_deposits.up.sql | 6 +- loopdb/sqlc/models.go | 15 +- .../sqlc/queries/static_address_deposits.sql | 9 +- loopdb/sqlc/static_address_deposits.sql.go | 40 +- looprpc/client.pb.go | 661 ++++++++++++------ looprpc/client.proto | 38 + looprpc/client.swagger.json | 22 + looprpc/client_grpc.pb.go | 40 ++ looprpc/swapclient.pb.json.go | 25 + staticaddr/deposit/actions.go | 16 + staticaddr/deposit/deposit.go | 9 +- staticaddr/deposit/fsm.go | 52 +- staticaddr/deposit/manager.go | 83 +++ staticaddr/deposit/sql_store.go | 14 +- staticaddr/withdraw/interface.go | 44 ++ staticaddr/withdraw/log.go | 24 + staticaddr/withdraw/manager.go | 649 +++++++++++++++++ swapserverrpc/withdraw.pb.go | 363 ++++++++++ swapserverrpc/withdraw.proto | 57 ++ swapserverrpc/withdraw_grpc.pb.go | 107 +++ 24 files changed, 2258 insertions(+), 250 deletions(-) create mode 100644 staticaddr/withdraw/interface.go create mode 100644 staticaddr/withdraw/log.go create mode 100644 staticaddr/withdraw/manager.go create mode 100644 swapserverrpc/withdraw.pb.go create mode 100644 swapserverrpc/withdraw.proto create mode 100644 swapserverrpc/withdraw_grpc.pb.go diff --git a/cmd/loop/staticaddr.go b/cmd/loop/staticaddr.go index 40c2e01..7525416 100644 --- a/cmd/loop/staticaddr.go +++ b/cmd/loop/staticaddr.go @@ -2,8 +2,13 @@ package main import ( "context" + "encoding/hex" + "errors" "fmt" + "strconv" + "strings" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/lightninglabs/loop/looprpc" "github.com/urfave/cli" ) @@ -16,6 +21,7 @@ var staticAddressCommands = cli.Command{ Subcommands: []cli.Command{ newStaticAddressCommand, listUnspentCommand, + withdrawalCommand, }, } @@ -104,3 +110,113 @@ func listUnspent(ctx *cli.Context) error { return nil } + +var withdrawalCommand = cli.Command{ + Name: "withdraw", + ShortName: "w", + Usage: "Withdraw from static address deposits.", + Description: ` + Withdraws from all or selected static address deposits by sweeping them + back to our lnd wallet. + `, + Flags: []cli.Flag{ + cli.StringSliceFlag{ + Name: "utxo", + Usage: "specify utxos as outpoints(tx:idx) which will" + + "be closed.", + }, + cli.BoolFlag{ + Name: "all", + Usage: "withdraws all static address deposits.", + }, + }, + Action: withdraw, +} + +func withdraw(ctx *cli.Context) error { + if ctx.NArg() > 0 { + return cli.ShowCommandHelp(ctx, "withdraw") + } + + client, cleanup, err := getClient(ctx) + if err != nil { + return err + } + defer cleanup() + + var ( + req = &looprpc.WithdrawDepositsRequest{} + isAllSelected = ctx.IsSet("all") + isUtxoSelected = ctx.IsSet("utxo") + outpoints []*looprpc.OutPoint + ctxb = context.Background() + ) + + switch { + case isAllSelected == isUtxoSelected: + return errors.New("must select either all or some utxos") + + case isAllSelected: + case isUtxoSelected: + utxos := ctx.StringSlice("utxo") + outpoints, err = utxosToOutpoints(utxos) + if err != nil { + return err + } + + req.Outpoints = outpoints + + default: + return fmt.Errorf("unknown withdrawal request") + } + + resp, err := client.WithdrawDeposits(ctxb, &looprpc.WithdrawDepositsRequest{ + Outpoints: outpoints, + All: isAllSelected, + }) + if err != nil { + return err + } + + printRespJSON(resp) + + return nil +} + +func utxosToOutpoints(utxos []string) ([]*looprpc.OutPoint, error) { + var outpoints []*looprpc.OutPoint + if len(utxos) == 0 { + return nil, fmt.Errorf("no utxos specified") + } + for _, utxo := range utxos { + outpoint, err := NewProtoOutPoint(utxo) + if err != nil { + return nil, err + } + outpoints = append(outpoints, outpoint) + } + + return outpoints, nil +} + +// NewProtoOutPoint parses an OutPoint into its corresponding lnrpc.OutPoint +// type. +func NewProtoOutPoint(op string) (*looprpc.OutPoint, error) { + parts := strings.Split(op, ":") + if len(parts) != 2 { + return nil, errors.New("outpoint should be of the form " + + "txid:index") + } + txid := parts[0] + if hex.DecodedLen(len(txid)) != chainhash.HashSize { + return nil, fmt.Errorf("invalid hex-encoded txid %v", txid) + } + outputIndex, err := strconv.Atoi(parts[1]) + if err != nil { + return nil, fmt.Errorf("invalid output index: %v", err) + } + return &looprpc.OutPoint{ + TxidStr: txid, + OutputIndex: uint32(outputIndex), + }, nil +} diff --git a/loopd/daemon.go b/loopd/daemon.go index 67671e1..8c127ed 100644 --- a/loopd/daemon.go +++ b/loopd/daemon.go @@ -23,6 +23,7 @@ import ( loop_looprpc "github.com/lightninglabs/loop/looprpc" "github.com/lightninglabs/loop/staticaddr/address" "github.com/lightninglabs/loop/staticaddr/deposit" + "github.com/lightninglabs/loop/staticaddr/withdraw" loop_swaprpc "github.com/lightninglabs/loop/swapserverrpc" "github.com/lightninglabs/loop/sweepbatcher" "github.com/lightningnetwork/lnd/clock" @@ -437,6 +438,12 @@ func (d *Daemon) initialize(withMacaroonService bool) error { swapClient.Conn, ) + // Create a static address client that cooperatively closes deposits + // with the server. + withdrawalClient := loop_swaprpc.NewWithdrawalServerClient( + swapClient.Conn, + ) + // Both the client RPC server and the swap server client should stop // on main context cancel. So we create it early and pass it down. d.mainCtx, d.mainCtxCancel = context.WithCancel(context.Background()) @@ -500,6 +507,7 @@ func (d *Daemon) initialize(withMacaroonService bool) error { staticAddressManager *address.Manager depositManager *deposit.Manager + withdrawalManager *withdraw.Manager ) // Create the reservation and instantout managers. if d.cfg.EnableExperimental { @@ -561,6 +569,18 @@ func (d *Daemon) initialize(withMacaroonService bool) error { Signer: d.lnd.Signer, } depositManager = deposit.NewManager(depoCfg) + + // Static address deposit withdrawal manager setup. + closeCfg := &withdraw.ManagerConfig{ + WithdrawalServerClient: withdrawalClient, + AddressManager: staticAddressManager, + DepositManager: depositManager, + WalletKit: d.lnd.WalletKit, + ChainParams: d.lnd.ChainParams, + ChainNotifier: d.lnd.ChainNotifier, + Signer: d.lnd.Signer, + } + withdrawalManager = withdraw.NewManager(closeCfg) } // Now finally fully initialize the swap client RPC server instance. @@ -578,6 +598,7 @@ func (d *Daemon) initialize(withMacaroonService bool) error { instantOutManager: instantOutManager, staticAddressManager: staticAddressManager, depositManager: depositManager, + withdrawalManager: withdrawalManager, } // Retrieve all currently existing swaps from the database. @@ -709,6 +730,32 @@ func (d *Daemon) initialize(withMacaroonService bool) error { depositManager.WaitInitComplete() } + // Start the static address deposit withdrawal manager. + if withdrawalManager != nil { + d.wg.Add(1) + go func() { + defer d.wg.Done() + + // Lnd's GetInfo call supplies us with the current block + // height. + info, err := d.lnd.Client.GetInfo(d.mainCtx) + if err != nil { + d.internalErrChan <- err + return + } + + log.Info("Starting static address deposit withdrawal " + + "manager...") + err = withdrawalManager.Run(d.mainCtx, info.BlockHeight) + if err != nil && !errors.Is(context.Canceled, err) { + d.internalErrChan <- err + } + log.Info("Static address deposit withdrawal manager " + + "stopped") + }() + withdrawalManager.WaitInitComplete() + } + // Last, start our internal error handler. This will return exactly one // error or nil on the main error channel to inform the caller that // something went wrong or that shutdown is complete. We don't add to diff --git a/loopd/perms/perms.go b/loopd/perms/perms.go index db2047b..37bd766 100644 --- a/loopd/perms/perms.go +++ b/loopd/perms/perms.go @@ -83,6 +83,13 @@ var RequiredPermissions = map[string][]bakery.Op{ Entity: "loop", Action: "in", }}, + "/looprpc.SwapClient/WithdrawDeposits": {{ + Entity: "swap", + Action: "execute", + }, { + Entity: "loop", + Action: "in", + }}, "/looprpc.SwapClient/GetLsatTokens": {{ Entity: "auth", Action: "read", diff --git a/loopd/swapclient_server.go b/loopd/swapclient_server.go index 1ead858..92f9535 100644 --- a/loopd/swapclient_server.go +++ b/loopd/swapclient_server.go @@ -15,6 +15,7 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/wire" "github.com/lightninglabs/aperture/lsat" "github.com/lightninglabs/lndclient" "github.com/lightninglabs/loop" @@ -26,6 +27,7 @@ import ( clientrpc "github.com/lightninglabs/loop/looprpc" "github.com/lightninglabs/loop/staticaddr/address" "github.com/lightninglabs/loop/staticaddr/deposit" + "github.com/lightninglabs/loop/staticaddr/withdraw" "github.com/lightninglabs/loop/swap" looprpc "github.com/lightninglabs/loop/swapserverrpc" "github.com/lightningnetwork/lnd/lnrpc/walletrpc" @@ -87,6 +89,7 @@ type swapClientServer struct { instantOutManager *instantout.Manager staticAddressManager *address.Manager depositManager *deposit.Manager + withdrawalManager *withdraw.Manager swaps map[lntypes.Hash]loop.SwapInfo subscribers map[int]chan<- interface{} statusChan chan loop.SwapInfo @@ -1278,6 +1281,67 @@ func (s *swapClientServer) ListUnspent(ctx context.Context, return &clientrpc.ListUnspentResponse{Utxos: respUtxos}, nil } +// WithdrawDeposits tries to obtain a partial signature from the server to spend +// the selected deposits to the client's wallet. +func (s *swapClientServer) WithdrawDeposits(ctx context.Context, + req *clientrpc.WithdrawDepositsRequest) ( + *clientrpc.WithdrawDepositsResponse, error) { + + var ( + isAllSelected = req.All + isUtxoSelected = req.Outpoints != nil + outpoints []wire.OutPoint + err error + ) + + switch { + case isAllSelected == isUtxoSelected: + return nil, fmt.Errorf("must select either all or some utxos") + + case isAllSelected: + deposits, err := s.depositManager.GetActiveDepositsInState( + deposit.Deposited, + ) + if err != nil { + return nil, err + } + + for _, d := range deposits { + outpoints = append(outpoints, d.OutPoint) + } + + case isUtxoSelected: + outpoints, err = toServerOutpoints(req.Outpoints) + if err != nil { + return nil, err + } + } + + err = s.withdrawalManager.WithdrawDeposits(ctx, outpoints) + if err != nil { + return nil, err + } + + return &clientrpc.WithdrawDepositsResponse{}, err +} + +func toServerOutpoints(outpoints []*clientrpc.OutPoint) ([]wire.OutPoint, + error) { + + var serverOutpoints []wire.OutPoint + for _, o := range outpoints { + outpointStr := fmt.Sprintf("%s:%d", o.TxidStr, o.OutputIndex) + newOutpoint, err := wire.NewOutPointFromString(outpointStr) + if err != nil { + return nil, err + } + + serverOutpoints = append(serverOutpoints, *newOutpoint) + } + + return serverOutpoints, nil +} + func rpcAutoloopReason(reason liquidity.Reason) (clientrpc.AutoReason, error) { switch reason { case liquidity.ReasonNone: diff --git a/loopdb/sqlc/migrations/000008_static_address_deposits.up.sql b/loopdb/sqlc/migrations/000008_static_address_deposits.up.sql index 98585a8..6d6e296 100644 --- a/loopdb/sqlc/migrations/000008_static_address_deposits.up.sql +++ b/loopdb/sqlc/migrations/000008_static_address_deposits.up.sql @@ -21,7 +21,11 @@ CREATE TABLE IF NOT EXISTS deposits ( -- timeout_sweep_pk_script is the public key script that will be used to -- sweep the deposit after has expired. - timeout_sweep_pk_script BYTEA NOT NULL + timeout_sweep_pk_script BYTEA NOT NULL, + + -- withdrawal_sweep_pk_script is the address that will be used to sweep the + -- deposit cooperatively with the server before it has expired. + withdrawal_sweep_address TEXT ); -- deposit_updates contains all the updates to a deposit. diff --git a/loopdb/sqlc/models.go b/loopdb/sqlc/models.go index e3e7e51..f41698d 100644 --- a/loopdb/sqlc/models.go +++ b/loopdb/sqlc/models.go @@ -10,13 +10,14 @@ import ( ) type Deposit struct { - ID int32 - DepositID []byte - TxHash []byte - OutIndex int32 - Amount int64 - ConfirmationHeight int64 - TimeoutSweepPkScript []byte + ID int32 + DepositID []byte + TxHash []byte + OutIndex int32 + Amount int64 + ConfirmationHeight int64 + TimeoutSweepPkScript []byte + WithdrawalSweepAddress sql.NullString } type DepositUpdate struct { diff --git a/loopdb/sqlc/queries/static_address_deposits.sql b/loopdb/sqlc/queries/static_address_deposits.sql index d576151..05d1680 100644 --- a/loopdb/sqlc/queries/static_address_deposits.sql +++ b/loopdb/sqlc/queries/static_address_deposits.sql @@ -5,14 +5,16 @@ INSERT INTO deposits ( out_index, amount, confirmation_height, - timeout_sweep_pk_script + timeout_sweep_pk_script, + withdrawal_sweep_address ) VALUES ( $1, $2, $3, $4, $5, - $6 + $6, + $7 ); -- name: UpdateDeposit :exec @@ -20,7 +22,8 @@ UPDATE deposits SET tx_hash = $2, out_index = $3, - confirmation_height = $4 + confirmation_height = $4, + withdrawal_sweep_address = $5 WHERE deposits.deposit_id = $1; diff --git a/loopdb/sqlc/static_address_deposits.sql.go b/loopdb/sqlc/static_address_deposits.sql.go index d33330d..d2acead 100644 --- a/loopdb/sqlc/static_address_deposits.sql.go +++ b/loopdb/sqlc/static_address_deposits.sql.go @@ -7,12 +7,13 @@ package sqlc import ( "context" + "database/sql" "time" ) const allDeposits = `-- name: AllDeposits :many SELECT - id, deposit_id, tx_hash, out_index, amount, confirmation_height, timeout_sweep_pk_script + id, deposit_id, tx_hash, out_index, amount, confirmation_height, timeout_sweep_pk_script, withdrawal_sweep_address FROM deposits ORDER BY @@ -36,6 +37,7 @@ func (q *Queries) AllDeposits(ctx context.Context) ([]Deposit, error) { &i.Amount, &i.ConfirmationHeight, &i.TimeoutSweepPkScript, + &i.WithdrawalSweepAddress, ); err != nil { return nil, err } @@ -57,24 +59,27 @@ INSERT INTO deposits ( out_index, amount, confirmation_height, - timeout_sweep_pk_script + timeout_sweep_pk_script, + withdrawal_sweep_address ) VALUES ( $1, $2, $3, $4, $5, - $6 + $6, + $7 ) ` type CreateDepositParams struct { - DepositID []byte - TxHash []byte - OutIndex int32 - Amount int64 - ConfirmationHeight int64 - TimeoutSweepPkScript []byte + DepositID []byte + TxHash []byte + OutIndex int32 + Amount int64 + ConfirmationHeight int64 + TimeoutSweepPkScript []byte + WithdrawalSweepAddress sql.NullString } func (q *Queries) CreateDeposit(ctx context.Context, arg CreateDepositParams) error { @@ -85,13 +90,14 @@ func (q *Queries) CreateDeposit(ctx context.Context, arg CreateDepositParams) er arg.Amount, arg.ConfirmationHeight, arg.TimeoutSweepPkScript, + arg.WithdrawalSweepAddress, ) return err } const getDeposit = `-- name: GetDeposit :one SELECT - id, deposit_id, tx_hash, out_index, amount, confirmation_height, timeout_sweep_pk_script + id, deposit_id, tx_hash, out_index, amount, confirmation_height, timeout_sweep_pk_script, withdrawal_sweep_address FROM deposits WHERE @@ -109,6 +115,7 @@ func (q *Queries) GetDeposit(ctx context.Context, depositID []byte) (Deposit, er &i.Amount, &i.ConfirmationHeight, &i.TimeoutSweepPkScript, + &i.WithdrawalSweepAddress, ) return i, err } @@ -165,16 +172,18 @@ UPDATE deposits SET tx_hash = $2, out_index = $3, - confirmation_height = $4 + confirmation_height = $4, + withdrawal_sweep_address = $5 WHERE deposits.deposit_id = $1 ` type UpdateDepositParams struct { - DepositID []byte - TxHash []byte - OutIndex int32 - ConfirmationHeight int64 + DepositID []byte + TxHash []byte + OutIndex int32 + ConfirmationHeight int64 + WithdrawalSweepAddress sql.NullString } func (q *Queries) UpdateDeposit(ctx context.Context, arg UpdateDepositParams) error { @@ -183,6 +192,7 @@ func (q *Queries) UpdateDeposit(ctx context.Context, arg UpdateDepositParams) er arg.TxHash, arg.OutIndex, arg.ConfirmationHeight, + arg.WithdrawalSweepAddress, ) return err } diff --git a/looprpc/client.pb.go b/looprpc/client.pb.go index 03d9b53..07080be 100644 --- a/looprpc/client.pb.go +++ b/looprpc/client.pb.go @@ -21,10 +21,11 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -// `AddressType` has to be one of: // -// - `unknown`: Unknown address type -// - `p2tr`: Pay to taproot pubkey (`TAPROOT_PUBKEY` = 1) +//`AddressType` has to be one of: +// +//- `unknown`: Unknown address type +//- `p2tr`: Pay to taproot pubkey (`TAPROOT_PUBKEY` = 1) type AddressType int32 const ( @@ -4162,6 +4163,172 @@ func (x *Utxo) GetConfirmations() int64 { return 0 } +type WithdrawDepositsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // + //The outpoints of the deposits to withdraw. + Outpoints []*OutPoint `protobuf:"bytes,1,rep,name=outpoints,proto3" json:"outpoints,omitempty"` + // + //If set to true, all deposits will be withdrawn. + All bool `protobuf:"varint,2,opt,name=all,proto3" json:"all,omitempty"` +} + +func (x *WithdrawDepositsRequest) Reset() { + *x = WithdrawDepositsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_client_proto_msgTypes[45] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WithdrawDepositsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WithdrawDepositsRequest) ProtoMessage() {} + +func (x *WithdrawDepositsRequest) ProtoReflect() protoreflect.Message { + mi := &file_client_proto_msgTypes[45] + 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 WithdrawDepositsRequest.ProtoReflect.Descriptor instead. +func (*WithdrawDepositsRequest) Descriptor() ([]byte, []int) { + return file_client_proto_rawDescGZIP(), []int{45} +} + +func (x *WithdrawDepositsRequest) GetOutpoints() []*OutPoint { + if x != nil { + return x.Outpoints + } + return nil +} + +func (x *WithdrawDepositsRequest) GetAll() bool { + if x != nil { + return x.All + } + return false +} + +type WithdrawDepositsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *WithdrawDepositsResponse) Reset() { + *x = WithdrawDepositsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_client_proto_msgTypes[46] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WithdrawDepositsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WithdrawDepositsResponse) ProtoMessage() {} + +func (x *WithdrawDepositsResponse) ProtoReflect() protoreflect.Message { + mi := &file_client_proto_msgTypes[46] + 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 WithdrawDepositsResponse.ProtoReflect.Descriptor instead. +func (*WithdrawDepositsResponse) Descriptor() ([]byte, []int) { + return file_client_proto_rawDescGZIP(), []int{46} +} + +type OutPoint struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // + //Raw bytes representing the transaction id. + TxidBytes []byte `protobuf:"bytes,1,opt,name=txid_bytes,json=txidBytes,proto3" json:"txid_bytes,omitempty"` + // + //Reversed, hex-encoded string representing the transaction id. + TxidStr string `protobuf:"bytes,2,opt,name=txid_str,json=txidStr,proto3" json:"txid_str,omitempty"` + // + //The index of the output on the transaction. + OutputIndex uint32 `protobuf:"varint,3,opt,name=output_index,json=outputIndex,proto3" json:"output_index,omitempty"` +} + +func (x *OutPoint) Reset() { + *x = OutPoint{} + if protoimpl.UnsafeEnabled { + mi := &file_client_proto_msgTypes[47] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *OutPoint) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OutPoint) ProtoMessage() {} + +func (x *OutPoint) ProtoReflect() protoreflect.Message { + mi := &file_client_proto_msgTypes[47] + 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 OutPoint.ProtoReflect.Descriptor instead. +func (*OutPoint) Descriptor() ([]byte, []int) { + return file_client_proto_rawDescGZIP(), []int{47} +} + +func (x *OutPoint) GetTxidBytes() []byte { + if x != nil { + return x.TxidBytes + } + return nil +} + +func (x *OutPoint) GetTxidStr() string { + if x != nil { + return x.TxidStr + } + return "" +} + +func (x *OutPoint) GetOutputIndex() uint32 { + if x != nil { + return x.OutputIndex + } + return 0 +} + var File_client_proto protoreflect.FileDescriptor var file_client_proto_rawDesc = []byte{ @@ -4654,169 +4821,189 @@ var file_client_proto_rawDesc = []byte{ 0x52, 0x08, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x2a, 0x3b, 0x0a, 0x0b, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x18, 0x0a, 0x14, 0x41, 0x44, 0x44, 0x52, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, - 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x54, 0x41, 0x50, - 0x52, 0x4f, 0x4f, 0x54, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, 0x59, 0x10, 0x01, 0x2a, 0x25, 0x0a, - 0x08, 0x53, 0x77, 0x61, 0x70, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x4c, 0x4f, 0x4f, - 0x50, 0x5f, 0x4f, 0x55, 0x54, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x4c, 0x4f, 0x4f, 0x50, 0x5f, - 0x49, 0x4e, 0x10, 0x01, 0x2a, 0x73, 0x0a, 0x09, 0x53, 0x77, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x54, 0x45, 0x44, 0x10, 0x00, - 0x12, 0x15, 0x0a, 0x11, 0x50, 0x52, 0x45, 0x49, 0x4d, 0x41, 0x47, 0x45, 0x5f, 0x52, 0x45, 0x56, - 0x45, 0x41, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x48, 0x54, 0x4c, 0x43, 0x5f, - 0x50, 0x55, 0x42, 0x4c, 0x49, 0x53, 0x48, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x53, - 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c, - 0x45, 0x44, 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f, 0x49, 0x4e, 0x56, 0x4f, 0x49, 0x43, 0x45, 0x5f, - 0x53, 0x45, 0x54, 0x54, 0x4c, 0x45, 0x44, 0x10, 0x05, 0x2a, 0xeb, 0x02, 0x0a, 0x0d, 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, 0x1b, 0x0a, 0x17, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, - 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4f, 0x46, 0x46, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x10, - 0x01, 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, 0x02, 0x12, 0x20, 0x0a, - 0x1c, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, - 0x53, 0x57, 0x45, 0x45, 0x50, 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, 0x03, 0x12, - 0x25, 0x0a, 0x21, 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, 0x56, - 0x41, 0x4c, 0x55, 0x45, 0x10, 0x04, 0x12, 0x1c, 0x0a, 0x18, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, - 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x54, 0x45, 0x4d, 0x50, 0x4f, 0x52, 0x41, - 0x52, 0x59, 0x10, 0x05, 0x12, 0x23, 0x0a, 0x1f, 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, 0x41, 0x4d, 0x4f, 0x55, 0x4e, 0x54, 0x10, 0x06, 0x12, 0x1c, 0x0a, 0x18, 0x46, 0x41, 0x49, - 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x41, 0x42, 0x41, 0x4e, - 0x44, 0x4f, 0x4e, 0x45, 0x44, 0x10, 0x07, 0x12, 0x31, 0x0a, 0x2d, 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, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x52, 0x4d, 0x45, 0x44, - 0x5f, 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x08, 0x12, 0x2b, 0x0a, 0x27, 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, 0x48, 0x54, 0x4c, 0x43, 0x5f, 0x41, 0x4d, 0x54, 0x5f, - 0x53, 0x57, 0x45, 0x50, 0x54, 0x10, 0x09, 0x2a, 0x2f, 0x0a, 0x11, 0x4c, 0x69, 0x71, 0x75, 0x69, - 0x64, 0x69, 0x74, 0x79, 0x52, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, - 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x48, 0x52, - 0x45, 0x53, 0x48, 0x4f, 0x4c, 0x44, 0x10, 0x01, 0x2a, 0xa6, 0x03, 0x0a, 0x0a, 0x41, 0x75, 0x74, - 0x6f, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x13, 0x41, 0x55, 0x54, 0x4f, 0x5f, - 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, - 0x12, 0x22, 0x0a, 0x1e, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, - 0x42, 0x55, 0x44, 0x47, 0x45, 0x54, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, - 0x45, 0x44, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, - 0x53, 0x4f, 0x4e, 0x5f, 0x53, 0x57, 0x45, 0x45, 0x50, 0x5f, 0x46, 0x45, 0x45, 0x53, 0x10, 0x02, - 0x12, 0x1e, 0x0a, 0x1a, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, - 0x42, 0x55, 0x44, 0x47, 0x45, 0x54, 0x5f, 0x45, 0x4c, 0x41, 0x50, 0x53, 0x45, 0x44, 0x10, 0x03, - 0x12, 0x19, 0x0a, 0x15, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, - 0x49, 0x4e, 0x5f, 0x46, 0x4c, 0x49, 0x47, 0x48, 0x54, 0x10, 0x04, 0x12, 0x18, 0x0a, 0x14, 0x41, - 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x53, 0x57, 0x41, 0x50, 0x5f, - 0x46, 0x45, 0x45, 0x10, 0x05, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, - 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4d, 0x49, 0x4e, 0x45, 0x52, 0x5f, 0x46, 0x45, 0x45, 0x10, 0x06, - 0x12, 0x16, 0x0a, 0x12, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, - 0x50, 0x52, 0x45, 0x50, 0x41, 0x59, 0x10, 0x07, 0x12, 0x1f, 0x0a, 0x1b, 0x41, 0x55, 0x54, 0x4f, - 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, - 0x42, 0x41, 0x43, 0x4b, 0x4f, 0x46, 0x46, 0x10, 0x08, 0x12, 0x18, 0x0a, 0x14, 0x41, 0x55, 0x54, - 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4c, 0x4f, 0x4f, 0x50, 0x5f, 0x4f, 0x55, - 0x54, 0x10, 0x09, 0x12, 0x17, 0x0a, 0x13, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, - 0x4f, 0x4e, 0x5f, 0x4c, 0x4f, 0x4f, 0x50, 0x5f, 0x49, 0x4e, 0x10, 0x0a, 0x12, 0x1c, 0x0a, 0x18, - 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4c, 0x49, 0x51, 0x55, - 0x49, 0x44, 0x49, 0x54, 0x59, 0x5f, 0x4f, 0x4b, 0x10, 0x0b, 0x12, 0x23, 0x0a, 0x1f, 0x41, 0x55, - 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x42, 0x55, 0x44, 0x47, 0x45, 0x54, - 0x5f, 0x49, 0x4e, 0x53, 0x55, 0x46, 0x46, 0x49, 0x43, 0x49, 0x45, 0x4e, 0x54, 0x10, 0x0c, 0x12, - 0x20, 0x0a, 0x1c, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x46, - 0x45, 0x45, 0x5f, 0x49, 0x4e, 0x53, 0x55, 0x46, 0x46, 0x49, 0x43, 0x49, 0x45, 0x4e, 0x54, 0x10, - 0x0d, 0x32, 0xd1, 0x0b, 0x0a, 0x0a, 0x53, 0x77, 0x61, 0x70, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x12, 0x39, 0x0a, 0x07, 0x4c, 0x6f, 0x6f, 0x70, 0x4f, 0x75, 0x74, 0x12, 0x17, 0x2e, 0x6c, 0x6f, - 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x6f, 0x70, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, - 0x77, 0x61, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x06, 0x4c, - 0x6f, 0x6f, 0x70, 0x49, 0x6e, 0x12, 0x16, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, - 0x4c, 0x6f, 0x6f, 0x70, 0x49, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, - 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x77, 0x61, 0x70, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x07, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x12, - 0x17, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, - 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, - 0x70, 0x63, 0x2e, 0x53, 0x77, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x30, 0x01, 0x12, - 0x42, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x77, 0x61, 0x70, 0x73, 0x12, 0x19, 0x2e, 0x6c, - 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x77, 0x61, 0x70, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, - 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x77, 0x61, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x12, - 0x18, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, - 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, - 0x72, 0x70, 0x63, 0x2e, 0x53, 0x77, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x48, - 0x0a, 0x0b, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x53, 0x77, 0x61, 0x70, 0x12, 0x1b, 0x2e, + 0x22, 0x5c, 0x0a, 0x17, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x44, 0x65, 0x70, 0x6f, + 0x73, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x09, 0x6f, + 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, + 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, + 0x74, 0x52, 0x09, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, + 0x61, 0x6c, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x61, 0x6c, 0x6c, 0x22, 0x1a, + 0x0a, 0x18, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x67, 0x0a, 0x08, 0x4f, 0x75, + 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x78, 0x69, 0x64, 0x5f, 0x62, + 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x74, 0x78, 0x69, 0x64, + 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x78, 0x69, 0x64, 0x5f, 0x73, 0x74, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x78, 0x69, 0x64, 0x53, 0x74, 0x72, + 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x49, 0x6e, + 0x64, 0x65, 0x78, 0x2a, 0x3b, 0x0a, 0x0b, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x41, 0x44, 0x44, 0x52, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, + 0x54, 0x41, 0x50, 0x52, 0x4f, 0x4f, 0x54, 0x5f, 0x50, 0x55, 0x42, 0x4b, 0x45, 0x59, 0x10, 0x01, + 0x2a, 0x25, 0x0a, 0x08, 0x53, 0x77, 0x61, 0x70, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0c, 0x0a, 0x08, + 0x4c, 0x4f, 0x4f, 0x50, 0x5f, 0x4f, 0x55, 0x54, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x4c, 0x4f, + 0x4f, 0x50, 0x5f, 0x49, 0x4e, 0x10, 0x01, 0x2a, 0x73, 0x0a, 0x09, 0x53, 0x77, 0x61, 0x70, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x54, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x50, 0x52, 0x45, 0x49, 0x4d, 0x41, 0x47, 0x45, 0x5f, + 0x52, 0x45, 0x56, 0x45, 0x41, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x48, 0x54, + 0x4c, 0x43, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x53, 0x48, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0b, + 0x0a, 0x07, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x46, + 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f, 0x49, 0x4e, 0x56, 0x4f, 0x49, + 0x43, 0x45, 0x5f, 0x53, 0x45, 0x54, 0x54, 0x4c, 0x45, 0x44, 0x10, 0x05, 0x2a, 0xeb, 0x02, 0x0a, + 0x0d, 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, 0x1b, 0x0a, 0x17, 0x46, 0x41, 0x49, 0x4c, 0x55, + 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4f, 0x46, 0x46, 0x43, 0x48, 0x41, + 0x49, 0x4e, 0x10, 0x01, 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, 0x02, + 0x12, 0x20, 0x0a, 0x1c, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, + 0x4f, 0x4e, 0x5f, 0x53, 0x57, 0x45, 0x45, 0x50, 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, + 0x10, 0x03, 0x12, 0x25, 0x0a, 0x21, 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, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x10, 0x04, 0x12, 0x1c, 0x0a, 0x18, 0x46, 0x41, 0x49, + 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x54, 0x45, 0x4d, 0x50, + 0x4f, 0x52, 0x41, 0x52, 0x59, 0x10, 0x05, 0x12, 0x23, 0x0a, 0x1f, 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, 0x41, 0x4d, 0x4f, 0x55, 0x4e, 0x54, 0x10, 0x06, 0x12, 0x1c, 0x0a, 0x18, + 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x41, + 0x42, 0x41, 0x4e, 0x44, 0x4f, 0x4e, 0x45, 0x44, 0x10, 0x07, 0x12, 0x31, 0x0a, 0x2d, 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, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x52, + 0x4d, 0x45, 0x44, 0x5f, 0x42, 0x41, 0x4c, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x08, 0x12, 0x2b, 0x0a, + 0x27, 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, 0x48, 0x54, 0x4c, 0x43, 0x5f, 0x41, + 0x4d, 0x54, 0x5f, 0x53, 0x57, 0x45, 0x50, 0x54, 0x10, 0x09, 0x2a, 0x2f, 0x0a, 0x11, 0x4c, 0x69, + 0x71, 0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x52, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, + 0x54, 0x48, 0x52, 0x45, 0x53, 0x48, 0x4f, 0x4c, 0x44, 0x10, 0x01, 0x2a, 0xa6, 0x03, 0x0a, 0x0a, + 0x41, 0x75, 0x74, 0x6f, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x13, 0x41, 0x55, + 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, + 0x4e, 0x10, 0x00, 0x12, 0x22, 0x0a, 0x1e, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, + 0x4f, 0x4e, 0x5f, 0x42, 0x55, 0x44, 0x47, 0x45, 0x54, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x53, 0x54, + 0x41, 0x52, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x41, 0x55, 0x54, 0x4f, 0x5f, + 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x53, 0x57, 0x45, 0x45, 0x50, 0x5f, 0x46, 0x45, 0x45, + 0x53, 0x10, 0x02, 0x12, 0x1e, 0x0a, 0x1a, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, + 0x4f, 0x4e, 0x5f, 0x42, 0x55, 0x44, 0x47, 0x45, 0x54, 0x5f, 0x45, 0x4c, 0x41, 0x50, 0x53, 0x45, + 0x44, 0x10, 0x03, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, + 0x4f, 0x4e, 0x5f, 0x49, 0x4e, 0x5f, 0x46, 0x4c, 0x49, 0x47, 0x48, 0x54, 0x10, 0x04, 0x12, 0x18, + 0x0a, 0x14, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x53, 0x57, + 0x41, 0x50, 0x5f, 0x46, 0x45, 0x45, 0x10, 0x05, 0x12, 0x19, 0x0a, 0x15, 0x41, 0x55, 0x54, 0x4f, + 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4d, 0x49, 0x4e, 0x45, 0x52, 0x5f, 0x46, 0x45, + 0x45, 0x10, 0x06, 0x12, 0x16, 0x0a, 0x12, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, + 0x4f, 0x4e, 0x5f, 0x50, 0x52, 0x45, 0x50, 0x41, 0x59, 0x10, 0x07, 0x12, 0x1f, 0x0a, 0x1b, 0x41, + 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, + 0x52, 0x45, 0x5f, 0x42, 0x41, 0x43, 0x4b, 0x4f, 0x46, 0x46, 0x10, 0x08, 0x12, 0x18, 0x0a, 0x14, + 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4c, 0x4f, 0x4f, 0x50, + 0x5f, 0x4f, 0x55, 0x54, 0x10, 0x09, 0x12, 0x17, 0x0a, 0x13, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, + 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4c, 0x4f, 0x4f, 0x50, 0x5f, 0x49, 0x4e, 0x10, 0x0a, 0x12, + 0x1c, 0x0a, 0x18, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x4c, + 0x49, 0x51, 0x55, 0x49, 0x44, 0x49, 0x54, 0x59, 0x5f, 0x4f, 0x4b, 0x10, 0x0b, 0x12, 0x23, 0x0a, + 0x1f, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x5f, 0x42, 0x55, 0x44, + 0x47, 0x45, 0x54, 0x5f, 0x49, 0x4e, 0x53, 0x55, 0x46, 0x46, 0x49, 0x43, 0x49, 0x45, 0x4e, 0x54, + 0x10, 0x0c, 0x12, 0x20, 0x0a, 0x1c, 0x41, 0x55, 0x54, 0x4f, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, + 0x4e, 0x5f, 0x46, 0x45, 0x45, 0x5f, 0x49, 0x4e, 0x53, 0x55, 0x46, 0x46, 0x49, 0x43, 0x49, 0x45, + 0x4e, 0x54, 0x10, 0x0d, 0x32, 0xaa, 0x0c, 0x0a, 0x0a, 0x53, 0x77, 0x61, 0x70, 0x43, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x07, 0x4c, 0x6f, 0x6f, 0x70, 0x4f, 0x75, 0x74, 0x12, 0x17, + 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x6f, 0x70, 0x4f, 0x75, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, + 0x63, 0x2e, 0x53, 0x77, 0x61, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, + 0x0a, 0x06, 0x4c, 0x6f, 0x6f, 0x70, 0x49, 0x6e, 0x12, 0x16, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, + 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x6f, 0x70, 0x49, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x15, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x77, 0x61, 0x70, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x07, 0x4d, 0x6f, 0x6e, 0x69, 0x74, + 0x6f, 0x72, 0x12, 0x17, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x6f, 0x6e, + 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, 0x6f, + 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x77, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x30, 0x01, 0x12, 0x42, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x77, 0x61, 0x70, 0x73, 0x12, + 0x19, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x77, + 0x61, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x6c, 0x6f, 0x6f, + 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x77, 0x61, 0x70, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, + 0x66, 0x6f, 0x12, 0x18, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x77, 0x61, + 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6c, + 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x77, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x48, 0x0a, 0x0b, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x53, 0x77, 0x61, 0x70, + 0x12, 0x1b, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x62, 0x61, 0x6e, 0x64, + 0x6f, 0x6e, 0x53, 0x77, 0x61, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x53, - 0x77, 0x61, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6c, 0x6f, 0x6f, - 0x70, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x53, 0x77, 0x61, 0x70, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x0c, 0x4c, 0x6f, 0x6f, 0x70, - 0x4f, 0x75, 0x74, 0x54, 0x65, 0x72, 0x6d, 0x73, 0x12, 0x15, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, - 0x70, 0x63, 0x2e, 0x54, 0x65, 0x72, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x19, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x75, 0x74, 0x54, 0x65, 0x72, - 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x0c, 0x4c, 0x6f, - 0x6f, 0x70, 0x4f, 0x75, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x65, 0x12, 0x15, 0x2e, 0x6c, 0x6f, 0x6f, - 0x70, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x75, 0x74, 0x51, - 0x75, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0e, - 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x6f, 0x70, 0x49, 0x6e, 0x54, 0x65, 0x72, 0x6d, 0x73, 0x12, 0x15, - 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x65, 0x72, 0x6d, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, - 0x49, 0x6e, 0x54, 0x65, 0x72, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x41, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x6f, 0x70, 0x49, 0x6e, 0x51, 0x75, 0x6f, 0x74, - 0x65, 0x12, 0x15, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x6f, 0x74, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, - 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x51, 0x75, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x36, 0x0a, 0x05, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x12, 0x15, 0x2e, 0x6c, 0x6f, - 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x72, 0x6f, - 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x0d, 0x47, 0x65, - 0x74, 0x4c, 0x73, 0x61, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x16, 0x2e, 0x6c, 0x6f, - 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x07, - 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x17, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, - 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x18, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, - 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x12, 0x47, 0x65, + 0x77, 0x61, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x0c, 0x4c, + 0x6f, 0x6f, 0x70, 0x4f, 0x75, 0x74, 0x54, 0x65, 0x72, 0x6d, 0x73, 0x12, 0x15, 0x2e, 0x6c, 0x6f, + 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x65, 0x72, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x75, 0x74, + 0x54, 0x65, 0x72, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, + 0x0c, 0x4c, 0x6f, 0x6f, 0x70, 0x4f, 0x75, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x65, 0x12, 0x15, 0x2e, + 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x51, 0x75, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4f, + 0x75, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x41, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x6f, 0x70, 0x49, 0x6e, 0x54, 0x65, 0x72, 0x6d, + 0x73, 0x12, 0x15, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x65, 0x72, 0x6d, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, + 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x54, 0x65, 0x72, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x6f, 0x70, 0x49, 0x6e, 0x51, + 0x75, 0x6f, 0x74, 0x65, 0x12, 0x15, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x51, + 0x75, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6f, + 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x51, 0x75, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x05, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x12, 0x15, + 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, + 0x50, 0x72, 0x6f, 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, + 0x0d, 0x47, 0x65, 0x74, 0x4c, 0x73, 0x61, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x16, + 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, + 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x3c, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x17, 0x2e, 0x6c, 0x6f, 0x6f, + 0x70, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, + 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, + 0x12, 0x47, 0x65, 0x74, 0x4c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, + 0x61, 0x6d, 0x73, 0x12, 0x22, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, - 0x12, 0x22, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x69, - 0x71, 0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, - 0x69, 0x71, 0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, - 0x72, 0x73, 0x12, 0x5d, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x4c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x69, - 0x74, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x22, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, - 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, 0x4c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x50, - 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x6c, - 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, 0x4c, 0x69, 0x71, 0x75, 0x69, 0x64, - 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x75, 0x67, 0x67, 0x65, 0x73, 0x74, 0x53, 0x77, 0x61, 0x70, - 0x73, 0x12, 0x1c, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x75, 0x67, 0x67, - 0x65, 0x73, 0x74, 0x53, 0x77, 0x61, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1d, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x75, 0x67, 0x67, 0x65, 0x73, - 0x74, 0x53, 0x77, 0x61, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, - 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x20, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x49, 0x6e, 0x73, 0x74, 0x61, - 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x12, 0x1a, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, - 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, - 0x0a, 0x0f, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x51, 0x75, 0x6f, 0x74, - 0x65, 0x12, 0x1f, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x73, - 0x74, 0x61, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x77, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, - 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x4c, - 0x69, 0x73, 0x74, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x2e, 0x6c, 0x6f, 0x6f, - 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, - 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x6e, 0x74, 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, 0x6c, 0x61, 0x62, - 0x73, 0x2f, 0x6c, 0x6f, 0x6f, 0x70, 0x2f, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x63, 0x2e, 0x4c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, + 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x5d, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x4c, 0x69, 0x71, 0x75, + 0x69, 0x64, 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x22, 0x2e, 0x6c, 0x6f, + 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, 0x4c, 0x69, 0x71, 0x75, 0x69, 0x64, 0x69, + 0x74, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x23, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, 0x4c, 0x69, 0x71, + 0x75, 0x69, 0x64, 0x69, 0x74, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x75, 0x67, 0x67, 0x65, 0x73, 0x74, 0x53, + 0x77, 0x61, 0x70, 0x73, 0x12, 0x1c, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, + 0x75, 0x67, 0x67, 0x65, 0x73, 0x74, 0x53, 0x77, 0x61, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x75, 0x67, + 0x67, 0x65, 0x73, 0x74, 0x53, 0x77, 0x61, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x57, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x20, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, + 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x49, 0x6e, + 0x73, 0x74, 0x61, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x12, 0x1a, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, + 0x70, 0x63, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x49, + 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x51, + 0x75, 0x6f, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x49, + 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, + 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x4f, 0x75, 0x74, 0x51, 0x75, 0x6f, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4e, 0x65, 0x77, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1a, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, + 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4e, 0x65, 0x77, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, + 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x2e, + 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, 0x73, 0x70, + 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6c, 0x6f, 0x6f, + 0x70, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x6e, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x10, 0x57, 0x69, 0x74, 0x68, + 0x64, 0x72, 0x61, 0x77, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12, 0x20, 0x2e, 0x6c, + 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x44, + 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, + 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, + 0x77, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 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, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x6c, 0x6f, + 0x6f, 0x70, 0x2f, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -4832,7 +5019,7 @@ func file_client_proto_rawDescGZIP() []byte { } var file_client_proto_enumTypes = make([]protoimpl.EnumInfo, 7) -var file_client_proto_msgTypes = make([]protoimpl.MessageInfo, 45) +var file_client_proto_msgTypes = make([]protoimpl.MessageInfo, 48) var file_client_proto_goTypes = []interface{}{ (AddressType)(0), // 0: looprpc.AddressType (SwapType)(0), // 1: looprpc.SwapType @@ -4886,19 +5073,22 @@ var file_client_proto_goTypes = []interface{}{ (*ListUnspentRequest)(nil), // 49: looprpc.ListUnspentRequest (*ListUnspentResponse)(nil), // 50: looprpc.ListUnspentResponse (*Utxo)(nil), // 51: looprpc.Utxo - (*swapserverrpc.RouteHint)(nil), // 52: looprpc.RouteHint + (*WithdrawDepositsRequest)(nil), // 52: looprpc.WithdrawDepositsRequest + (*WithdrawDepositsResponse)(nil), // 53: looprpc.WithdrawDepositsResponse + (*OutPoint)(nil), // 54: looprpc.OutPoint + (*swapserverrpc.RouteHint)(nil), // 55: looprpc.RouteHint } var file_client_proto_depIdxs = []int32{ 0, // 0: looprpc.LoopOutRequest.account_addr_type:type_name -> looprpc.AddressType - 52, // 1: looprpc.LoopInRequest.route_hints:type_name -> looprpc.RouteHint + 55, // 1: looprpc.LoopInRequest.route_hints:type_name -> looprpc.RouteHint 1, // 2: looprpc.SwapStatus.type:type_name -> looprpc.SwapType 2, // 3: looprpc.SwapStatus.state:type_name -> looprpc.SwapState 3, // 4: looprpc.SwapStatus.failure_reason:type_name -> looprpc.FailureReason 13, // 5: looprpc.ListSwapsRequest.list_swap_filter:type_name -> looprpc.ListSwapsFilter 6, // 6: looprpc.ListSwapsFilter.swap_type:type_name -> looprpc.ListSwapsFilter.SwapTypeFilter 11, // 7: looprpc.ListSwapsResponse.swaps:type_name -> looprpc.SwapStatus - 52, // 8: looprpc.QuoteRequest.loop_in_route_hints:type_name -> looprpc.RouteHint - 52, // 9: looprpc.ProbeRequest.route_hints:type_name -> looprpc.RouteHint + 55, // 8: looprpc.QuoteRequest.loop_in_route_hints:type_name -> looprpc.RouteHint + 55, // 9: looprpc.ProbeRequest.route_hints:type_name -> looprpc.RouteHint 26, // 10: looprpc.TokensResponse.tokens:type_name -> looprpc.LsatToken 27, // 11: looprpc.GetInfoResponse.loop_out_stats:type_name -> looprpc.LoopStats 27, // 12: looprpc.GetInfoResponse.loop_in_stats:type_name -> looprpc.LoopStats @@ -4913,53 +5103,56 @@ var file_client_proto_depIdxs = []int32{ 36, // 21: looprpc.SuggestSwapsResponse.disqualified:type_name -> looprpc.Disqualified 42, // 22: looprpc.ListReservationsResponse.reservations:type_name -> looprpc.ClientReservation 51, // 23: looprpc.ListUnspentResponse.utxos:type_name -> looprpc.Utxo - 7, // 24: looprpc.SwapClient.LoopOut:input_type -> looprpc.LoopOutRequest - 8, // 25: looprpc.SwapClient.LoopIn:input_type -> looprpc.LoopInRequest - 10, // 26: looprpc.SwapClient.Monitor:input_type -> looprpc.MonitorRequest - 12, // 27: looprpc.SwapClient.ListSwaps:input_type -> looprpc.ListSwapsRequest - 15, // 28: looprpc.SwapClient.SwapInfo:input_type -> looprpc.SwapInfoRequest - 38, // 29: looprpc.SwapClient.AbandonSwap:input_type -> looprpc.AbandonSwapRequest - 16, // 30: looprpc.SwapClient.LoopOutTerms:input_type -> looprpc.TermsRequest - 19, // 31: looprpc.SwapClient.LoopOutQuote:input_type -> looprpc.QuoteRequest - 16, // 32: looprpc.SwapClient.GetLoopInTerms:input_type -> looprpc.TermsRequest - 19, // 33: looprpc.SwapClient.GetLoopInQuote:input_type -> looprpc.QuoteRequest - 22, // 34: looprpc.SwapClient.Probe:input_type -> looprpc.ProbeRequest - 24, // 35: looprpc.SwapClient.GetLsatTokens:input_type -> looprpc.TokensRequest - 28, // 36: looprpc.SwapClient.GetInfo:input_type -> looprpc.GetInfoRequest - 30, // 37: looprpc.SwapClient.GetLiquidityParams:input_type -> looprpc.GetLiquidityParamsRequest - 33, // 38: looprpc.SwapClient.SetLiquidityParams:input_type -> looprpc.SetLiquidityParamsRequest - 35, // 39: looprpc.SwapClient.SuggestSwaps:input_type -> looprpc.SuggestSwapsRequest - 40, // 40: looprpc.SwapClient.ListReservations:input_type -> looprpc.ListReservationsRequest - 43, // 41: looprpc.SwapClient.InstantOut:input_type -> looprpc.InstantOutRequest - 45, // 42: looprpc.SwapClient.InstantOutQuote:input_type -> looprpc.InstantOutQuoteRequest - 47, // 43: looprpc.SwapClient.NewAddress:input_type -> looprpc.NewAddressRequest - 49, // 44: looprpc.SwapClient.ListUnspent:input_type -> looprpc.ListUnspentRequest - 9, // 45: looprpc.SwapClient.LoopOut:output_type -> looprpc.SwapResponse - 9, // 46: looprpc.SwapClient.LoopIn:output_type -> looprpc.SwapResponse - 11, // 47: looprpc.SwapClient.Monitor:output_type -> looprpc.SwapStatus - 14, // 48: looprpc.SwapClient.ListSwaps:output_type -> looprpc.ListSwapsResponse - 11, // 49: looprpc.SwapClient.SwapInfo:output_type -> looprpc.SwapStatus - 39, // 50: looprpc.SwapClient.AbandonSwap:output_type -> looprpc.AbandonSwapResponse - 18, // 51: looprpc.SwapClient.LoopOutTerms:output_type -> looprpc.OutTermsResponse - 21, // 52: looprpc.SwapClient.LoopOutQuote:output_type -> looprpc.OutQuoteResponse - 17, // 53: looprpc.SwapClient.GetLoopInTerms:output_type -> looprpc.InTermsResponse - 20, // 54: looprpc.SwapClient.GetLoopInQuote:output_type -> looprpc.InQuoteResponse - 23, // 55: looprpc.SwapClient.Probe:output_type -> looprpc.ProbeResponse - 25, // 56: looprpc.SwapClient.GetLsatTokens:output_type -> looprpc.TokensResponse - 29, // 57: looprpc.SwapClient.GetInfo:output_type -> looprpc.GetInfoResponse - 31, // 58: looprpc.SwapClient.GetLiquidityParams:output_type -> looprpc.LiquidityParameters - 34, // 59: looprpc.SwapClient.SetLiquidityParams:output_type -> looprpc.SetLiquidityParamsResponse - 37, // 60: looprpc.SwapClient.SuggestSwaps:output_type -> looprpc.SuggestSwapsResponse - 41, // 61: looprpc.SwapClient.ListReservations:output_type -> looprpc.ListReservationsResponse - 44, // 62: looprpc.SwapClient.InstantOut:output_type -> looprpc.InstantOutResponse - 46, // 63: looprpc.SwapClient.InstantOutQuote:output_type -> looprpc.InstantOutQuoteResponse - 48, // 64: looprpc.SwapClient.NewAddress:output_type -> looprpc.NewAddressResponse - 50, // 65: looprpc.SwapClient.ListUnspent:output_type -> looprpc.ListUnspentResponse - 45, // [45:66] is the sub-list for method output_type - 24, // [24:45] is the sub-list for method input_type - 24, // [24:24] is the sub-list for extension type_name - 24, // [24:24] is the sub-list for extension extendee - 0, // [0:24] is the sub-list for field type_name + 54, // 24: looprpc.WithdrawDepositsRequest.outpoints:type_name -> looprpc.OutPoint + 7, // 25: looprpc.SwapClient.LoopOut:input_type -> looprpc.LoopOutRequest + 8, // 26: looprpc.SwapClient.LoopIn:input_type -> looprpc.LoopInRequest + 10, // 27: looprpc.SwapClient.Monitor:input_type -> looprpc.MonitorRequest + 12, // 28: looprpc.SwapClient.ListSwaps:input_type -> looprpc.ListSwapsRequest + 15, // 29: looprpc.SwapClient.SwapInfo:input_type -> looprpc.SwapInfoRequest + 38, // 30: looprpc.SwapClient.AbandonSwap:input_type -> looprpc.AbandonSwapRequest + 16, // 31: looprpc.SwapClient.LoopOutTerms:input_type -> looprpc.TermsRequest + 19, // 32: looprpc.SwapClient.LoopOutQuote:input_type -> looprpc.QuoteRequest + 16, // 33: looprpc.SwapClient.GetLoopInTerms:input_type -> looprpc.TermsRequest + 19, // 34: looprpc.SwapClient.GetLoopInQuote:input_type -> looprpc.QuoteRequest + 22, // 35: looprpc.SwapClient.Probe:input_type -> looprpc.ProbeRequest + 24, // 36: looprpc.SwapClient.GetLsatTokens:input_type -> looprpc.TokensRequest + 28, // 37: looprpc.SwapClient.GetInfo:input_type -> looprpc.GetInfoRequest + 30, // 38: looprpc.SwapClient.GetLiquidityParams:input_type -> looprpc.GetLiquidityParamsRequest + 33, // 39: looprpc.SwapClient.SetLiquidityParams:input_type -> looprpc.SetLiquidityParamsRequest + 35, // 40: looprpc.SwapClient.SuggestSwaps:input_type -> looprpc.SuggestSwapsRequest + 40, // 41: looprpc.SwapClient.ListReservations:input_type -> looprpc.ListReservationsRequest + 43, // 42: looprpc.SwapClient.InstantOut:input_type -> looprpc.InstantOutRequest + 45, // 43: looprpc.SwapClient.InstantOutQuote:input_type -> looprpc.InstantOutQuoteRequest + 47, // 44: looprpc.SwapClient.NewAddress:input_type -> looprpc.NewAddressRequest + 49, // 45: looprpc.SwapClient.ListUnspent:input_type -> looprpc.ListUnspentRequest + 52, // 46: looprpc.SwapClient.WithdrawDeposits:input_type -> looprpc.WithdrawDepositsRequest + 9, // 47: looprpc.SwapClient.LoopOut:output_type -> looprpc.SwapResponse + 9, // 48: looprpc.SwapClient.LoopIn:output_type -> looprpc.SwapResponse + 11, // 49: looprpc.SwapClient.Monitor:output_type -> looprpc.SwapStatus + 14, // 50: looprpc.SwapClient.ListSwaps:output_type -> looprpc.ListSwapsResponse + 11, // 51: looprpc.SwapClient.SwapInfo:output_type -> looprpc.SwapStatus + 39, // 52: looprpc.SwapClient.AbandonSwap:output_type -> looprpc.AbandonSwapResponse + 18, // 53: looprpc.SwapClient.LoopOutTerms:output_type -> looprpc.OutTermsResponse + 21, // 54: looprpc.SwapClient.LoopOutQuote:output_type -> looprpc.OutQuoteResponse + 17, // 55: looprpc.SwapClient.GetLoopInTerms:output_type -> looprpc.InTermsResponse + 20, // 56: looprpc.SwapClient.GetLoopInQuote:output_type -> looprpc.InQuoteResponse + 23, // 57: looprpc.SwapClient.Probe:output_type -> looprpc.ProbeResponse + 25, // 58: looprpc.SwapClient.GetLsatTokens:output_type -> looprpc.TokensResponse + 29, // 59: looprpc.SwapClient.GetInfo:output_type -> looprpc.GetInfoResponse + 31, // 60: looprpc.SwapClient.GetLiquidityParams:output_type -> looprpc.LiquidityParameters + 34, // 61: looprpc.SwapClient.SetLiquidityParams:output_type -> looprpc.SetLiquidityParamsResponse + 37, // 62: looprpc.SwapClient.SuggestSwaps:output_type -> looprpc.SuggestSwapsResponse + 41, // 63: looprpc.SwapClient.ListReservations:output_type -> looprpc.ListReservationsResponse + 44, // 64: looprpc.SwapClient.InstantOut:output_type -> looprpc.InstantOutResponse + 46, // 65: looprpc.SwapClient.InstantOutQuote:output_type -> looprpc.InstantOutQuoteResponse + 48, // 66: looprpc.SwapClient.NewAddress:output_type -> looprpc.NewAddressResponse + 50, // 67: looprpc.SwapClient.ListUnspent:output_type -> looprpc.ListUnspentResponse + 53, // 68: looprpc.SwapClient.WithdrawDeposits:output_type -> looprpc.WithdrawDepositsResponse + 47, // [47:69] is the sub-list for method output_type + 25, // [25:47] is the sub-list for method input_type + 25, // [25:25] is the sub-list for extension type_name + 25, // [25:25] is the sub-list for extension extendee + 0, // [0:25] is the sub-list for field type_name } func init() { file_client_proto_init() } @@ -5508,6 +5701,42 @@ func file_client_proto_init() { return nil } } + file_client_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WithdrawDepositsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_client_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WithdrawDepositsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_client_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*OutPoint); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -5515,7 +5744,7 @@ func file_client_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_client_proto_rawDesc, NumEnums: 7, - NumMessages: 45, + NumMessages: 48, NumExtensions: 0, NumServices: 1, }, diff --git a/looprpc/client.proto b/looprpc/client.proto index 881a31d..ddf1f5f 100644 --- a/looprpc/client.proto +++ b/looprpc/client.proto @@ -137,6 +137,12 @@ service SwapClient { ListUnspent returns a list of utxos behind a static address. */ rpc ListUnspent (ListUnspentRequest) returns (ListUnspentResponse); + + /* loop:`static withdraw` + WithdrawDeposits withdraws a selection or all deposits of a static address. + */ + rpc WithdrawDeposits (WithdrawDepositsRequest) + returns (WithdrawDepositsResponse); } message LoopOutRequest { @@ -1456,4 +1462,36 @@ message Utxo { The number of confirmations for the Utxo. */ int64 confirmations = 4; +} + +message WithdrawDepositsRequest { + /* + The outpoints of the deposits to withdraw. + */ + repeated OutPoint outpoints = 1; + + /* + If set to true, all deposits will be withdrawn. + */ + bool all = 2; +} + +message WithdrawDepositsResponse { +} + +message OutPoint { + /* + Raw bytes representing the transaction id. + */ + bytes txid_bytes = 1; + + /* + Reversed, hex-encoded string representing the transaction id. + */ + string txid_str = 2; + + /* + The index of the output on the transaction. + */ + uint32 output_index = 3; } \ No newline at end of file diff --git a/looprpc/client.swagger.json b/looprpc/client.swagger.json index 1a2c682..76d1407 100644 --- a/looprpc/client.swagger.json +++ b/looprpc/client.swagger.json @@ -1261,6 +1261,25 @@ } } }, + "looprpcOutPoint": { + "type": "object", + "properties": { + "txid_bytes": { + "type": "string", + "format": "byte", + "description": "Raw bytes representing the transaction id." + }, + "txid_str": { + "type": "string", + "description": "Reversed, hex-encoded string representing the transaction id." + }, + "output_index": { + "type": "integer", + "format": "int64", + "description": "The index of the output on the transaction." + } + } + }, "looprpcOutQuoteResponse": { "type": "object", "properties": { @@ -1546,6 +1565,9 @@ } } }, + "looprpcWithdrawDepositsResponse": { + "type": "object" + }, "protobufAny": { "type": "object", "properties": { diff --git a/looprpc/client_grpc.pb.go b/looprpc/client_grpc.pb.go index 1ccbe92..a2d83b8 100644 --- a/looprpc/client_grpc.pb.go +++ b/looprpc/client_grpc.pb.go @@ -99,6 +99,9 @@ type SwapClientClient interface { // loop: `static listunspent` //ListUnspent returns a list of utxos behind a static address. ListUnspent(ctx context.Context, in *ListUnspentRequest, opts ...grpc.CallOption) (*ListUnspentResponse, error) + // loop:`static withdraw` + //WithdrawDeposits withdraws a selection or all deposits of a static address. + WithdrawDeposits(ctx context.Context, in *WithdrawDepositsRequest, opts ...grpc.CallOption) (*WithdrawDepositsResponse, error) } type swapClientClient struct { @@ -321,6 +324,15 @@ func (c *swapClientClient) ListUnspent(ctx context.Context, in *ListUnspentReque return out, nil } +func (c *swapClientClient) WithdrawDeposits(ctx context.Context, in *WithdrawDepositsRequest, opts ...grpc.CallOption) (*WithdrawDepositsResponse, error) { + out := new(WithdrawDepositsResponse) + err := c.cc.Invoke(ctx, "/looprpc.SwapClient/WithdrawDeposits", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // SwapClientServer is the server API for SwapClient service. // All implementations must embed UnimplementedSwapClientServer // for forward compatibility @@ -406,6 +418,9 @@ type SwapClientServer interface { // loop: `static listunspent` //ListUnspent returns a list of utxos behind a static address. ListUnspent(context.Context, *ListUnspentRequest) (*ListUnspentResponse, error) + // loop:`static withdraw` + //WithdrawDeposits withdraws a selection or all deposits of a static address. + WithdrawDeposits(context.Context, *WithdrawDepositsRequest) (*WithdrawDepositsResponse, error) mustEmbedUnimplementedSwapClientServer() } @@ -476,6 +491,9 @@ func (UnimplementedSwapClientServer) NewAddress(context.Context, *NewAddressRequ func (UnimplementedSwapClientServer) ListUnspent(context.Context, *ListUnspentRequest) (*ListUnspentResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListUnspent not implemented") } +func (UnimplementedSwapClientServer) WithdrawDeposits(context.Context, *WithdrawDepositsRequest) (*WithdrawDepositsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method WithdrawDeposits not implemented") +} func (UnimplementedSwapClientServer) mustEmbedUnimplementedSwapClientServer() {} // UnsafeSwapClientServer may be embedded to opt out of forward compatibility for this service. @@ -870,6 +888,24 @@ func _SwapClient_ListUnspent_Handler(srv interface{}, ctx context.Context, dec f return interceptor(ctx, in, info, handler) } +func _SwapClient_WithdrawDeposits_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(WithdrawDepositsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SwapClientServer).WithdrawDeposits(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/looprpc.SwapClient/WithdrawDeposits", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SwapClientServer).WithdrawDeposits(ctx, req.(*WithdrawDepositsRequest)) + } + return interceptor(ctx, in, info, handler) +} + // SwapClient_ServiceDesc is the grpc.ServiceDesc for SwapClient service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -957,6 +993,10 @@ var SwapClient_ServiceDesc = grpc.ServiceDesc{ MethodName: "ListUnspent", Handler: _SwapClient_ListUnspent_Handler, }, + { + MethodName: "WithdrawDeposits", + Handler: _SwapClient_WithdrawDeposits_Handler, + }, }, Streams: []grpc.StreamDesc{ { diff --git a/looprpc/swapclient.pb.json.go b/looprpc/swapclient.pb.json.go index 896d961..97b8e26 100644 --- a/looprpc/swapclient.pb.json.go +++ b/looprpc/swapclient.pb.json.go @@ -562,4 +562,29 @@ func RegisterSwapClientJSONCallbacks(registry map[string]func(ctx context.Contex } callback(string(respBytes), nil) } + + registry["looprpc.SwapClient.WithdrawDeposits"] = func(ctx context.Context, + conn *grpc.ClientConn, reqJSON string, callback func(string, error)) { + + req := &WithdrawDepositsRequest{} + err := marshaler.Unmarshal([]byte(reqJSON), req) + if err != nil { + callback("", err) + return + } + + client := NewSwapClientClient(conn) + resp, err := client.WithdrawDeposits(ctx, req) + if err != nil { + callback("", err) + return + } + + respBytes, err := marshaler.Marshal(resp) + if err != nil { + callback("", err) + return + } + callback(string(respBytes), nil) + } } diff --git a/staticaddr/deposit/actions.go b/staticaddr/deposit/actions.go index 607fe68..63869a5 100644 --- a/staticaddr/deposit/actions.go +++ b/staticaddr/deposit/actions.go @@ -138,3 +138,19 @@ func (f *FSM) SweptExpiredDepositAction(_ fsm.EventContext) fsm.EventType { return fsm.NoOp } + +// WithdrawnDepositAction is the final action after a withdrawal. It signals to +// the manager that the deposit has been swept and the FSM can be removed. It +// also ends the state machine main loop by cancelling its context. +func (f *FSM) WithdrawnDepositAction(_ fsm.EventContext) fsm.EventType { + select { + case <-f.ctx.Done(): + return fsm.OnError + + default: + f.finalizedDepositChan <- f.deposit.OutPoint + f.ctx.Done() + } + + return fsm.NoOp +} diff --git a/staticaddr/deposit/deposit.go b/staticaddr/deposit/deposit.go index c3ac4a9..bbc2c29 100644 --- a/staticaddr/deposit/deposit.go +++ b/staticaddr/deposit/deposit.go @@ -33,7 +33,7 @@ type Deposit struct { // State is the current state of the deposit. State fsm.StateType - // The outpoint of the deposit. + // Outpoint of the deposit. wire.OutPoint // Value is the amount of the deposit. @@ -46,6 +46,10 @@ type Deposit struct { // TimeOutSweepPkScript is the pk script that is used to sweep the // deposit to after it is expired. TimeOutSweepPkScript []byte + + // WithdrawalSweepAddress is the address that is used to + // cooperatively sweep the deposit to before it is expired. + WithdrawalSweepAddress string } // IsPending returns true if the deposit is pending. @@ -55,7 +59,8 @@ func (d *Deposit) IsPending() bool { // IsFinal returns true if the deposit is final. func (d *Deposit) IsFinal() bool { - return d.State == Expired || d.State == Failed + return d.State == Withdrawn || d.State == Expired || + d.State == Failed } // GetRandomDepositID generates a random deposit ID. diff --git a/staticaddr/deposit/fsm.go b/staticaddr/deposit/fsm.go index 6816d16..91c3307 100644 --- a/staticaddr/deposit/fsm.go +++ b/staticaddr/deposit/fsm.go @@ -29,6 +29,10 @@ var ( var ( Deposited = fsm.StateType("Deposited") + Withdrawing = fsm.StateType("Withdrawing") + + Withdrawn = fsm.StateType("Withdrawn") + PublishExpiredDeposit = fsm.StateType("PublishExpiredDeposit") WaitForExpirySweep = fsm.StateType("WaitForExpirySweep") @@ -41,6 +45,8 @@ var ( // Events. var ( OnStart = fsm.EventType("OnStart") + OnWithdraw = fsm.EventType("OnWithdraw") + OnWithdrawn = fsm.EventType("OnWithdrawn") OnExpiry = fsm.EventType("OnExpiry") OnExpiryPublished = fsm.EventType("OnExpiryPublished") OnExpirySwept = fsm.EventType("OnExpirySwept") @@ -172,8 +178,33 @@ func (f *FSM) DepositStatesV0() fsm.States { }, Deposited: fsm.State{ Transitions: fsm.Transitions{ - OnExpiry: PublishExpiredDeposit, + OnWithdraw: Withdrawing, + OnExpiry: PublishExpiredDeposit, + OnRecover: Deposited, + }, + Action: fsm.NoOpAction, + }, + Withdrawing: fsm.State{ + Transitions: fsm.Transitions{ + OnWithdrawn: Withdrawn, + // Upon recovery, we go back to the Deposited + // state. The deposit by then has a withdrawal + // address stamped to it which will cause it to + // transition into the Withdrawing state again. OnRecover: Deposited, + + // A precondition for the Withdrawing state is + // that the withdrawal transaction has been + // broadcast. If the deposit expires while the + // withdrawal isn't confirmed, we can ignore the + // expiry. + OnExpiry: Withdrawing, + + // If the withdrawal failed we go back to + // Deposited, hoping that another withdrawal + // attempt will be successful. Alternatively, + // the client can wait for the timeout sweep. + fsm.OnError: Deposited, }, Action: fsm.NoOpAction, }, @@ -207,6 +238,9 @@ func (f *FSM) DepositStatesV0() fsm.States { }, Action: f.SweptExpiredDepositAction, }, + Withdrawn: fsm.State{ + Action: f.WithdrawnDepositAction, + }, Failed: fsm.State{ Action: fsm.NoOpAction, }, @@ -230,8 +264,10 @@ func (f *FSM) updateDeposit(notification fsm.Notification) { // Don't update the deposit if we are in an initial state or if we // are transitioning from an initial state to a failed state. state := f.deposit.State - if state == fsm.EmptyState || state == Deposited || - (notification.PreviousState == Deposited && state == Failed) { + prevState := notification.PreviousState + if state == fsm.EmptyState || + state == Deposited && !isRecoverable(prevState) || + (prevState == Deposited && state == Failed) { return } @@ -242,6 +278,16 @@ func (f *FSM) updateDeposit(notification fsm.Notification) { } } +func isRecoverable(state fsm.StateType) bool { + if state == Withdrawing || state == PublishExpiredDeposit || + state == WaitForExpirySweep { + + return true + } + + return false +} + // Infof logs an info message with the deposit outpoint. func (f *FSM) Infof(format string, args ...interface{}) { log.Infof( diff --git a/staticaddr/deposit/manager.go b/staticaddr/deposit/manager.go index 9dfb23d..f21d588 100644 --- a/staticaddr/deposit/manager.go +++ b/staticaddr/deposit/manager.go @@ -11,6 +11,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/lightninglabs/lndclient" "github.com/lightninglabs/loop" + "github.com/lightninglabs/loop/fsm" staticaddressrpc "github.com/lightninglabs/loop/swapserverrpc" "github.com/lightningnetwork/lnd/lnrpc/walletrpc" "github.com/lightningnetwork/lnd/lnwallet" @@ -418,3 +419,85 @@ func (m *Manager) finalizeDeposit(outpoint wire.OutPoint) { delete(m.deposits, outpoint) m.Unlock() } + +// GetActiveDepositsInState returns all active deposits. +func (m *Manager) GetActiveDepositsInState(stateFilter fsm.StateType) ( + []*Deposit, error) { + + m.Lock() + defer m.Unlock() + + var deposits []*Deposit + for _, fsm := range m.activeDeposits { + if fsm.deposit.State != stateFilter { + continue + } + deposits = append(deposits, fsm.deposit) + } + + return deposits, nil +} + +// GetAllDeposits returns all active deposits. +func (m *Manager) GetAllDeposits() ([]*Deposit, error) { + return m.cfg.Store.AllDeposits(m.runCtx) +} + +// AllOutpointsActiveDeposits checks if all deposits referenced by the outpoints +// are active and in the specified state. +func (m *Manager) AllOutpointsActiveDeposits(outpoints []wire.OutPoint, + stateFilter fsm.StateType) ( + + []*Deposit, bool) { + + m.Lock() + defer m.Unlock() + + var deposits []*Deposit + for _, o := range outpoints { + if _, ok := m.activeDeposits[o]; !ok { + return nil, false + } + + deposit := m.deposits[o] + if deposit.State != stateFilter { + return nil, false + } + + deposits = append(deposits, m.deposits[o]) + } + + return deposits, true +} + +// TransitionDeposits allows a caller to transition a set of deposits to a new +// state. +func (m *Manager) TransitionDeposits(deposits []*Deposit, event fsm.EventType, + expectedFinalState fsm.StateType) error { + + for _, d := range deposits { + m.Lock() + sm, ok := m.activeDeposits[d.OutPoint] + m.Unlock() + if !ok { + return fmt.Errorf("deposit not found") + } + + err := sm.SendEvent(event, nil) + if err != nil { + return err + } + err = sm.DefaultObserver.WaitForState( + m.runCtx, time.Minute, expectedFinalState, + ) + if err != nil { + return err + } + } + + return nil +} + +func (m *Manager) UpdateDeposit(d *Deposit) error { + return m.cfg.Store.UpdateDeposit(m.runCtx, d) +} diff --git a/staticaddr/deposit/sql_store.go b/staticaddr/deposit/sql_store.go index 939161f..2afced1 100644 --- a/staticaddr/deposit/sql_store.go +++ b/staticaddr/deposit/sql_store.go @@ -39,6 +39,9 @@ func (s *SqlStore) CreateDeposit(ctx context.Context, deposit *Deposit) error { Amount: int64(deposit.Value), ConfirmationHeight: deposit.ConfirmationHeight, TimeoutSweepPkScript: deposit.TimeOutSweepPkScript, + WithdrawalSweepAddress: sql.NullString{ + String: deposit.WithdrawalSweepAddress, + }, } updateArgs := sqlc.InsertDepositUpdateParams{ @@ -81,6 +84,10 @@ func (s *SqlStore) UpdateDeposit(ctx context.Context, deposit *Deposit) error { ConfirmationHeight: marshalSqlNullInt64( deposit.ConfirmationHeight, ).Int64, + WithdrawalSweepAddress: sql.NullString{ + String: deposit.WithdrawalSweepAddress, + Valid: deposit.WithdrawalSweepAddress != "", + }, } return s.baseDB.ExecTx(ctx, &loopdb.SqliteTxOptions{}, @@ -188,9 +195,10 @@ func (s *SqlStore) toDeposit(row sqlc.Deposit, Hash: *txHash, Index: uint32(row.OutIndex), }, - Value: btcutil.Amount(row.Amount), - ConfirmationHeight: row.ConfirmationHeight, - TimeOutSweepPkScript: row.TimeoutSweepPkScript, + Value: btcutil.Amount(row.Amount), + ConfirmationHeight: row.ConfirmationHeight, + TimeOutSweepPkScript: row.TimeoutSweepPkScript, + WithdrawalSweepAddress: row.WithdrawalSweepAddress.String, }, nil } diff --git a/staticaddr/withdraw/interface.go b/staticaddr/withdraw/interface.go new file mode 100644 index 0000000..48f110c --- /dev/null +++ b/staticaddr/withdraw/interface.go @@ -0,0 +1,44 @@ +package withdraw + +import ( + "context" + + "github.com/btcsuite/btcd/wire" + "github.com/lightninglabs/loop/fsm" + "github.com/lightninglabs/loop/staticaddr/address" + "github.com/lightninglabs/loop/staticaddr/deposit" + "github.com/lightninglabs/loop/staticaddr/script" + "github.com/lightningnetwork/lnd/lnwallet" +) + +const ( + IdLength = 32 +) + +// AddressManager handles fetching of address parameters. +type AddressManager interface { + // GetStaticAddressParameters returns the static address parameters. + GetStaticAddressParameters(ctx context.Context) (*address.Parameters, + error) + + // GetStaticAddress returns the deposit address for the given + // client and server public keys. + GetStaticAddress(ctx context.Context) (*script.StaticAddress, error) + + // ListUnspent returns a list of utxos at the static address. + ListUnspent(ctx context.Context, minConfs, + maxConfs int32) ([]*lnwallet.Utxo, error) +} + +type DepositManager interface { + GetActiveDepositsInState(stateFilter fsm.StateType) ([]*deposit.Deposit, + error) + + AllOutpointsActiveDeposits(outpoints []wire.OutPoint, + stateFilter fsm.StateType) ([]*deposit.Deposit, bool) + + TransitionDeposits(deposits []*deposit.Deposit, event fsm.EventType, + expectedFinalState fsm.StateType) error + + UpdateDeposit(d *deposit.Deposit) error +} diff --git a/staticaddr/withdraw/log.go b/staticaddr/withdraw/log.go new file mode 100644 index 0000000..82c2c3e --- /dev/null +++ b/staticaddr/withdraw/log.go @@ -0,0 +1,24 @@ +package withdraw + +import ( + "github.com/btcsuite/btclog" + "github.com/lightningnetwork/lnd/build" +) + +// Subsystem defines the sub system name of this package. +const Subsystem = "CLOS" + +// log is a logger that is initialized with no output filters. This means the +// package will not perform any logging by default until the caller requests it. +var log btclog.Logger + +// The default amount of logging is none. +func init() { + UseLogger(build.NewSubLogger(Subsystem, nil)) +} + +// UseLogger uses a specified Logger to output package logging info. This should +// be used in preference to SetLogWriter if the caller is also using btclog. +func UseLogger(logger btclog.Logger) { + log = logger +} diff --git a/staticaddr/withdraw/manager.go b/staticaddr/withdraw/manager.go new file mode 100644 index 0000000..a83d15c --- /dev/null +++ b/staticaddr/withdraw/manager.go @@ -0,0 +1,649 @@ +package withdraw + +import ( + "context" + "errors" + "fmt" + "github.com/btcsuite/btcd/chaincfg" + "reflect" + "sync" + + "github.com/btcsuite/btcd/btcec/v2/schnorr/musig2" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" + "github.com/lightninglabs/lndclient" + "github.com/lightninglabs/loop/staticaddr/deposit" + staticaddressrpc "github.com/lightninglabs/loop/swapserverrpc" + "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/lnrpc/walletrpc" + "github.com/lightningnetwork/lnd/lnwallet" + "github.com/lightningnetwork/lnd/lnwallet/chainfee" +) + +var ( + // ErrWithdrawingInactiveDeposits is returned when the user tries to + // withdraw inactive deposits. + ErrWithdrawingInactiveDeposits = errors.New("deposits to be withdrawn " + + "are unknown or inactive") + + // MinConfs is the minimum number of confirmations we require for a + // deposit to be considered withdrawn. + MinConfs int32 = 3 + + // Is the default confirmation target for the fee estimation of the + // withdrawal transaction. + defaultConfTarget int32 = 3 +) + +// ManagerConfig holds the configuration for the address manager. +type ManagerConfig struct { + WithdrawalServerClient staticaddressrpc.WithdrawalServerClient + + AddressManager AddressManager + + DepositManager DepositManager + + // WalletKit is the wallet client that is used to derive new keys from + // lnd's wallet. + WalletKit lndclient.WalletKitClient + + // ChainParams is the chain configuration(mainnet, testnet...) this + // manager uses. + ChainParams *chaincfg.Params + + // ChainNotifier is the chain notifier that is used to listen for new + // blocks. + ChainNotifier lndclient.ChainNotifierClient + + // Signer is the signer client that is used to sign transactions. + Signer lndclient.SignerClient +} + +// Manager manages the address state machines. +type Manager struct { + cfg *ManagerConfig + + runCtx context.Context + + sync.Mutex + + // initChan signals the daemon that the address manager has completed + // its initialization. + initChan chan struct{} + + // initiationHeight stores the currently best known block height. + initiationHeight uint32 + + // currentHeight stores the currently best known block height. + currentHeight uint32 +} + +// NewManager creates a new deposit withdrawal manager. +func NewManager(cfg *ManagerConfig) *Manager { + return &Manager{ + cfg: cfg, + initChan: make(chan struct{}), + } +} + +// Run runs the deposit withdrawal manager. +func (m *Manager) Run(ctx context.Context, currentHeight uint32) error { + m.runCtx = ctx + + m.Lock() + m.currentHeight, m.initiationHeight = currentHeight, currentHeight + m.Unlock() + + newBlockChan, newBlockErrChan, err := m.cfg.ChainNotifier.RegisterBlockEpochNtfn(m.runCtx) //nolint:lll + if err != nil { + return err + } + + err = m.recover() + if err != nil { + return err + } + + // Communicate to the caller that the address manager has completed its + // initialization. + close(m.initChan) + + for { + select { + case height := <-newBlockChan: + m.Lock() + m.currentHeight = uint32(height) + m.Unlock() + + case err := <-newBlockErrChan: + return err + + case <-m.runCtx.Done(): + return m.runCtx.Err() + } + } +} + +func (m *Manager) recover() error { + // To recover withdrawals we skim through all active deposits and check + // if they have a withdrawal address set. For the ones that do we + // cluster those with equal withdrawal addresses and kick-off + // their withdrawal. Each cluster represents a separate withdrawal by + // the user. + activeDeposits, err := m.cfg.DepositManager.GetActiveDepositsInState( + deposit.Deposited, + ) + if err != nil { + return err + } + + // Group the deposits by their withdrawal address. + depositsByWithdrawalAddress := make(map[string][]*deposit.Deposit) + for _, d := range activeDeposits { + sweepAddress := d.WithdrawalSweepAddress + if sweepAddress == "" { + continue + } + + depositsByWithdrawalAddress[sweepAddress] = append( + depositsByWithdrawalAddress[sweepAddress], d, + ) + } + + // We can now reinstate each cluster of deposits for a withdrawal. + for address, deposits := range depositsByWithdrawalAddress { + sweepAddress, err := btcutil.DecodeAddress( + address, m.cfg.ChainParams, + ) + if err != nil { + return err + } + + err = m.cfg.DepositManager.TransitionDeposits( + deposits, deposit.OnWithdraw, deposit.Withdrawing, + ) + if err != nil { + return err + } + + err = m.publishWithdrawal(m.runCtx, deposits, sweepAddress) + if err != nil { + return err + } + } + + return nil +} + +// WaitInitComplete waits until the address manager has completed its setup. +func (m *Manager) WaitInitComplete() { + defer log.Debugf("Static address withdrawal manager initiation " + + "complete.") + + <-m.initChan +} + +// WithdrawDeposits starts a deposits withdrawal flow. +func (m *Manager) WithdrawDeposits(ctx context.Context, + outpoints []wire.OutPoint) error { + + if len(outpoints) == 0 { + return fmt.Errorf("no outpoints selected to withdraw") + } + + // Ensure that the deposits are in a state in which they can be + // withdrawn. + deposits, allActive := m.cfg.DepositManager.AllOutpointsActiveDeposits( + outpoints, deposit.Deposited) + + if !allActive { + return ErrWithdrawingInactiveDeposits + } + + // Generate the withdrawal address from our local lnd wallet. + withdrawalAddress, err := m.cfg.WalletKit.NextAddr( + ctx, lnwallet.DefaultAccountName, + walletrpc.AddressType_TAPROOT_PUBKEY, false, + ) + if err != nil { + return err + } + + // Attach the withdrawal address to the deposit. After a client restart + // we can use this address as an indicator to continue the withdrawal. + // If there are multiple deposits with the same withdrawal address, we + // bundle them together in the same withdrawal transaction. + for _, d := range deposits { + d.WithdrawalSweepAddress = withdrawalAddress.String() + /*err := m.cfg.DepositManager.UpdateDeposit(d) + if err != nil { + return err + }*/ + } + + // Transition the deposits to the withdrawing state. This updates each + // deposits withdrawal address. If a transition fails, we'll return an + // error and abort the withdrawal. An error in transition is likely due + // to an error in the state machine. The already transitioned deposits + // should be reset to the deposit state after a restart. + err = m.cfg.DepositManager.TransitionDeposits( + deposits, deposit.OnWithdraw, deposit.Withdrawing, + ) + if err != nil { + return err + } + + return m.publishWithdrawal(ctx, deposits, withdrawalAddress) +} + +func (m *Manager) publishWithdrawal(ctx context.Context, + deposits []*deposit.Deposit, withdrawalAddress btcutil.Address) error { + + // Create a musig2 session for each deposit. + withdrawalSessions, clientNonces, err := m.createMusig2Sessions( + ctx, deposits, + ) + if err != nil { + return err + } + + // Get the fee rate for the withdrawal sweep. + withdrawalSweepFeeRate, err := m.cfg.WalletKit.EstimateFeeRate( + m.runCtx, defaultConfTarget, + ) + if err != nil { + return err + } + + outpoints := toOutpoints(deposits) + resp, err := m.cfg.WithdrawalServerClient.WithdrawDeposits( + m.runCtx, + &staticaddressrpc.ServerWithdrawRequest{ + Outpoints: toServerOutpoints(outpoints), + ClientNonces: clientNonces, + ClientSweepAddr: withdrawalAddress.String(), + MusigTxFeeRate: uint64(withdrawalSweepFeeRate), + }, + ) + if err != nil { + return err + } + + addressParams, err := m.cfg.AddressManager.GetStaticAddressParameters( + ctx, + ) + if err != nil { + return fmt.Errorf("couldn't get confirmation height for "+ + "deposit, %v", err) + } + + prevOuts := m.toPrevOuts(deposits, addressParams.PkScript) + totalValue := withdrawalValue(prevOuts) + withdrawalTx, err := m.createWithdrawalTx( + prevOuts, totalValue, withdrawalAddress, withdrawalSweepFeeRate, + ) + if err != nil { + return err + } + + coopServerNonces, err := toNonces(resp.ServerNonces) + if err != nil { + return err + } + + // Next we'll get our sweep tx signatures. + prevOutFetcher := txscript.NewMultiPrevOutFetcher(prevOuts) + _, err = m.signMusig2Tx( + m.runCtx, prevOutFetcher, outpoints, m.cfg.Signer, withdrawalTx, + withdrawalSessions, coopServerNonces, + ) + if err != nil { + return err + } + + // Now we'll finalize the sweepless sweep transaction. + finalizedWithdrawalTx, err := m.finalizeMusig2Transaction( + m.runCtx, outpoints, m.cfg.Signer, withdrawalSessions, + withdrawalTx, resp.Musig2SweepSigs, + ) + if err != nil { + return err + } + + txLabel := fmt.Sprintf("deposit-withdrawal-%v", + finalizedWithdrawalTx.TxHash()) + + // Publish the sweepless sweep transaction. + err = m.cfg.WalletKit.PublishTransaction( + m.runCtx, finalizedWithdrawalTx, txLabel, + ) + if err != nil { + return err + } + + txHash := finalizedWithdrawalTx.TxHash() + if err != nil { + return err + } + + withdrawalPkScript, err := txscript.PayToAddrScript(withdrawalAddress) + + confChan, errChan, err := m.cfg.ChainNotifier.RegisterConfirmationsNtfn( + m.runCtx, &txHash, withdrawalPkScript, MinConfs, + int32(m.initiationHeight), + ) + if err != nil { + return err + } + + go func() { + select { + case <-confChan: + err = m.cfg.DepositManager.TransitionDeposits( + deposits, deposit.OnWithdrawn, + deposit.Withdrawn, + ) + if err != nil { + log.Errorf("Error transitioning deposits: %v", + err) + } + + case err := <-errChan: + log.Errorf("Error waiting for confirmation: %v", err) + + case <-m.runCtx.Done(): + log.Errorf("Withdrawal tx confirmation wait canceled") + } + }() + + return nil +} + +func toOutpoints(deposits []*deposit.Deposit) []wire.OutPoint { + outpoints := make([]wire.OutPoint, len(deposits)) + for i, d := range deposits { + outpoints[i] = wire.OutPoint{ + Hash: d.Hash, + Index: d.Index, + } + } + + return outpoints +} + +// signMusig2Tx adds the server nonces to the musig2 sessions and signs the +// transaction. +func (m *Manager) signMusig2Tx(ctx context.Context, + prevOutFetcher *txscript.MultiPrevOutFetcher, outpoints []wire.OutPoint, + signer lndclient.SignerClient, tx *wire.MsgTx, + musig2sessions []*input.MuSig2SessionInfo, + counterPartyNonces [][musig2.PubNonceSize]byte) ([][]byte, error) { + + sigHashes := txscript.NewTxSigHashes(tx, prevOutFetcher) + sigs := make([][]byte, len(outpoints)) + + for idx, outpoint := range outpoints { + if !reflect.DeepEqual(tx.TxIn[idx].PreviousOutPoint, + outpoint) { + + return nil, fmt.Errorf("tx input does not match " + + "deposits") + } + + taprootSigHash, err := txscript.CalcTaprootSignatureHash( + sigHashes, txscript.SigHashDefault, tx, idx, + prevOutFetcher, + ) + if err != nil { + return nil, err + } + + var digest [32]byte + copy(digest[:], taprootSigHash) + + // Register the server's nonce before attempting to create our + // partial signature. + haveAllNonces, err := signer.MuSig2RegisterNonces( + ctx, musig2sessions[idx].SessionID, + [][musig2.PubNonceSize]byte{counterPartyNonces[idx]}, + ) + if err != nil { + return nil, err + } + + // Sanity check that we have all the nonces. + if !haveAllNonces { + return nil, fmt.Errorf("invalid MuSig2 session: " + + "nonces missing") + } + + // Since our MuSig2 session has all nonces, we can now create + // the local partial signature by signing the sig hash. + sig, err := signer.MuSig2Sign( + ctx, musig2sessions[idx].SessionID, digest, false, + ) + if err != nil { + return nil, err + } + + sigs[idx] = sig + } + + return sigs, nil +} + +func withdrawalValue(prevOuts map[wire.OutPoint]*wire.TxOut) btcutil.Amount { + var totalValue btcutil.Amount + for _, prevOut := range prevOuts { + totalValue += btcutil.Amount(prevOut.Value) + } + return totalValue +} + +// toNonces converts a byte slice to a 66 byte slice. +func toNonces(nonces [][]byte) ([][66]byte, error) { + res := make([][66]byte, 0, len(nonces)) + for _, n := range nonces { + n := n + nonce, err := byteSliceTo66ByteSlice(n) + if err != nil { + return nil, err + } + + res = append(res, nonce) + } + + return res, nil +} + +// byteSliceTo66ByteSlice converts a byte slice to a 66 byte slice. +func byteSliceTo66ByteSlice(b []byte) ([66]byte, error) { + if len(b) != 66 { + return [66]byte{}, fmt.Errorf("invalid byte slice length") + } + + var res [66]byte + copy(res[:], b) + + return res, nil +} + +func (m *Manager) createWithdrawalTx(prevOuts map[wire.OutPoint]*wire.TxOut, + withdrawlAmount btcutil.Amount, clientSweepAddress btcutil.Address, + feeRate chainfee.SatPerKWeight) (*wire.MsgTx, error) { + + // First Create the tx. + msgTx := wire.NewMsgTx(2) + + // Add the deposit inputs to the transaction. + for o, _ := range prevOuts { + msgTx.AddTxIn(&wire.TxIn{ + PreviousOutPoint: o, + }) + } + + // Estimate the fee + weight, err := withdrawalFee(len(prevOuts), clientSweepAddress) + if err != nil { + return nil, err + } + + pkscript, err := txscript.PayToAddrScript(clientSweepAddress) + if err != nil { + return nil, err + } + + fee := feeRate.FeeForWeight(weight) + + // Create the sweep output + sweepOutput := &wire.TxOut{ + Value: int64(withdrawlAmount) - int64(fee), + PkScript: pkscript, + } + + msgTx.AddTxOut(sweepOutput) + + return msgTx, nil +} + +// withdrawalFee returns the weight for the withdrawal transaction. +func withdrawalFee(numInputs int, sweepAddress btcutil.Address) (int64, + error) { + + var weightEstimator input.TxWeightEstimator + for i := 0; i < numInputs; i++ { + weightEstimator.AddTaprootKeySpendInput( + txscript.SigHashDefault, + ) + } + + // Get the weight of the sweep output. + switch sweepAddress.(type) { + case *btcutil.AddressWitnessPubKeyHash: + weightEstimator.AddP2WKHOutput() + + case *btcutil.AddressTaproot: + weightEstimator.AddP2TROutput() + + default: + return 0, fmt.Errorf("invalid sweep address type %T", + sweepAddress) + } + + return int64(weightEstimator.Weight()), nil +} + +// finalizeMusig2Transaction creates the finalized transactions for either +// the htlc or the cooperative close. +func (m *Manager) finalizeMusig2Transaction(ctx context.Context, + outpoints []wire.OutPoint, signer lndclient.SignerClient, + musig2Sessions []*input.MuSig2SessionInfo, + tx *wire.MsgTx, serverSigs [][]byte) (*wire.MsgTx, error) { + + for idx := range outpoints { + haveAllSigs, finalSig, err := signer.MuSig2CombineSig( + ctx, musig2Sessions[idx].SessionID, + [][]byte{serverSigs[idx]}, + ) + if err != nil { + return nil, err + } + + if !haveAllSigs { + return nil, fmt.Errorf("missing sigs") + } + + tx.TxIn[idx].Witness = wire.TxWitness{finalSig} + } + + return tx, nil +} + +func toServerOutpoints(outpoints []wire.OutPoint) []*staticaddressrpc.ServerOutPoint { //nolint:lll + var result []*staticaddressrpc.ServerOutPoint + for _, o := range outpoints { + outP := o + outpoint := &staticaddressrpc.ServerOutPoint{ + TxidBytes: outP.Hash[:], + OutputIndex: outP.Index, + } + result = append(result, outpoint) + } + + return result +} + +// createMusig2Sessions creates a musig2 session for a number of deposits. +func (m *Manager) createMusig2Sessions(ctx context.Context, + deposits []*deposit.Deposit) ([]*input.MuSig2SessionInfo, [][]byte, + error) { + + musig2Sessions := make([]*input.MuSig2SessionInfo, len(deposits)) + clientNonces := make([][]byte, len(deposits)) + + // Create the sessions and nonces from the deposits. + for i := 0; i < len(deposits); i++ { + session, err := m.createMusig2Session(ctx) + if err != nil { + return nil, nil, err + } + + musig2Sessions[i] = session + clientNonces[i] = session.PublicNonce[:] + } + + return musig2Sessions, clientNonces, nil +} + +// Musig2CreateSession creates a musig2 session for the deposit. +func (m *Manager) createMusig2Session(ctx context.Context) ( + *input.MuSig2SessionInfo, error) { + + addressParams, err := m.cfg.AddressManager.GetStaticAddressParameters( + ctx, + ) + if err != nil { + return nil, fmt.Errorf("couldn't get confirmation height for "+ + "deposit, %v", err) + } + + signers := [][]byte{ + addressParams.ClientPubkey.SerializeCompressed(), + addressParams.ServerPubkey.SerializeCompressed(), + } + + address, err := m.cfg.AddressManager.GetStaticAddress(ctx) + if err != nil { + return nil, fmt.Errorf("couldn't get confirmation height for "+ + "deposit, %v", err) + } + + expiryLeaf := address.TimeoutLeaf + + rootHash := expiryLeaf.TapHash() + + return m.cfg.Signer.MuSig2CreateSession( + ctx, input.MuSig2Version100RC2, &addressParams.KeyLocator, + signers, lndclient.MuSig2TaprootTweakOpt(rootHash[:], false), + ) +} + +func (m *Manager) toPrevOuts(deposits []*deposit.Deposit, + pkScript []byte) map[wire.OutPoint]*wire.TxOut { + + prevOuts := make(map[wire.OutPoint]*wire.TxOut, len(deposits)) + for _, d := range deposits { + outpoint := wire.OutPoint{ + Hash: d.Hash, + Index: d.Index, + } + txOut := &wire.TxOut{ + Value: int64(d.Value), + PkScript: pkScript, + } + prevOuts[outpoint] = txOut + } + + return prevOuts +} diff --git a/swapserverrpc/withdraw.pb.go b/swapserverrpc/withdraw.pb.go new file mode 100644 index 0000000..1c60ce6 --- /dev/null +++ b/swapserverrpc/withdraw.pb.go @@ -0,0 +1,363 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.30.0 +// protoc v3.6.1 +// source: withdraw.proto + +// We can't change this to swapserverrpc, it would be a breaking change because +// the package name is also contained in the HTTP URIs and old clients would +// call the wrong endpoints. Luckily with the go_package option we can have +// different golang and RPC package names to fix protobuf namespace conflicts. + +package swapserverrpc + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type ServerWithdrawRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The deposit outpoints the client whishes to close. + Outpoints []*ServerOutPoint `protobuf:"bytes,1,rep,name=outpoints,proto3" json:"outpoints,omitempty"` + // The nonces that the client used to generate the coop close tx sigs. + ClientNonces [][]byte `protobuf:"bytes,2,rep,name=client_nonces,json=clientNonces,proto3" json:"client_nonces,omitempty"` + // The address that the client wants to sweep the static address deposits + // to. + ClientSweepAddr string `protobuf:"bytes,3,opt,name=client_sweep_addr,json=clientSweepAddr,proto3" json:"client_sweep_addr,omitempty"` + // The fee rate in sat/kw that the client wants to use for the sweep. + MusigTxFeeRate uint64 `protobuf:"varint,4,opt,name=musig_tx_fee_rate,json=musigTxFeeRate,proto3" json:"musig_tx_fee_rate,omitempty"` +} + +func (x *ServerWithdrawRequest) Reset() { + *x = ServerWithdrawRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_withdraw_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ServerWithdrawRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServerWithdrawRequest) ProtoMessage() {} + +func (x *ServerWithdrawRequest) ProtoReflect() protoreflect.Message { + mi := &file_withdraw_proto_msgTypes[0] + 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 ServerWithdrawRequest.ProtoReflect.Descriptor instead. +func (*ServerWithdrawRequest) Descriptor() ([]byte, []int) { + return file_withdraw_proto_rawDescGZIP(), []int{0} +} + +func (x *ServerWithdrawRequest) GetOutpoints() []*ServerOutPoint { + if x != nil { + return x.Outpoints + } + return nil +} + +func (x *ServerWithdrawRequest) GetClientNonces() [][]byte { + if x != nil { + return x.ClientNonces + } + return nil +} + +func (x *ServerWithdrawRequest) GetClientSweepAddr() string { + if x != nil { + return x.ClientSweepAddr + } + return "" +} + +func (x *ServerWithdrawRequest) GetMusigTxFeeRate() uint64 { + if x != nil { + return x.MusigTxFeeRate + } + return 0 +} + +type ServerWithdrawResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The sweep sigs that the server generated for the htlc. + Musig2SweepSigs [][]byte `protobuf:"bytes,1,rep,name=musig2_sweep_sigs,json=musig2SweepSigs,proto3" json:"musig2_sweep_sigs,omitempty"` + // The nonces that the server used to generate the sweepless sweep sigs. + ServerNonces [][]byte `protobuf:"bytes,2,rep,name=server_nonces,json=serverNonces,proto3" json:"server_nonces,omitempty"` +} + +func (x *ServerWithdrawResponse) Reset() { + *x = ServerWithdrawResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_withdraw_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ServerWithdrawResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServerWithdrawResponse) ProtoMessage() {} + +func (x *ServerWithdrawResponse) ProtoReflect() protoreflect.Message { + mi := &file_withdraw_proto_msgTypes[1] + 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 ServerWithdrawResponse.ProtoReflect.Descriptor instead. +func (*ServerWithdrawResponse) Descriptor() ([]byte, []int) { + return file_withdraw_proto_rawDescGZIP(), []int{1} +} + +func (x *ServerWithdrawResponse) GetMusig2SweepSigs() [][]byte { + if x != nil { + return x.Musig2SweepSigs + } + return nil +} + +func (x *ServerWithdrawResponse) GetServerNonces() [][]byte { + if x != nil { + return x.ServerNonces + } + return nil +} + +type ServerOutPoint struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // + //Raw bytes representing the transaction id. + TxidBytes []byte `protobuf:"bytes,1,opt,name=txid_bytes,json=txidBytes,proto3" json:"txid_bytes,omitempty"` + // + //Reversed, hex-encoded string representing the transaction id. + TxidStr string `protobuf:"bytes,2,opt,name=txid_str,json=txidStr,proto3" json:"txid_str,omitempty"` + // + //The index of the output on the transaction. + OutputIndex uint32 `protobuf:"varint,3,opt,name=output_index,json=outputIndex,proto3" json:"output_index,omitempty"` +} + +func (x *ServerOutPoint) Reset() { + *x = ServerOutPoint{} + if protoimpl.UnsafeEnabled { + mi := &file_withdraw_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ServerOutPoint) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServerOutPoint) ProtoMessage() {} + +func (x *ServerOutPoint) ProtoReflect() protoreflect.Message { + mi := &file_withdraw_proto_msgTypes[2] + 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 ServerOutPoint.ProtoReflect.Descriptor instead. +func (*ServerOutPoint) Descriptor() ([]byte, []int) { + return file_withdraw_proto_rawDescGZIP(), []int{2} +} + +func (x *ServerOutPoint) GetTxidBytes() []byte { + if x != nil { + return x.TxidBytes + } + return nil +} + +func (x *ServerOutPoint) GetTxidStr() string { + if x != nil { + return x.TxidStr + } + return "" +} + +func (x *ServerOutPoint) GetOutputIndex() uint32 { + if x != nil { + return x.OutputIndex + } + return 0 +} + +var File_withdraw_proto protoreflect.FileDescriptor + +var file_withdraw_proto_rawDesc = []byte{ + 0x0a, 0x0e, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x12, 0x07, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x22, 0xca, 0x01, 0x0a, 0x15, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x09, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, + 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, + 0x09, 0x6f, 0x75, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0c, 0x52, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x12, + 0x2a, 0x0a, 0x11, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x77, 0x65, 0x65, 0x70, 0x5f, + 0x61, 0x64, 0x64, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x53, 0x77, 0x65, 0x65, 0x70, 0x41, 0x64, 0x64, 0x72, 0x12, 0x29, 0x0a, 0x11, 0x6d, + 0x75, 0x73, 0x69, 0x67, 0x5f, 0x74, 0x78, 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x72, 0x61, 0x74, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x6d, 0x75, 0x73, 0x69, 0x67, 0x54, 0x78, 0x46, + 0x65, 0x65, 0x52, 0x61, 0x74, 0x65, 0x22, 0x69, 0x0a, 0x16, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x75, 0x73, 0x69, 0x67, 0x32, 0x5f, 0x73, 0x77, 0x65, 0x65, 0x70, + 0x5f, 0x73, 0x69, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0f, 0x6d, 0x75, 0x73, + 0x69, 0x67, 0x32, 0x53, 0x77, 0x65, 0x65, 0x70, 0x53, 0x69, 0x67, 0x73, 0x12, 0x23, 0x0a, 0x0d, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0c, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x6f, 0x6e, 0x63, 0x65, + 0x73, 0x22, 0x6d, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x50, 0x6f, + 0x69, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x78, 0x69, 0x64, 0x5f, 0x62, 0x79, 0x74, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x74, 0x78, 0x69, 0x64, 0x42, 0x79, 0x74, + 0x65, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x78, 0x69, 0x64, 0x5f, 0x73, 0x74, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x78, 0x69, 0x64, 0x53, 0x74, 0x72, 0x12, 0x21, 0x0a, + 0x0c, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, + 0x32, 0x67, 0x0a, 0x10, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x12, 0x53, 0x0a, 0x10, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, + 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x73, 0x12, 0x1e, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, + 0x70, 0x63, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, + 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, + 0x70, 0x63, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, + 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2d, 0x5a, 0x2b, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, + 0x67, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x6c, 0x6f, 0x6f, 0x70, 0x2f, 0x73, 0x77, 0x61, 0x70, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_withdraw_proto_rawDescOnce sync.Once + file_withdraw_proto_rawDescData = file_withdraw_proto_rawDesc +) + +func file_withdraw_proto_rawDescGZIP() []byte { + file_withdraw_proto_rawDescOnce.Do(func() { + file_withdraw_proto_rawDescData = protoimpl.X.CompressGZIP(file_withdraw_proto_rawDescData) + }) + return file_withdraw_proto_rawDescData +} + +var file_withdraw_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_withdraw_proto_goTypes = []interface{}{ + (*ServerWithdrawRequest)(nil), // 0: looprpc.ServerWithdrawRequest + (*ServerWithdrawResponse)(nil), // 1: looprpc.ServerWithdrawResponse + (*ServerOutPoint)(nil), // 2: looprpc.ServerOutPoint +} +var file_withdraw_proto_depIdxs = []int32{ + 2, // 0: looprpc.ServerWithdrawRequest.outpoints:type_name -> looprpc.ServerOutPoint + 0, // 1: looprpc.WithdrawalServer.WithdrawDeposits:input_type -> looprpc.ServerWithdrawRequest + 1, // 2: looprpc.WithdrawalServer.WithdrawDeposits:output_type -> looprpc.ServerWithdrawResponse + 2, // [2:3] is the sub-list for method output_type + 1, // [1:2] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_withdraw_proto_init() } +func file_withdraw_proto_init() { + if File_withdraw_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_withdraw_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ServerWithdrawRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_withdraw_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ServerWithdrawResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_withdraw_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ServerOutPoint); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_withdraw_proto_rawDesc, + NumEnums: 0, + NumMessages: 3, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_withdraw_proto_goTypes, + DependencyIndexes: file_withdraw_proto_depIdxs, + MessageInfos: file_withdraw_proto_msgTypes, + }.Build() + File_withdraw_proto = out.File + file_withdraw_proto_rawDesc = nil + file_withdraw_proto_goTypes = nil + file_withdraw_proto_depIdxs = nil +} diff --git a/swapserverrpc/withdraw.proto b/swapserverrpc/withdraw.proto new file mode 100644 index 0000000..c8420bc --- /dev/null +++ b/swapserverrpc/withdraw.proto @@ -0,0 +1,57 @@ +syntax = "proto3"; + +// We can't change this to swapserverrpc, it would be a breaking change because +// the package name is also contained in the HTTP URIs and old clients would +// call the wrong endpoints. Luckily with the go_package option we can have +// different golang and RPC package names to fix protobuf namespace conflicts. +package looprpc; + +option go_package = "github.com/lightninglabs/loop/swapserverrpc"; + +service WithdrawalServer { + // WithdrawDeposits allows to cooperatively sweep deposits that haven't + // timed out yet to the client's wallet. The server will generate the + // partial sigs for the client's selected deposits. + rpc WithdrawDeposits (ServerWithdrawRequest) + returns (ServerWithdrawResponse); +} + +message ServerWithdrawRequest { + // The deposit outpoints the client whishes to close. + repeated ServerOutPoint outpoints = 1; + + // The nonces that the client used to generate the coop close tx sigs. + repeated bytes client_nonces = 2; + + // The address that the client wants to sweep the static address deposits + // to. + string client_sweep_addr = 3; + + // The fee rate in sat/kw that the client wants to use for the sweep. + uint64 musig_tx_fee_rate = 4; +} + +message ServerWithdrawResponse { + // The sweep sigs that the server generated for the htlc. + repeated bytes musig2_sweep_sigs = 1; + + // The nonces that the server used to generate the sweepless sweep sigs. + repeated bytes server_nonces = 2; +} + +message ServerOutPoint { + /* + Raw bytes representing the transaction id. + */ + bytes txid_bytes = 1; + + /* + Reversed, hex-encoded string representing the transaction id. + */ + string txid_str = 2; + + /* + The index of the output on the transaction. + */ + uint32 output_index = 3; +} diff --git a/swapserverrpc/withdraw_grpc.pb.go b/swapserverrpc/withdraw_grpc.pb.go new file mode 100644 index 0000000..a9dae59 --- /dev/null +++ b/swapserverrpc/withdraw_grpc.pb.go @@ -0,0 +1,107 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. + +package swapserverrpc + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// WithdrawalServerClient is the client API for WithdrawalServer service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type WithdrawalServerClient interface { + // WithdrawDeposits allows to cooperatively sweep deposits that haven't + // timed out yet to the client's wallet. The server will generate the + // partial sigs for the client's selected deposits. + WithdrawDeposits(ctx context.Context, in *ServerWithdrawRequest, opts ...grpc.CallOption) (*ServerWithdrawResponse, error) +} + +type withdrawalServerClient struct { + cc grpc.ClientConnInterface +} + +func NewWithdrawalServerClient(cc grpc.ClientConnInterface) WithdrawalServerClient { + return &withdrawalServerClient{cc} +} + +func (c *withdrawalServerClient) WithdrawDeposits(ctx context.Context, in *ServerWithdrawRequest, opts ...grpc.CallOption) (*ServerWithdrawResponse, error) { + out := new(ServerWithdrawResponse) + err := c.cc.Invoke(ctx, "/looprpc.WithdrawalServer/WithdrawDeposits", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// WithdrawalServerServer is the server API for WithdrawalServer service. +// All implementations must embed UnimplementedWithdrawalServerServer +// for forward compatibility +type WithdrawalServerServer interface { + // WithdrawDeposits allows to cooperatively sweep deposits that haven't + // timed out yet to the client's wallet. The server will generate the + // partial sigs for the client's selected deposits. + WithdrawDeposits(context.Context, *ServerWithdrawRequest) (*ServerWithdrawResponse, error) + mustEmbedUnimplementedWithdrawalServerServer() +} + +// UnimplementedWithdrawalServerServer must be embedded to have forward compatible implementations. +type UnimplementedWithdrawalServerServer struct { +} + +func (UnimplementedWithdrawalServerServer) WithdrawDeposits(context.Context, *ServerWithdrawRequest) (*ServerWithdrawResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method WithdrawDeposits not implemented") +} +func (UnimplementedWithdrawalServerServer) mustEmbedUnimplementedWithdrawalServerServer() {} + +// UnsafeWithdrawalServerServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to WithdrawalServerServer will +// result in compilation errors. +type UnsafeWithdrawalServerServer interface { + mustEmbedUnimplementedWithdrawalServerServer() +} + +func RegisterWithdrawalServerServer(s grpc.ServiceRegistrar, srv WithdrawalServerServer) { + s.RegisterService(&WithdrawalServer_ServiceDesc, srv) +} + +func _WithdrawalServer_WithdrawDeposits_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ServerWithdrawRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WithdrawalServerServer).WithdrawDeposits(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/looprpc.WithdrawalServer/WithdrawDeposits", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WithdrawalServerServer).WithdrawDeposits(ctx, req.(*ServerWithdrawRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// WithdrawalServer_ServiceDesc is the grpc.ServiceDesc for WithdrawalServer service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var WithdrawalServer_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "looprpc.WithdrawalServer", + HandlerType: (*WithdrawalServerServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "WithdrawDeposits", + Handler: _WithdrawalServer_WithdrawDeposits_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "withdraw.proto", +}