mirror of
https://github.com/lightninglabs/loop.git
synced 2026-08-13 12:33:03 +02:00
Merge pull request #632 from sputn1ck/instantloopout_2
[2/?] Instant loop out: Add reservations
This commit is contained in:
commit
e9d374a341
37 changed files with 3716 additions and 206 deletions
|
|
@ -19,6 +19,7 @@ import (
|
|||
"github.com/lightninglabs/loop/sweep"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/routing/route"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
|
|
@ -148,6 +149,7 @@ func NewClient(dbDir string, loopDB loopdb.SwapStore,
|
|||
LndServices: cfg.Lnd,
|
||||
Server: swapServerClient,
|
||||
Store: loopDB,
|
||||
Conn: swapServerClient.conn,
|
||||
LsatStore: lsatStore,
|
||||
CreateExpiryTimer: func(d time.Duration) <-chan time.Time {
|
||||
return time.NewTimer(d).C
|
||||
|
|
@ -200,6 +202,11 @@ func NewClient(dbDir string, loopDB loopdb.SwapStore,
|
|||
return client, cleanup, nil
|
||||
}
|
||||
|
||||
// GetConn returns the gRPC connection to the server.
|
||||
func (s *Client) GetConn() *grpc.ClientConn {
|
||||
return s.clientConfig.Conn
|
||||
}
|
||||
|
||||
// FetchSwaps returns all loop in and out swaps currently in the database.
|
||||
func (s *Client) FetchSwaps(ctx context.Context) ([]*SwapInfo, error) {
|
||||
loopOutSwaps, err := s.Store.FetchLoopOutSwaps(ctx)
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ func main() {
|
|||
monitorCommand, quoteCommand, listAuthCommand,
|
||||
listSwapsCommand, swapInfoCommand, getLiquidityParamsCommand,
|
||||
setLiquidityRuleCommand, suggestSwapCommand, setParamsCommand,
|
||||
getInfoCommand, abandonSwapCommand,
|
||||
getInfoCommand, abandonSwapCommand, reservationsCommands,
|
||||
}
|
||||
|
||||
err := app.Run(os.Args)
|
||||
|
|
|
|||
55
cmd/loop/reservations.go
Normal file
55
cmd/loop/reservations.go
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/lightninglabs/loop/looprpc"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var reservationsCommands = cli.Command{
|
||||
|
||||
Name: "reservations",
|
||||
ShortName: "r",
|
||||
Usage: "manage reservations",
|
||||
Description: `
|
||||
With loopd running, you can use this command to manage your
|
||||
reservations. Reservations are 2-of-2 multisig utxos that
|
||||
the loop server can open to clients. The reservations are used
|
||||
to enable instant swaps.
|
||||
`,
|
||||
Subcommands: []cli.Command{
|
||||
listReservationsCommand,
|
||||
},
|
||||
}
|
||||
|
||||
var (
|
||||
listReservationsCommand = cli.Command{
|
||||
Name: "list",
|
||||
ShortName: "l",
|
||||
Usage: "list all reservations",
|
||||
ArgsUsage: "",
|
||||
Description: `
|
||||
List all reservations.
|
||||
`,
|
||||
Action: listReservations,
|
||||
}
|
||||
)
|
||||
|
||||
func listReservations(ctx *cli.Context) error {
|
||||
client, cleanup, err := getClient(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
resp, err := client.ListReservations(
|
||||
context.Background(), &looprpc.ListReservationsRequest{},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
printRespJSON(resp)
|
||||
return nil
|
||||
}
|
||||
|
|
@ -6,12 +6,14 @@ import (
|
|||
"github.com/lightninglabs/aperture/lsat"
|
||||
"github.com/lightninglabs/lndclient"
|
||||
"github.com/lightninglabs/loop/loopdb"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// clientConfig contains config items for the swap client.
|
||||
type clientConfig struct {
|
||||
LndServices *lndclient.LndServices
|
||||
Server swapServerClient
|
||||
Conn *grpc.ClientConn
|
||||
Store loopdb.SwapStore
|
||||
LsatStore lsat.Store
|
||||
CreateExpiryTimer func(expiry time.Duration) <-chan time.Time
|
||||
|
|
|
|||
|
|
@ -206,6 +206,8 @@ func (s *StateMachine) SendEvent(event EventType, eventCtx EventContext) error {
|
|||
// current state.
|
||||
state, err := s.getNextState(event)
|
||||
if err != nil {
|
||||
log.Errorf("unable to get next state: %v from event: "+
|
||||
"%v, current state: %v", err, event, s.current)
|
||||
return ErrEventRejected
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"sort"
|
||||
|
||||
"github.com/lightninglabs/loop/fsm"
|
||||
"github.com/lightninglabs/loop/instantout/reservation"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
|
@ -41,6 +42,13 @@ func run() error {
|
|||
return err
|
||||
}
|
||||
|
||||
case "reservation":
|
||||
reservationFSM := &reservation.FSM{}
|
||||
err = writeMermaidFile(fp, reservationFSM.GetReservationStates())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
default:
|
||||
fmt.Println("Missing or wrong argument: fsm must be one of:")
|
||||
fmt.Println("\treservations")
|
||||
|
|
|
|||
176
instantout/reservation/actions.go
Normal file
176
instantout/reservation/actions.go
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
package reservation
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/lightninglabs/loop/fsm"
|
||||
looprpc "github.com/lightninglabs/loop/swapserverrpc"
|
||||
)
|
||||
|
||||
// InitReservationContext contains the request parameters for a reservation.
|
||||
type InitReservationContext struct {
|
||||
reservationID ID
|
||||
serverPubkey *btcec.PublicKey
|
||||
value btcutil.Amount
|
||||
expiry uint32
|
||||
heightHint uint32
|
||||
}
|
||||
|
||||
// InitAction is the action that is executed when the reservation state machine
|
||||
// is initialized. It creates the reservation in the database and dispatches the
|
||||
// payment to the server.
|
||||
func (r *FSM) InitAction(eventCtx fsm.EventContext) fsm.EventType {
|
||||
// Check if the context is of the correct type.
|
||||
reservationRequest, ok := eventCtx.(*InitReservationContext)
|
||||
if !ok {
|
||||
return r.HandleError(fsm.ErrInvalidContextType)
|
||||
}
|
||||
|
||||
keyRes, err := r.cfg.Wallet.DeriveNextKey(
|
||||
r.ctx, KeyFamily,
|
||||
)
|
||||
if err != nil {
|
||||
return r.HandleError(err)
|
||||
}
|
||||
|
||||
// Send the client reservation details to the server.
|
||||
log.Debugf("Dispatching reservation to server: %x",
|
||||
reservationRequest.reservationID)
|
||||
|
||||
request := &looprpc.ServerOpenReservationRequest{
|
||||
ReservationId: reservationRequest.reservationID[:],
|
||||
ClientKey: keyRes.PubKey.SerializeCompressed(),
|
||||
}
|
||||
|
||||
_, err = r.cfg.ReservationClient.OpenReservation(r.ctx, request)
|
||||
if err != nil {
|
||||
return r.HandleError(err)
|
||||
}
|
||||
|
||||
reservation, err := NewReservation(
|
||||
reservationRequest.reservationID,
|
||||
reservationRequest.serverPubkey,
|
||||
keyRes.PubKey,
|
||||
reservationRequest.value,
|
||||
reservationRequest.expiry,
|
||||
reservationRequest.heightHint,
|
||||
keyRes.KeyLocator,
|
||||
)
|
||||
if err != nil {
|
||||
return r.HandleError(err)
|
||||
}
|
||||
|
||||
r.reservation = reservation
|
||||
|
||||
// Create the reservation in the database.
|
||||
err = r.cfg.Store.CreateReservation(r.ctx, reservation)
|
||||
if err != nil {
|
||||
return r.HandleError(err)
|
||||
}
|
||||
|
||||
return OnBroadcast
|
||||
}
|
||||
|
||||
// SubscribeToConfirmationAction is the action that is executed when the
|
||||
// reservation is waiting for confirmation. It subscribes to the confirmation
|
||||
// of the reservation transaction.
|
||||
func (r *FSM) SubscribeToConfirmationAction(_ fsm.EventContext) fsm.EventType {
|
||||
pkscript, err := r.reservation.GetPkScript()
|
||||
if err != nil {
|
||||
return r.HandleError(err)
|
||||
}
|
||||
|
||||
callCtx, cancel := context.WithCancel(r.ctx)
|
||||
defer cancel()
|
||||
|
||||
// Subscribe to the confirmation of the reservation transaction.
|
||||
log.Debugf("Subscribing to conf for reservation: %x pkscript: %x, "+
|
||||
"initiation height: %v", r.reservation.ID, pkscript,
|
||||
r.reservation.InitiationHeight)
|
||||
|
||||
confChan, errConfChan, err := r.cfg.ChainNotifier.RegisterConfirmationsNtfn(
|
||||
callCtx, nil, pkscript, DefaultConfTarget,
|
||||
r.reservation.InitiationHeight,
|
||||
)
|
||||
if err != nil {
|
||||
r.Errorf("unable to subscribe to conf notification: %v", err)
|
||||
return r.HandleError(err)
|
||||
}
|
||||
|
||||
blockChan, errBlockChan, err := r.cfg.ChainNotifier.RegisterBlockEpochNtfn(
|
||||
callCtx,
|
||||
)
|
||||
if err != nil {
|
||||
r.Errorf("unable to subscribe to block notifications: %v", err)
|
||||
return r.HandleError(err)
|
||||
}
|
||||
|
||||
// We'll now wait for the confirmation of the reservation transaction.
|
||||
for {
|
||||
select {
|
||||
case err := <-errConfChan:
|
||||
r.Errorf("conf subscription error: %v", err)
|
||||
return r.HandleError(err)
|
||||
|
||||
case err := <-errBlockChan:
|
||||
r.Errorf("block subscription error: %v", err)
|
||||
return r.HandleError(err)
|
||||
|
||||
case confInfo := <-confChan:
|
||||
r.Debugf("reservation confirmed: %v", confInfo)
|
||||
outpoint, err := r.reservation.findReservationOutput(
|
||||
confInfo.Tx,
|
||||
)
|
||||
if err != nil {
|
||||
return r.HandleError(err)
|
||||
}
|
||||
|
||||
r.reservation.ConfirmationHeight = confInfo.BlockHeight
|
||||
r.reservation.Outpoint = outpoint
|
||||
|
||||
return OnConfirmed
|
||||
|
||||
case block := <-blockChan:
|
||||
r.Debugf("block received: %v expiry: %v", block,
|
||||
r.reservation.Expiry)
|
||||
|
||||
if uint32(block) >= r.reservation.Expiry {
|
||||
return OnTimedOut
|
||||
}
|
||||
|
||||
case <-r.ctx.Done():
|
||||
return fsm.NoOp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ReservationConfirmedAction waits for the reservation to be either expired or
|
||||
// waits for other actions to happen.
|
||||
func (r *FSM) ReservationConfirmedAction(_ fsm.EventContext) fsm.EventType {
|
||||
blockHeightChan, errEpochChan, err := r.cfg.ChainNotifier.
|
||||
RegisterBlockEpochNtfn(r.ctx)
|
||||
if err != nil {
|
||||
return r.HandleError(err)
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case err := <-errEpochChan:
|
||||
return r.HandleError(err)
|
||||
|
||||
case blockHeight := <-blockHeightChan:
|
||||
expired := blockHeight >= int32(r.reservation.Expiry)
|
||||
if expired {
|
||||
r.Debugf("Reservation %v expired",
|
||||
r.reservation.ID)
|
||||
|
||||
return OnTimedOut
|
||||
}
|
||||
|
||||
case <-r.ctx.Done():
|
||||
return fsm.NoOp
|
||||
}
|
||||
}
|
||||
}
|
||||
371
instantout/reservation/actions_test.go
Normal file
371
instantout/reservation/actions_test.go
Normal file
|
|
@ -0,0 +1,371 @@
|
|||
package reservation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightninglabs/lndclient"
|
||||
"github.com/lightninglabs/loop/fsm"
|
||||
"github.com/lightninglabs/loop/swapserverrpc"
|
||||
"github.com/lightninglabs/loop/test"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultPubkeyBytes, _ = hex.DecodeString("021c97a90a411ff2b10dc2a8e32de2f29d2fa49d41bfbb52bd416e460db0747d0d")
|
||||
defaultPubkey, _ = btcec.ParsePubKey(defaultPubkeyBytes)
|
||||
|
||||
defaultValue = btcutil.Amount(100)
|
||||
|
||||
defaultExpiry = uint32(100)
|
||||
)
|
||||
|
||||
func newValidInitReservationContext() *InitReservationContext {
|
||||
return &InitReservationContext{
|
||||
reservationID: ID{0x01},
|
||||
serverPubkey: defaultPubkey,
|
||||
value: defaultValue,
|
||||
expiry: defaultExpiry,
|
||||
heightHint: 0,
|
||||
}
|
||||
}
|
||||
|
||||
func newValidClientReturn() *swapserverrpc.ServerOpenReservationResponse {
|
||||
return &swapserverrpc.ServerOpenReservationResponse{}
|
||||
}
|
||||
|
||||
type mockReservationClient struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (m *mockReservationClient) OpenReservation(ctx context.Context,
|
||||
in *swapserverrpc.ServerOpenReservationRequest,
|
||||
opts ...grpc.CallOption) (*swapserverrpc.ServerOpenReservationResponse,
|
||||
error) {
|
||||
|
||||
args := m.Called(ctx, in, opts)
|
||||
return args.Get(0).(*swapserverrpc.ServerOpenReservationResponse),
|
||||
args.Error(1)
|
||||
}
|
||||
|
||||
func (m *mockReservationClient) ReservationNotificationStream(
|
||||
ctx context.Context, in *swapserverrpc.ReservationNotificationRequest,
|
||||
opts ...grpc.CallOption,
|
||||
) (swapserverrpc.ReservationService_ReservationNotificationStreamClient,
|
||||
error) {
|
||||
|
||||
args := m.Called(ctx, in, opts)
|
||||
return args.Get(0).(swapserverrpc.ReservationService_ReservationNotificationStreamClient),
|
||||
args.Error(1)
|
||||
}
|
||||
|
||||
func (m *mockReservationClient) FetchL402(ctx context.Context,
|
||||
in *swapserverrpc.FetchL402Request,
|
||||
opts ...grpc.CallOption) (*swapserverrpc.FetchL402Response, error) {
|
||||
|
||||
args := m.Called(ctx, in, opts)
|
||||
|
||||
return args.Get(0).(*swapserverrpc.FetchL402Response),
|
||||
args.Error(1)
|
||||
}
|
||||
|
||||
type mockStore struct {
|
||||
mock.Mock
|
||||
|
||||
Store
|
||||
}
|
||||
|
||||
func (m *mockStore) CreateReservation(ctx context.Context,
|
||||
reservation *Reservation) error {
|
||||
|
||||
args := m.Called(ctx, reservation)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
// TestInitReservationAction tests the InitReservationAction of the reservation
|
||||
// state machine.
|
||||
func TestInitReservationAction(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
eventCtx fsm.EventContext
|
||||
mockStoreErr error
|
||||
mockClientReturn *swapserverrpc.ServerOpenReservationResponse
|
||||
mockClientErr error
|
||||
expectedEvent fsm.EventType
|
||||
}{
|
||||
{
|
||||
name: "success",
|
||||
eventCtx: newValidInitReservationContext(),
|
||||
mockClientReturn: newValidClientReturn(),
|
||||
expectedEvent: OnBroadcast,
|
||||
},
|
||||
{
|
||||
name: "invalid context",
|
||||
eventCtx: struct{}{},
|
||||
expectedEvent: fsm.OnError,
|
||||
},
|
||||
{
|
||||
name: "reservation server error",
|
||||
eventCtx: newValidInitReservationContext(),
|
||||
mockClientErr: errors.New("reservation server error"),
|
||||
expectedEvent: fsm.OnError,
|
||||
},
|
||||
{
|
||||
name: "store error",
|
||||
eventCtx: newValidInitReservationContext(),
|
||||
mockClientReturn: newValidClientReturn(),
|
||||
mockStoreErr: errors.New("store error"),
|
||||
expectedEvent: fsm.OnError,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
ctxb := context.Background()
|
||||
mockLnd := test.NewMockLnd()
|
||||
mockReservationClient := new(mockReservationClient)
|
||||
mockReservationClient.On(
|
||||
"OpenReservation", mock.Anything,
|
||||
mock.Anything, mock.Anything,
|
||||
).Return(tc.mockClientReturn, tc.mockClientErr)
|
||||
|
||||
mockStore := new(mockStore)
|
||||
mockStore.On(
|
||||
"CreateReservation", mock.Anything, mock.Anything,
|
||||
).Return(tc.mockStoreErr)
|
||||
|
||||
reservationFSM := &FSM{
|
||||
ctx: ctxb,
|
||||
cfg: &Config{
|
||||
Wallet: mockLnd.WalletKit,
|
||||
ChainNotifier: mockLnd.ChainNotifier,
|
||||
ReservationClient: mockReservationClient,
|
||||
Store: mockStore,
|
||||
},
|
||||
StateMachine: &fsm.StateMachine{},
|
||||
}
|
||||
|
||||
event := reservationFSM.InitAction(tc.eventCtx)
|
||||
require.Equal(t, tc.expectedEvent, event)
|
||||
}
|
||||
}
|
||||
|
||||
type MockChainNotifier struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (m *MockChainNotifier) RegisterConfirmationsNtfn(ctx context.Context,
|
||||
txid *chainhash.Hash, pkScript []byte, numConfs, heightHint int32,
|
||||
options ...lndclient.NotifierOption) (chan *chainntnfs.TxConfirmation,
|
||||
chan error, error) {
|
||||
|
||||
args := m.Called(ctx, txid, pkScript, numConfs, heightHint)
|
||||
return args.Get(0).(chan *chainntnfs.TxConfirmation), args.Get(1).(chan error), args.Error(2)
|
||||
}
|
||||
|
||||
func (m *MockChainNotifier) RegisterBlockEpochNtfn(ctx context.Context) (
|
||||
chan int32, chan error, error) {
|
||||
|
||||
args := m.Called(ctx)
|
||||
return args.Get(0).(chan int32), args.Get(1).(chan error), args.Error(2)
|
||||
}
|
||||
|
||||
func (m *MockChainNotifier) RegisterSpendNtfn(ctx context.Context,
|
||||
outpoint *wire.OutPoint, pkScript []byte, heightHint int32) (
|
||||
chan *chainntnfs.SpendDetail, chan error, error) {
|
||||
|
||||
args := m.Called(ctx, pkScript, heightHint)
|
||||
return args.Get(0).(chan *chainntnfs.SpendDetail), args.Get(1).(chan error), args.Error(2)
|
||||
}
|
||||
|
||||
// TestSubscribeToConfirmationAction tests the SubscribeToConfirmationAction of
|
||||
// the reservation state machine.
|
||||
func TestSubscribeToConfirmationAction(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
blockHeight int32
|
||||
blockErr error
|
||||
sendTxConf bool
|
||||
confErr error
|
||||
expectedEvent fsm.EventType
|
||||
}{
|
||||
{
|
||||
name: "success",
|
||||
blockHeight: 0,
|
||||
sendTxConf: true,
|
||||
expectedEvent: OnConfirmed,
|
||||
},
|
||||
{
|
||||
name: "expired",
|
||||
blockHeight: 100,
|
||||
expectedEvent: OnTimedOut,
|
||||
},
|
||||
{
|
||||
name: "block error",
|
||||
blockHeight: 0,
|
||||
blockErr: errors.New("block error"),
|
||||
expectedEvent: fsm.OnError,
|
||||
},
|
||||
{
|
||||
name: "tx confirmation error",
|
||||
blockHeight: 0,
|
||||
confErr: errors.New("tx confirmation error"),
|
||||
expectedEvent: fsm.OnError,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
chainNotifier := new(MockChainNotifier)
|
||||
|
||||
// Create the FSM.
|
||||
r := NewFSMFromReservation(
|
||||
context.Background(), &Config{
|
||||
ChainNotifier: chainNotifier,
|
||||
},
|
||||
&Reservation{
|
||||
Expiry: defaultExpiry,
|
||||
ServerPubkey: defaultPubkey,
|
||||
ClientPubkey: defaultPubkey,
|
||||
Value: defaultValue,
|
||||
},
|
||||
)
|
||||
pkScript, err := r.reservation.GetPkScript()
|
||||
require.NoError(t, err)
|
||||
|
||||
confChan := make(chan *chainntnfs.TxConfirmation)
|
||||
confErrChan := make(chan error)
|
||||
blockChan := make(chan int32)
|
||||
blockErrChan := make(chan error)
|
||||
|
||||
// Define the expected return values for the mocks.
|
||||
chainNotifier.On(
|
||||
"RegisterConfirmationsNtfn", mock.Anything, mock.Anything,
|
||||
mock.Anything, mock.Anything, mock.Anything,
|
||||
).Return(confChan, confErrChan, nil)
|
||||
|
||||
chainNotifier.On("RegisterBlockEpochNtfn", mock.Anything).Return(
|
||||
blockChan, blockErrChan, nil,
|
||||
)
|
||||
|
||||
go func() {
|
||||
// Send the tx confirmation.
|
||||
if tc.sendTxConf {
|
||||
confChan <- &chainntnfs.TxConfirmation{
|
||||
Tx: &wire.MsgTx{
|
||||
TxIn: []*wire.TxIn{},
|
||||
TxOut: []*wire.TxOut{
|
||||
{
|
||||
Value: int64(defaultValue),
|
||||
PkScript: pkScript,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
// Send the block notification.
|
||||
if tc.blockHeight != 0 {
|
||||
blockChan <- tc.blockHeight
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
// Send the block notification error.
|
||||
if tc.blockErr != nil {
|
||||
blockErrChan <- tc.blockErr
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
// Send the tx confirmation error.
|
||||
if tc.confErr != nil {
|
||||
confErrChan <- tc.confErr
|
||||
}
|
||||
}()
|
||||
|
||||
eventType := r.SubscribeToConfirmationAction(nil)
|
||||
// Assert that the return value is as expected
|
||||
require.Equal(t, tc.expectedEvent, eventType)
|
||||
|
||||
// Assert that the expected functions were called on the mocks
|
||||
chainNotifier.AssertExpectations(t)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestReservationConfirmedAction tests the ReservationConfirmedAction of the
|
||||
// reservation state machine.
|
||||
func TestReservationConfirmedAction(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
blockHeight int32
|
||||
blockErr error
|
||||
expectedEvent fsm.EventType
|
||||
}{
|
||||
{
|
||||
name: "expired",
|
||||
blockHeight: 100,
|
||||
expectedEvent: OnTimedOut,
|
||||
},
|
||||
{
|
||||
name: "block error",
|
||||
blockHeight: 0,
|
||||
blockErr: errors.New("block error"),
|
||||
expectedEvent: fsm.OnError,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
chainNotifier := new(MockChainNotifier)
|
||||
|
||||
// Create the FSM.
|
||||
r := NewFSMFromReservation(
|
||||
context.Background(), &Config{
|
||||
ChainNotifier: chainNotifier,
|
||||
},
|
||||
&Reservation{
|
||||
Expiry: defaultExpiry,
|
||||
},
|
||||
)
|
||||
|
||||
blockChan := make(chan int32)
|
||||
blockErrChan := make(chan error)
|
||||
|
||||
// Define our expected return values for the mocks.
|
||||
chainNotifier.On("RegisterBlockEpochNtfn", mock.Anything).Return(
|
||||
blockChan, blockErrChan, nil,
|
||||
)
|
||||
go func() {
|
||||
// Send the block notification.
|
||||
if tc.blockHeight != 0 {
|
||||
blockChan <- tc.blockHeight
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
// Send the block notification error.
|
||||
if tc.blockErr != nil {
|
||||
blockErrChan <- tc.blockErr
|
||||
}
|
||||
}()
|
||||
|
||||
eventType := r.ReservationConfirmedAction(nil)
|
||||
require.Equal(t, tc.expectedEvent, eventType)
|
||||
|
||||
// Assert that the expected functions were called on the mocks
|
||||
chainNotifier.AssertExpectations(t)
|
||||
})
|
||||
}
|
||||
}
|
||||
229
instantout/reservation/fsm.go
Normal file
229
instantout/reservation/fsm.go
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
package reservation
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/lightninglabs/lndclient"
|
||||
"github.com/lightninglabs/loop/fsm"
|
||||
looprpc "github.com/lightninglabs/loop/swapserverrpc"
|
||||
)
|
||||
|
||||
const (
|
||||
// defaultObserverSize is the size of the fsm observer channel.
|
||||
defaultObserverSize = 15
|
||||
)
|
||||
|
||||
// Config contains all the services that the reservation FSM needs to operate.
|
||||
type Config struct {
|
||||
// Store is the database store for the reservations.
|
||||
Store Store
|
||||
|
||||
// Wallet handles the key derivation for the reservation.
|
||||
Wallet lndclient.WalletKitClient
|
||||
|
||||
// ChainNotifier is used to subscribe to block notifications.
|
||||
ChainNotifier lndclient.ChainNotifierClient
|
||||
|
||||
// ReservationClient is the client used to communicate with the
|
||||
// swap server.
|
||||
ReservationClient looprpc.ReservationServiceClient
|
||||
|
||||
// FetchL402 is the function used to fetch the l402 token.
|
||||
FetchL402 func(context.Context) error
|
||||
}
|
||||
|
||||
// FSM is the state machine that manages the reservation lifecycle.
|
||||
type FSM struct {
|
||||
*fsm.StateMachine
|
||||
|
||||
cfg *Config
|
||||
|
||||
reservation *Reservation
|
||||
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
// NewFSM creates a new reservation FSM.
|
||||
func NewFSM(ctx context.Context, cfg *Config) *FSM {
|
||||
reservation := &Reservation{
|
||||
State: fsm.EmptyState,
|
||||
}
|
||||
|
||||
return NewFSMFromReservation(ctx, cfg, reservation)
|
||||
}
|
||||
|
||||
// NewFSMFromReservation creates a new reservation FSM from an existing
|
||||
// reservation recovered from the database.
|
||||
func NewFSMFromReservation(ctx context.Context, cfg *Config,
|
||||
reservation *Reservation) *FSM {
|
||||
|
||||
reservationFsm := &FSM{
|
||||
ctx: ctx,
|
||||
cfg: cfg,
|
||||
reservation: reservation,
|
||||
}
|
||||
|
||||
reservationFsm.StateMachine = fsm.NewStateMachineWithState(
|
||||
reservationFsm.GetReservationStates(), reservation.State,
|
||||
defaultObserverSize,
|
||||
)
|
||||
reservationFsm.ActionEntryFunc = reservationFsm.updateReservation
|
||||
|
||||
return reservationFsm
|
||||
}
|
||||
|
||||
// States.
|
||||
var (
|
||||
// Init is the initial state of the reservation.
|
||||
Init = fsm.StateType("Init")
|
||||
|
||||
// WaitForConfirmation is the state where we wait for the reservation
|
||||
// tx to be confirmed.
|
||||
WaitForConfirmation = fsm.StateType("WaitForConfirmation")
|
||||
|
||||
// Confirmed is the state where the reservation tx has been confirmed.
|
||||
Confirmed = fsm.StateType("Confirmed")
|
||||
|
||||
// TimedOut is the state where the reservation has timed out.
|
||||
TimedOut = fsm.StateType("TimedOut")
|
||||
|
||||
// Failed is the state where the reservation has failed.
|
||||
Failed = fsm.StateType("Failed")
|
||||
|
||||
// Spent is the state where a spend tx has been confirmed.
|
||||
Spent = fsm.StateType("Spent")
|
||||
|
||||
// Locked is the state where the reservation is locked and can't be
|
||||
// used for instant out swaps.
|
||||
Locked = fsm.StateType("Locked")
|
||||
)
|
||||
|
||||
// Events.
|
||||
var (
|
||||
// OnServerRequest is the event that is triggered when the server
|
||||
// requests a new reservation.
|
||||
OnServerRequest = fsm.EventType("OnServerRequest")
|
||||
|
||||
// OnBroadcast is the event that is triggered when the reservation tx
|
||||
// has been broadcast.
|
||||
OnBroadcast = fsm.EventType("OnBroadcast")
|
||||
|
||||
// OnConfirmed is the event that is triggered when the reservation tx
|
||||
// has been confirmed.
|
||||
OnConfirmed = fsm.EventType("OnConfirmed")
|
||||
|
||||
// OnTimedOut is the event that is triggered when the reservation has
|
||||
// timed out.
|
||||
OnTimedOut = fsm.EventType("OnTimedOut")
|
||||
|
||||
// OnSwept is the event that is triggered when the reservation has been
|
||||
// swept by the server.
|
||||
OnSwept = fsm.EventType("OnSwept")
|
||||
|
||||
// OnRecover is the event that is triggered when the reservation FSM
|
||||
// recovers from a restart.
|
||||
OnRecover = fsm.EventType("OnRecover")
|
||||
)
|
||||
|
||||
// GetReservationStates returns the statemap that defines the reservation
|
||||
// state machine.
|
||||
func (f *FSM) GetReservationStates() fsm.States {
|
||||
return fsm.States{
|
||||
fsm.EmptyState: fsm.State{
|
||||
Transitions: fsm.Transitions{
|
||||
OnServerRequest: Init,
|
||||
},
|
||||
Action: nil,
|
||||
},
|
||||
Init: fsm.State{
|
||||
Transitions: fsm.Transitions{
|
||||
OnBroadcast: WaitForConfirmation,
|
||||
OnRecover: Failed,
|
||||
fsm.OnError: Failed,
|
||||
},
|
||||
Action: f.InitAction,
|
||||
},
|
||||
WaitForConfirmation: fsm.State{
|
||||
Transitions: fsm.Transitions{
|
||||
OnRecover: WaitForConfirmation,
|
||||
OnConfirmed: Confirmed,
|
||||
OnTimedOut: TimedOut,
|
||||
},
|
||||
Action: f.SubscribeToConfirmationAction,
|
||||
},
|
||||
Confirmed: fsm.State{
|
||||
Transitions: fsm.Transitions{
|
||||
OnTimedOut: TimedOut,
|
||||
OnRecover: Confirmed,
|
||||
},
|
||||
Action: f.ReservationConfirmedAction,
|
||||
},
|
||||
TimedOut: fsm.State{
|
||||
Action: fsm.NoOpAction,
|
||||
},
|
||||
Failed: fsm.State{
|
||||
Action: fsm.NoOpAction,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// updateReservation updates the reservation in the database. This function
|
||||
// is called after every new state transition.
|
||||
func (r *FSM) updateReservation(notification fsm.Notification) {
|
||||
if r.reservation == nil {
|
||||
return
|
||||
}
|
||||
|
||||
r.Debugf(
|
||||
"NextState: %v, PreviousState: %v, Event: %v",
|
||||
notification.NextState, notification.PreviousState,
|
||||
notification.Event,
|
||||
)
|
||||
|
||||
r.reservation.State = notification.NextState
|
||||
|
||||
// Don't update the reservation if we are in an initial state or if we
|
||||
// are transitioning from an initial state to a failed state.
|
||||
if r.reservation.State == fsm.EmptyState ||
|
||||
r.reservation.State == Init ||
|
||||
(notification.PreviousState == Init &&
|
||||
r.reservation.State == Failed) {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
err := r.cfg.Store.UpdateReservation(r.ctx, r.reservation)
|
||||
if err != nil {
|
||||
r.Errorf("unable to update reservation: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *FSM) Infof(format string, args ...interface{}) {
|
||||
log.Infof(
|
||||
"Reservation %x: "+format,
|
||||
append([]interface{}{r.reservation.ID}, args...)...,
|
||||
)
|
||||
}
|
||||
|
||||
func (r *FSM) Debugf(format string, args ...interface{}) {
|
||||
log.Debugf(
|
||||
"Reservation %x: "+format,
|
||||
append([]interface{}{r.reservation.ID}, args...)...,
|
||||
)
|
||||
}
|
||||
|
||||
func (r *FSM) Errorf(format string, args ...interface{}) {
|
||||
log.Errorf(
|
||||
"Reservation %x: "+format,
|
||||
append([]interface{}{r.reservation.ID}, args...)...,
|
||||
)
|
||||
}
|
||||
|
||||
// isFinalState returns true if the state is a final state.
|
||||
func isFinalState(state fsm.StateType) bool {
|
||||
switch state {
|
||||
case Failed, TimedOut, Spent:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
33
instantout/reservation/interfaces.go
Normal file
33
instantout/reservation/interfaces.go
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
package reservation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrReservationAlreadyExists = fmt.Errorf("reservation already exists")
|
||||
ErrReservationNotFound = fmt.Errorf("reservation not found")
|
||||
)
|
||||
|
||||
const (
|
||||
KeyFamily = int32(42068)
|
||||
DefaultConfTarget = int32(3)
|
||||
IdLength = 32
|
||||
)
|
||||
|
||||
// Store is the interface that stores the reservations.
|
||||
type Store interface {
|
||||
// CreateReservation stores the reservation in the database.
|
||||
CreateReservation(ctx context.Context, reservation *Reservation) error
|
||||
|
||||
// UpdateReservation updates the reservation in the database.
|
||||
UpdateReservation(ctx context.Context, reservation *Reservation) error
|
||||
|
||||
// GetReservation retrieves the reservation from the database.
|
||||
GetReservation(ctx context.Context, id ID) (*Reservation, error)
|
||||
|
||||
// ListReservations lists all existing reservations the client has ever
|
||||
// made.
|
||||
ListReservations(ctx context.Context) ([]*Reservation, error)
|
||||
}
|
||||
26
instantout/reservation/log.go
Normal file
26
instantout/reservation/log.go
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
package reservation
|
||||
|
||||
import (
|
||||
"github.com/btcsuite/btclog"
|
||||
"github.com/lightningnetwork/lnd/build"
|
||||
)
|
||||
|
||||
// Subsystem defines the sub system name of this package.
|
||||
const Subsystem = "RSRV"
|
||||
|
||||
// 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
|
||||
}
|
||||
271
instantout/reservation/manager.go
Normal file
271
instantout/reservation/manager.go
Normal file
|
|
@ -0,0 +1,271 @@
|
|||
package reservation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
|
||||
"github.com/lightninglabs/loop/fsm"
|
||||
reservationrpc "github.com/lightninglabs/loop/swapserverrpc"
|
||||
)
|
||||
|
||||
// Manager manages the reservation state machines.
|
||||
type Manager struct {
|
||||
// cfg contains all the services that the reservation manager needs to
|
||||
// operate.
|
||||
cfg *Config
|
||||
|
||||
// activeReservations contains all the active reservationsFSMs.
|
||||
activeReservations map[ID]*FSM
|
||||
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// NewManager creates a new reservation manager.
|
||||
func NewManager(cfg *Config) *Manager {
|
||||
return &Manager{
|
||||
cfg: cfg,
|
||||
activeReservations: make(map[ID]*FSM),
|
||||
}
|
||||
}
|
||||
|
||||
// Run runs the reservation manager.
|
||||
func (m *Manager) Run(ctx context.Context, height int32) error {
|
||||
// todo(sputn1ck): recover swaps on startup
|
||||
log.Debugf("Starting reservation manager")
|
||||
|
||||
runCtx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
|
||||
currentHeight := height
|
||||
|
||||
err := m.RecoverReservations(runCtx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
newBlockChan, newBlockErrChan, err := m.cfg.ChainNotifier.
|
||||
RegisterBlockEpochNtfn(runCtx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
reservationResChan := make(
|
||||
chan *reservationrpc.ServerReservationNotification,
|
||||
)
|
||||
|
||||
err = m.RegisterReservationNotifications(runCtx, reservationResChan)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case height := <-newBlockChan:
|
||||
log.Debugf("Received block %v", height)
|
||||
currentHeight = height
|
||||
|
||||
case reservationRes := <-reservationResChan:
|
||||
log.Debugf("Received reservation %x",
|
||||
reservationRes.ReservationId)
|
||||
_, err := m.newReservation(
|
||||
runCtx, uint32(currentHeight), reservationRes,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case err := <-newBlockErrChan:
|
||||
return err
|
||||
|
||||
case <-runCtx.Done():
|
||||
log.Debugf("Stopping reservation manager")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// newReservation creates a new reservation from the reservation request.
|
||||
func (m *Manager) newReservation(ctx context.Context, currentHeight uint32,
|
||||
req *reservationrpc.ServerReservationNotification) (*FSM, error) {
|
||||
|
||||
var reservationID ID
|
||||
err := reservationID.FromByteSlice(
|
||||
req.ReservationId,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
serverKey, err := btcec.ParsePubKey(req.ServerKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create the reservation state machine. We need to pass in the runCtx
|
||||
// of the reservation manager so that the state machine will keep on
|
||||
// running even if the grpc conte
|
||||
reservationFSM := NewFSM(
|
||||
ctx, m.cfg,
|
||||
)
|
||||
|
||||
// Add the reservation to the active reservations map.
|
||||
m.Lock()
|
||||
m.activeReservations[reservationID] = reservationFSM
|
||||
m.Unlock()
|
||||
|
||||
initContext := &InitReservationContext{
|
||||
reservationID: reservationID,
|
||||
serverPubkey: serverKey,
|
||||
value: btcutil.Amount(req.Value),
|
||||
expiry: req.Expiry,
|
||||
heightHint: currentHeight,
|
||||
}
|
||||
|
||||
// Send the init event to the state machine.
|
||||
go func() {
|
||||
err = reservationFSM.SendEvent(OnServerRequest, initContext)
|
||||
if err != nil {
|
||||
log.Errorf("Error sending init event: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// We'll now wait for the reservation to be in the state where it is
|
||||
// waiting to be confirmed.
|
||||
err = reservationFSM.DefaultObserver.WaitForState(
|
||||
ctx, 5*time.Second, WaitForConfirmation,
|
||||
fsm.WithWaitForStateOption(time.Second),
|
||||
)
|
||||
if err != nil {
|
||||
if reservationFSM.LastActionError != nil {
|
||||
return nil, fmt.Errorf("error waiting for "+
|
||||
"state: %v, last action error: %v",
|
||||
err, reservationFSM.LastActionError)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return reservationFSM, nil
|
||||
}
|
||||
|
||||
// RegisterReservationNotifications registers a new reservation notification
|
||||
// stream.
|
||||
func (m *Manager) RegisterReservationNotifications(
|
||||
ctx context.Context, reservationChan chan *reservationrpc.
|
||||
ServerReservationNotification) error {
|
||||
|
||||
// In order to create a valid lsat we first are going to call
|
||||
// the FetchL402 method.
|
||||
err := m.cfg.FetchL402(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// We'll now subscribe to the reservation notifications.
|
||||
reservationStream, err := m.cfg.ReservationClient.
|
||||
ReservationNotificationStream(
|
||||
ctx, &reservationrpc.ReservationNotificationRequest{},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// We'll now start a goroutine that will forward all the reservation
|
||||
// notifications to the reservationChan.
|
||||
go func() {
|
||||
for {
|
||||
reservationRes, err := reservationStream.Recv()
|
||||
if err == nil && reservationRes != nil {
|
||||
log.Debugf("Received reservation %x",
|
||||
reservationRes.ReservationId)
|
||||
reservationChan <- reservationRes
|
||||
continue
|
||||
}
|
||||
log.Errorf("Error receiving "+
|
||||
"reservation: %v", err)
|
||||
|
||||
reconnectTimer := time.NewTimer(time.Second * 10)
|
||||
|
||||
// If we encounter an error, we'll
|
||||
// try to reconnect.
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-reconnectTimer.C:
|
||||
err = m.RegisterReservationNotifications(
|
||||
ctx, reservationChan,
|
||||
)
|
||||
if err == nil {
|
||||
log.Debugf(
|
||||
"Successfully " +
|
||||
"reconnected",
|
||||
)
|
||||
reconnectTimer.Stop()
|
||||
// If we were able to
|
||||
// reconnect, we'll
|
||||
// return.
|
||||
return
|
||||
}
|
||||
log.Errorf("Error "+
|
||||
"reconnecting: %v",
|
||||
err)
|
||||
|
||||
reconnectTimer.Reset(
|
||||
time.Second * 10,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RecoverReservations tries to recover all reservations that are still active
|
||||
// from the database.
|
||||
func (m *Manager) RecoverReservations(ctx context.Context) error {
|
||||
reservations, err := m.cfg.Store.ListReservations(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, reservation := range reservations {
|
||||
if isFinalState(reservation.State) {
|
||||
continue
|
||||
}
|
||||
|
||||
log.Debugf("Recovering reservation %x", reservation.ID)
|
||||
|
||||
fsmCtx := context.WithValue(ctx, reservation.ID, nil)
|
||||
|
||||
reservationFSM := NewFSMFromReservation(
|
||||
fsmCtx, m.cfg, reservation,
|
||||
)
|
||||
|
||||
m.activeReservations[reservation.ID] = reservationFSM
|
||||
|
||||
// As SendEvent can block, we'll start a goroutine to process
|
||||
// the event.
|
||||
go func() {
|
||||
err := reservationFSM.SendEvent(OnRecover, nil)
|
||||
if err != nil {
|
||||
log.Errorf("FSM %v Error sending recover "+
|
||||
"event %v, state: %v",
|
||||
reservationFSM.reservation.ID, err,
|
||||
reservationFSM.reservation.State)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetReservations retrieves all reservations from the database.
|
||||
func (m *Manager) GetReservations(ctx context.Context) ([]*Reservation, error) {
|
||||
return m.cfg.Store.ListReservations(ctx)
|
||||
}
|
||||
160
instantout/reservation/manager_test.go
Normal file
160
instantout/reservation/manager_test.go
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
package reservation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightninglabs/loop/loopdb"
|
||||
"github.com/lightninglabs/loop/swapserverrpc"
|
||||
"github.com/lightninglabs/loop/test"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultReservationId = mustDecodeID("17cecc61ab4aafebdc0542dabdae0d0cb8907ec1c9c8ae387bc5a3309ca8b600")
|
||||
)
|
||||
|
||||
func TestManager(t *testing.T) {
|
||||
ctxb, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
testContext := newManagerTestContext(t)
|
||||
|
||||
// Start the manager.
|
||||
go func() {
|
||||
err := testContext.manager.Run(ctxb, testContext.mockLnd.Height)
|
||||
require.NoError(t, err)
|
||||
}()
|
||||
|
||||
// Create a new reservation.
|
||||
fsm, err := testContext.manager.newReservation(
|
||||
ctxb, uint32(testContext.mockLnd.Height),
|
||||
&swapserverrpc.ServerReservationNotification{
|
||||
ReservationId: defaultReservationId[:],
|
||||
Value: uint64(defaultValue),
|
||||
ServerKey: defaultPubkeyBytes,
|
||||
Expiry: uint32(testContext.mockLnd.Height) + defaultExpiry,
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// We'll expect the spendConfirmation to be sent to the server.
|
||||
pkScript, err := fsm.reservation.GetPkScript()
|
||||
require.NoError(t, err)
|
||||
|
||||
conf := <-testContext.mockLnd.RegisterConfChannel
|
||||
require.Equal(t, conf.PkScript, pkScript)
|
||||
|
||||
confTx := &wire.MsgTx{
|
||||
TxOut: []*wire.TxOut{
|
||||
{
|
||||
PkScript: pkScript,
|
||||
},
|
||||
},
|
||||
}
|
||||
// We'll now confirm the spend.
|
||||
conf.ConfChan <- &chainntnfs.TxConfirmation{
|
||||
BlockHeight: uint32(testContext.mockLnd.Height),
|
||||
Tx: confTx,
|
||||
}
|
||||
|
||||
// We'll now expect the reservation to be confirmed.
|
||||
err = fsm.DefaultObserver.WaitForState(ctxb, 5*time.Second, Confirmed)
|
||||
require.NoError(t, err)
|
||||
|
||||
// We'll now expire the reservation.
|
||||
err = testContext.mockLnd.NotifyHeight(
|
||||
testContext.mockLnd.Height + int32(defaultExpiry),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
// We'll now expect the reservation to be expired.
|
||||
err = fsm.DefaultObserver.WaitForState(ctxb, 5*time.Second, TimedOut)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// ManagerTestContext is a helper struct that contains all the necessary
|
||||
// components to test the reservation manager.
|
||||
type ManagerTestContext struct {
|
||||
manager *Manager
|
||||
context test.Context
|
||||
mockLnd *test.LndMockServices
|
||||
reservationNotificationChan chan *swapserverrpc.ServerReservationNotification
|
||||
mockReservationClient *mockReservationClient
|
||||
}
|
||||
|
||||
// newManagerTestContext creates a new test context for the reservation manager.
|
||||
func newManagerTestContext(t *testing.T) *ManagerTestContext {
|
||||
mockLnd := test.NewMockLnd()
|
||||
lndContext := test.NewContext(t, mockLnd)
|
||||
|
||||
dbFixture := loopdb.NewTestDB(t)
|
||||
|
||||
store := NewSQLStore(dbFixture)
|
||||
|
||||
mockReservationClient := new(mockReservationClient)
|
||||
|
||||
sendChan := make(chan *swapserverrpc.ServerReservationNotification)
|
||||
|
||||
mockReservationClient.On(
|
||||
"ReservationNotificationStream", mock.Anything, mock.Anything,
|
||||
mock.Anything,
|
||||
).Return(
|
||||
&dummyReservationNotificationServer{
|
||||
SendChan: sendChan,
|
||||
}, nil,
|
||||
)
|
||||
|
||||
mockReservationClient.On(
|
||||
"OpenReservation", mock.Anything, mock.Anything, mock.Anything,
|
||||
).Return(
|
||||
&swapserverrpc.ServerOpenReservationResponse{}, nil,
|
||||
)
|
||||
|
||||
cfg := &Config{
|
||||
Store: store,
|
||||
Wallet: mockLnd.WalletKit,
|
||||
ChainNotifier: mockLnd.ChainNotifier,
|
||||
FetchL402: func(context.Context) error { return nil },
|
||||
ReservationClient: mockReservationClient,
|
||||
}
|
||||
|
||||
manager := NewManager(cfg)
|
||||
|
||||
return &ManagerTestContext{
|
||||
manager: manager,
|
||||
context: lndContext,
|
||||
mockLnd: mockLnd,
|
||||
mockReservationClient: mockReservationClient,
|
||||
reservationNotificationChan: sendChan,
|
||||
}
|
||||
}
|
||||
|
||||
type dummyReservationNotificationServer struct {
|
||||
grpc.ClientStream
|
||||
|
||||
// SendChan is the channel that is used to send notifications.
|
||||
SendChan chan *swapserverrpc.ServerReservationNotification
|
||||
}
|
||||
|
||||
func (d *dummyReservationNotificationServer) Recv() (
|
||||
*swapserverrpc.ServerReservationNotification, error) {
|
||||
|
||||
return <-d.SendChan, nil
|
||||
}
|
||||
|
||||
func mustDecodeID(id string) ID {
|
||||
bytes, err := hex.DecodeString(id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var decoded ID
|
||||
copy(decoded[:], bytes)
|
||||
return decoded
|
||||
}
|
||||
137
instantout/reservation/reservation.go
Normal file
137
instantout/reservation/reservation.go
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
package reservation
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightninglabs/loop/fsm"
|
||||
reservation_script "github.com/lightninglabs/loop/instantout/reservation/script"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
)
|
||||
|
||||
// ID is a unique identifier for a reservation.
|
||||
type ID [IdLength]byte
|
||||
|
||||
// FromByteSlice creates a reservation id from a byte slice.
|
||||
func (r *ID) FromByteSlice(b []byte) error {
|
||||
if len(b) != IdLength {
|
||||
return fmt.Errorf("reservation id must be 32 bytes, got %d, %x",
|
||||
len(b), b)
|
||||
}
|
||||
|
||||
copy(r[:], b)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Reservation holds all the necessary information for the 2-of-2 multisig
|
||||
// reservation utxo.
|
||||
type Reservation struct {
|
||||
// ID is the unique identifier of the reservation.
|
||||
ID ID
|
||||
|
||||
// State is the current state of the reservation.
|
||||
State fsm.StateType
|
||||
|
||||
// ClientPubkey is the client's pubkey.
|
||||
ClientPubkey *btcec.PublicKey
|
||||
|
||||
// ServerPubkey is the server's pubkey.
|
||||
ServerPubkey *btcec.PublicKey
|
||||
|
||||
// Value is the amount of the reservation.
|
||||
Value btcutil.Amount
|
||||
|
||||
// Expiry is the absolute block height at which the reservation expires.
|
||||
Expiry uint32
|
||||
|
||||
// KeyLocator is the key locator of the client's key.
|
||||
KeyLocator keychain.KeyLocator
|
||||
|
||||
// Outpoint is the outpoint of the reservation.
|
||||
Outpoint *wire.OutPoint
|
||||
|
||||
// InitiationHeight is the height at which the reservation was
|
||||
// initiated.
|
||||
InitiationHeight int32
|
||||
|
||||
// ConfirmationHeight is the height at which the reservation was
|
||||
// confirmed.
|
||||
ConfirmationHeight uint32
|
||||
}
|
||||
|
||||
func NewReservation(id ID, serverPubkey, clientPubkey *btcec.PublicKey,
|
||||
value btcutil.Amount, expiry, heightHint uint32,
|
||||
keyLocator keychain.KeyLocator) (*Reservation,
|
||||
error) {
|
||||
|
||||
if id == [32]byte{} {
|
||||
return nil, errors.New("id is empty")
|
||||
}
|
||||
|
||||
if clientPubkey == nil {
|
||||
return nil, errors.New("client pubkey is nil")
|
||||
}
|
||||
|
||||
if serverPubkey == nil {
|
||||
return nil, errors.New("server pubkey is nil")
|
||||
}
|
||||
|
||||
if expiry == 0 {
|
||||
return nil, errors.New("expiry is 0")
|
||||
}
|
||||
|
||||
if value == 0 {
|
||||
return nil, errors.New("value is 0")
|
||||
}
|
||||
|
||||
if keyLocator.Family == 0 {
|
||||
return nil, errors.New("key locator family is 0")
|
||||
}
|
||||
return &Reservation{
|
||||
ID: id,
|
||||
Value: value,
|
||||
ClientPubkey: clientPubkey,
|
||||
ServerPubkey: serverPubkey,
|
||||
KeyLocator: keyLocator,
|
||||
Expiry: expiry,
|
||||
InitiationHeight: int32(heightHint),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetPkScript returns the pk script of the reservation.
|
||||
func (r *Reservation) GetPkScript() ([]byte, error) {
|
||||
// Now that we have all the required data, we can create the pk script.
|
||||
pkScript, err := reservation_script.ReservationScript(
|
||||
r.Expiry, r.ServerPubkey, r.ClientPubkey,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return pkScript, nil
|
||||
}
|
||||
|
||||
func (r *Reservation) findReservationOutput(tx *wire.MsgTx) (*wire.OutPoint,
|
||||
error) {
|
||||
|
||||
pkScript, err := r.GetPkScript()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i, txOut := range tx.TxOut {
|
||||
if bytes.Equal(txOut.PkScript, pkScript) {
|
||||
return &wire.OutPoint{
|
||||
Hash: tx.TxHash(),
|
||||
Index: uint32(i),
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, errors.New("reservation output not found")
|
||||
}
|
||||
17
instantout/reservation/reservation_fsm.md
Normal file
17
instantout/reservation/reservation_fsm.md
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Init: OnServerRequest
|
||||
Confirmed
|
||||
Confirmed --> TimedOut: OnTimedOut
|
||||
Confirmed --> Confirmed: OnRecover
|
||||
Failed
|
||||
Init
|
||||
Init --> Failed: OnError
|
||||
Init --> WaitForConfirmation: OnBroadcast
|
||||
Init --> Failed: OnRecover
|
||||
TimedOut
|
||||
WaitForConfirmation
|
||||
WaitForConfirmation --> WaitForConfirmation: OnRecover
|
||||
WaitForConfirmation --> Confirmed: OnConfirmed
|
||||
WaitForConfirmation --> TimedOut: OnTimedOut
|
||||
```
|
||||
298
instantout/reservation/store.go
Normal file
298
instantout/reservation/store.go
Normal file
|
|
@ -0,0 +1,298 @@
|
|||
package reservation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightninglabs/loop/fsm"
|
||||
"github.com/lightninglabs/loop/loopdb"
|
||||
"github.com/lightninglabs/loop/loopdb/sqlc"
|
||||
"github.com/lightningnetwork/lnd/clock"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
)
|
||||
|
||||
// BaseDB is the interface that contains all the queries generated
|
||||
// by sqlc for the reservation table.
|
||||
type BaseDB interface {
|
||||
// CreateReservation stores the reservation in the database.
|
||||
CreateReservation(ctx context.Context,
|
||||
arg sqlc.CreateReservationParams) error
|
||||
|
||||
// GetReservation retrieves the reservation from the database.
|
||||
GetReservation(ctx context.Context,
|
||||
reservationID []byte) (sqlc.Reservation, error)
|
||||
|
||||
// GetReservationUpdates fetches all updates for a reservation.
|
||||
GetReservationUpdates(ctx context.Context,
|
||||
reservationID []byte) ([]sqlc.ReservationUpdate, error)
|
||||
|
||||
// GetReservations lists all existing reservations the client has ever
|
||||
// made.
|
||||
GetReservations(ctx context.Context) ([]sqlc.Reservation, error)
|
||||
|
||||
// UpdateReservation inserts a new reservation update.
|
||||
UpdateReservation(ctx context.Context,
|
||||
arg sqlc.UpdateReservationParams) error
|
||||
|
||||
// ExecTx allows for executing a function in the context of a database
|
||||
// transaction.
|
||||
ExecTx(ctx context.Context, txOptions loopdb.TxOptions,
|
||||
txBody func(*sqlc.Queries) error) error
|
||||
}
|
||||
|
||||
// SQLStore manages the reservations in the database.
|
||||
type SQLStore struct {
|
||||
baseDb BaseDB
|
||||
|
||||
clock clock.Clock
|
||||
}
|
||||
|
||||
// NewSQLStore creates a new SQLStore.
|
||||
func NewSQLStore(db BaseDB) *SQLStore {
|
||||
return &SQLStore{
|
||||
baseDb: db,
|
||||
clock: clock.NewDefaultClock(),
|
||||
}
|
||||
}
|
||||
|
||||
// CreateReservation stores the reservation in the database.
|
||||
func (r *SQLStore) CreateReservation(ctx context.Context,
|
||||
reservation *Reservation) error {
|
||||
|
||||
args := sqlc.CreateReservationParams{
|
||||
ReservationID: reservation.ID[:],
|
||||
ClientPubkey: reservation.ClientPubkey.SerializeCompressed(),
|
||||
ServerPubkey: reservation.ServerPubkey.SerializeCompressed(),
|
||||
Expiry: int32(reservation.Expiry),
|
||||
Value: int64(reservation.Value),
|
||||
ClientKeyFamily: int32(reservation.KeyLocator.Family),
|
||||
ClientKeyIndex: int32(reservation.KeyLocator.Index),
|
||||
InitiationHeight: reservation.InitiationHeight,
|
||||
}
|
||||
|
||||
updateArgs := sqlc.InsertReservationUpdateParams{
|
||||
ReservationID: reservation.ID[:],
|
||||
UpdateTimestamp: r.clock.Now().UTC(),
|
||||
UpdateState: string(reservation.State),
|
||||
}
|
||||
|
||||
return r.baseDb.ExecTx(ctx, &loopdb.SqliteTxOptions{},
|
||||
func(q *sqlc.Queries) error {
|
||||
err := q.CreateReservation(ctx, args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return q.InsertReservationUpdate(ctx, updateArgs)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateReservation updates the reservation in the database.
|
||||
func (r *SQLStore) UpdateReservation(ctx context.Context,
|
||||
reservation *Reservation) error {
|
||||
|
||||
var txHash []byte
|
||||
var outIndex sql.NullInt32
|
||||
if reservation.Outpoint != nil {
|
||||
txHash = reservation.Outpoint.Hash[:]
|
||||
outIndex = sql.NullInt32{
|
||||
Int32: int32(reservation.Outpoint.Index),
|
||||
Valid: true,
|
||||
}
|
||||
}
|
||||
|
||||
insertUpdateArgs := sqlc.InsertReservationUpdateParams{
|
||||
ReservationID: reservation.ID[:],
|
||||
UpdateTimestamp: r.clock.Now().UTC(),
|
||||
UpdateState: string(reservation.State),
|
||||
}
|
||||
|
||||
updateArgs := sqlc.UpdateReservationParams{
|
||||
ReservationID: reservation.ID[:],
|
||||
TxHash: txHash,
|
||||
OutIndex: outIndex,
|
||||
ConfirmationHeight: marshalSqlNullInt32(
|
||||
int32(reservation.ConfirmationHeight),
|
||||
),
|
||||
}
|
||||
|
||||
return r.baseDb.ExecTx(ctx, &loopdb.SqliteTxOptions{},
|
||||
func(q *sqlc.Queries) error {
|
||||
err := q.UpdateReservation(ctx, updateArgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return q.InsertReservationUpdate(ctx, insertUpdateArgs)
|
||||
})
|
||||
}
|
||||
|
||||
// GetReservation retrieves the reservation from the database.
|
||||
func (r *SQLStore) GetReservation(ctx context.Context,
|
||||
reservationId ID) (*Reservation, error) {
|
||||
|
||||
var reservation *Reservation
|
||||
err := r.baseDb.ExecTx(ctx, loopdb.NewSqlReadOpts(),
|
||||
func(q *sqlc.Queries) error {
|
||||
var err error
|
||||
reservationRow, err := q.GetReservation(
|
||||
ctx, reservationId[:],
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
reservationUpdates, err := q.GetReservationUpdates(
|
||||
ctx, reservationId[:],
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(reservationUpdates) == 0 {
|
||||
return errors.New("no reservation updates")
|
||||
}
|
||||
|
||||
reservation, err = sqlReservationToReservation(
|
||||
reservationRow,
|
||||
reservationUpdates[len(reservationUpdates)-1],
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return reservation, nil
|
||||
}
|
||||
|
||||
// ListReservations lists all existing reservations the client has ever made.
|
||||
func (r *SQLStore) ListReservations(ctx context.Context) ([]*Reservation,
|
||||
error) {
|
||||
|
||||
var result []*Reservation
|
||||
|
||||
err := r.baseDb.ExecTx(ctx, loopdb.NewSqlReadOpts(),
|
||||
func(q *sqlc.Queries) error {
|
||||
var err error
|
||||
|
||||
reservations, err := q.GetReservations(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, reservation := range reservations {
|
||||
reservationUpdates, err := q.GetReservationUpdates(
|
||||
ctx, reservation.ReservationID,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(reservationUpdates) == 0 {
|
||||
return errors.New(
|
||||
"no reservation updates",
|
||||
)
|
||||
}
|
||||
|
||||
res, err := sqlReservationToReservation(
|
||||
reservation, reservationUpdates[len(
|
||||
reservationUpdates,
|
||||
)-1],
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result = append(result, res)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// sqlReservationToReservation converts a sql reservation to a reservation.
|
||||
func sqlReservationToReservation(row sqlc.Reservation,
|
||||
lastUpdate sqlc.ReservationUpdate) (*Reservation,
|
||||
error) {
|
||||
|
||||
id := ID{}
|
||||
err := id.FromByteSlice(row.ReservationID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clientPubkey, err := btcec.ParsePubKey(row.ClientPubkey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
serverPubkey, err := btcec.ParsePubKey(row.ServerPubkey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var txHash *chainhash.Hash
|
||||
if row.TxHash != nil {
|
||||
txHash, err = chainhash.NewHash(row.TxHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var outpoint *wire.OutPoint
|
||||
if row.OutIndex.Valid {
|
||||
outpoint = wire.NewOutPoint(
|
||||
txHash, uint32(unmarshalSqlNullInt32(row.OutIndex)),
|
||||
)
|
||||
}
|
||||
|
||||
return &Reservation{
|
||||
ID: id,
|
||||
ClientPubkey: clientPubkey,
|
||||
ServerPubkey: serverPubkey,
|
||||
Expiry: uint32(row.Expiry),
|
||||
Value: btcutil.Amount(row.Value),
|
||||
KeyLocator: keychain.KeyLocator{
|
||||
Family: keychain.KeyFamily(row.ClientKeyFamily),
|
||||
Index: uint32(row.ClientKeyIndex),
|
||||
},
|
||||
Outpoint: outpoint,
|
||||
ConfirmationHeight: uint32(
|
||||
unmarshalSqlNullInt32(row.ConfirmationHeight),
|
||||
),
|
||||
InitiationHeight: row.InitiationHeight,
|
||||
State: fsm.StateType(lastUpdate.UpdateState),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// marshalSqlNullInt32 converts an int32 to a sql.NullInt32.
|
||||
func marshalSqlNullInt32(i int32) sql.NullInt32 {
|
||||
return sql.NullInt32{
|
||||
Int32: i,
|
||||
Valid: i != 0,
|
||||
}
|
||||
}
|
||||
|
||||
// unmarshalSqlNullInt32 converts a sql.NullInt32 to an int32.
|
||||
func unmarshalSqlNullInt32(i sql.NullInt32) int32 {
|
||||
if i.Valid {
|
||||
return i.Int32
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
96
instantout/reservation/store_test.go
Normal file
96
instantout/reservation/store_test.go
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
package reservation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightninglabs/loop/fsm"
|
||||
"github.com/lightninglabs/loop/loopdb"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// TestSqlStore tests the basic functionality of the SQLStore.
|
||||
func TestSqlStore(t *testing.T) {
|
||||
ctxb := context.Background()
|
||||
testDb := loopdb.NewTestDB(t)
|
||||
defer testDb.Close()
|
||||
|
||||
store := NewSQLStore(testDb)
|
||||
|
||||
// Create a reservation and store it.
|
||||
reservation := &Reservation{
|
||||
ID: getRandomReservationID(),
|
||||
State: fsm.StateType("init"),
|
||||
ClientPubkey: defaultPubkey,
|
||||
ServerPubkey: defaultPubkey,
|
||||
Value: 100,
|
||||
Expiry: 100,
|
||||
KeyLocator: keychain.KeyLocator{
|
||||
Family: 1,
|
||||
Index: 1,
|
||||
},
|
||||
}
|
||||
|
||||
err := store.CreateReservation(ctxb, reservation)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Get the reservation and compare it.
|
||||
reservation2, err := store.GetReservation(ctxb, reservation.ID)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, reservation, reservation2)
|
||||
|
||||
// Update the reservation and compare it.
|
||||
reservation.State = fsm.StateType("state2")
|
||||
err = store.UpdateReservation(ctxb, reservation)
|
||||
require.NoError(t, err)
|
||||
|
||||
reservation2, err = store.GetReservation(ctxb, reservation.ID)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, reservation, reservation2)
|
||||
|
||||
// Add an outpoint to the reservation and compare it.
|
||||
reservation.Outpoint = &wire.OutPoint{
|
||||
Hash: chainhash.Hash{0x01},
|
||||
Index: 0,
|
||||
}
|
||||
reservation.State = Confirmed
|
||||
|
||||
err = store.UpdateReservation(ctxb, reservation)
|
||||
require.NoError(t, err)
|
||||
|
||||
reservation2, err = store.GetReservation(ctxb, reservation.ID)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, reservation, reservation2)
|
||||
|
||||
// Add a second reservation.
|
||||
reservation3 := &Reservation{
|
||||
ID: getRandomReservationID(),
|
||||
State: fsm.StateType("init"),
|
||||
ClientPubkey: defaultPubkey,
|
||||
ServerPubkey: defaultPubkey,
|
||||
Value: 99,
|
||||
Expiry: 100,
|
||||
KeyLocator: keychain.KeyLocator{
|
||||
Family: 1,
|
||||
Index: 1,
|
||||
},
|
||||
}
|
||||
|
||||
err = store.CreateReservation(ctxb, reservation3)
|
||||
require.NoError(t, err)
|
||||
|
||||
reservations, err := store.ListReservations(ctxb)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 2, len(reservations))
|
||||
}
|
||||
|
||||
// getRandomReservationID generates a random reservation ID.
|
||||
func getRandomReservationID() ID {
|
||||
var id ID
|
||||
rand.Read(id[:]) // nolint: errcheck
|
||||
return id
|
||||
}
|
||||
|
|
@ -168,7 +168,7 @@ type Config struct {
|
|||
TotalPaymentTimeout time.Duration `long:"totalpaymenttimeout" description:"The timeout to use for off-chain payments."`
|
||||
MaxPaymentRetries int `long:"maxpaymentretries" description:"The maximum number of times an off-chain payment may be retried."`
|
||||
|
||||
EnableExperimental bool `long:"experimental" description:"Enable experimental features: taproot HTLCs and MuSig2 loop out sweeps."`
|
||||
EnableExperimental bool `long:"experimental" description:"Enable experimental features: reservations"`
|
||||
|
||||
Lnd *lndConfig `group:"lnd" namespace:"lnd"`
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,11 @@ import (
|
|||
"github.com/lightninglabs/loop"
|
||||
"github.com/lightninglabs/loop/loopd/perms"
|
||||
"github.com/lightninglabs/loop/loopdb"
|
||||
"github.com/lightninglabs/loop/looprpc"
|
||||
|
||||
"github.com/lightninglabs/loop/instantout/reservation"
|
||||
loop_looprpc "github.com/lightninglabs/loop/looprpc"
|
||||
|
||||
loop_swaprpc "github.com/lightninglabs/loop/swapserverrpc"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/macaroons"
|
||||
"google.golang.org/grpc"
|
||||
|
|
@ -62,6 +66,10 @@ type Daemon struct {
|
|||
// same process.
|
||||
swapClientServer
|
||||
|
||||
// reservationManager is the manager that handles all reservation state
|
||||
// machines.
|
||||
reservationManager *reservation.Manager
|
||||
|
||||
// ErrChan is an error channel that users of the Daemon struct must use
|
||||
// to detect runtime errors and also whether a shutdown is fully
|
||||
// completed.
|
||||
|
|
@ -226,7 +234,7 @@ func (d *Daemon) startWebServers() error {
|
|||
grpc.UnaryInterceptor(unaryInterceptor),
|
||||
grpc.StreamInterceptor(streamInterceptor),
|
||||
)
|
||||
looprpc.RegisterSwapClientServer(d.grpcServer, d)
|
||||
loop_looprpc.RegisterSwapClientServer(d.grpcServer, d)
|
||||
|
||||
// Register our debug server if it is compiled in.
|
||||
d.registerDebugServer()
|
||||
|
|
@ -286,7 +294,7 @@ func (d *Daemon) startWebServers() error {
|
|||
restProxyDest, "[::]", "[::1]", 1,
|
||||
)
|
||||
}
|
||||
err = looprpc.RegisterSwapClientHandlerFromEndpoint(
|
||||
err = loop_looprpc.RegisterSwapClientHandlerFromEndpoint(
|
||||
ctx, mux, restProxyDest, proxyOpts,
|
||||
)
|
||||
if err != nil {
|
||||
|
|
@ -399,7 +407,7 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
|
|||
return err
|
||||
}
|
||||
|
||||
swapDb, _, err := openDatabase(d.cfg, chainParams)
|
||||
swapDb, baseDb, err := openDatabase(d.cfg, chainParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -413,6 +421,15 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
|
|||
}
|
||||
d.clientCleanup = clientCleanup
|
||||
|
||||
// Create a reservation server client.
|
||||
reservationClient := loop_swaprpc.NewReservationServiceClient(
|
||||
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())
|
||||
|
||||
// Add our debug permissions to our main set of required permissions
|
||||
// if compiled in.
|
||||
for endpoint, perm := range debugRequiredPermissions {
|
||||
|
|
@ -466,17 +483,34 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
|
|||
}
|
||||
}
|
||||
|
||||
// Create the reservation rpc server.
|
||||
if d.cfg.EnableExperimental {
|
||||
reservationStore := reservation.NewSQLStore(baseDb)
|
||||
reservationConfig := &reservation.Config{
|
||||
Store: reservationStore,
|
||||
Wallet: d.lnd.WalletKit,
|
||||
ChainNotifier: d.lnd.ChainNotifier,
|
||||
ReservationClient: reservationClient,
|
||||
FetchL402: swapClient.Server.FetchL402,
|
||||
}
|
||||
|
||||
d.reservationManager = reservation.NewManager(
|
||||
reservationConfig,
|
||||
)
|
||||
}
|
||||
|
||||
// Now finally fully initialize the swap client RPC server instance.
|
||||
d.swapClientServer = swapClientServer{
|
||||
config: d.cfg,
|
||||
network: lndclient.Network(d.cfg.Network),
|
||||
impl: swapClient,
|
||||
liquidityMgr: getLiquidityManager(swapClient),
|
||||
lnd: &d.lnd.LndServices,
|
||||
swaps: make(map[lntypes.Hash]loop.SwapInfo),
|
||||
subscribers: make(map[int]chan<- interface{}),
|
||||
statusChan: make(chan loop.SwapInfo),
|
||||
mainCtx: d.mainCtx,
|
||||
config: d.cfg,
|
||||
network: lndclient.Network(d.cfg.Network),
|
||||
impl: swapClient,
|
||||
liquidityMgr: getLiquidityManager(swapClient),
|
||||
lnd: &d.lnd.LndServices,
|
||||
swaps: make(map[lntypes.Hash]loop.SwapInfo),
|
||||
subscribers: make(map[int]chan<- interface{}),
|
||||
statusChan: make(chan loop.SwapInfo),
|
||||
mainCtx: d.mainCtx,
|
||||
reservationManager: d.reservationManager,
|
||||
}
|
||||
|
||||
// Retrieve all currently existing swaps from the database.
|
||||
|
|
@ -543,6 +577,32 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
|
|||
log.Info("Liquidity manager stopped")
|
||||
}()
|
||||
|
||||
// Start the reservation manager.
|
||||
if d.reservationManager != nil {
|
||||
d.wg.Add(1)
|
||||
go func() {
|
||||
defer d.wg.Done()
|
||||
|
||||
// We need to know the current block height to properly
|
||||
// initialize the reservation manager.
|
||||
getInfo, err := d.lnd.Client.GetInfo(d.mainCtx)
|
||||
if err != nil {
|
||||
d.internalErrChan <- err
|
||||
return
|
||||
}
|
||||
|
||||
log.Info("Starting reservation manager")
|
||||
defer log.Info("Reservation manager stopped")
|
||||
|
||||
err = d.reservationManager.Run(
|
||||
d.mainCtx, int32(getInfo.BlockHeight),
|
||||
)
|
||||
if err != nil && !errors.Is(err, context.Canceled) {
|
||||
d.internalErrChan <- err
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// 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
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import (
|
|||
"github.com/lightninglabs/lndclient"
|
||||
"github.com/lightninglabs/loop"
|
||||
"github.com/lightninglabs/loop/fsm"
|
||||
"github.com/lightninglabs/loop/instantout/reservation"
|
||||
"github.com/lightninglabs/loop/liquidity"
|
||||
"github.com/lightninglabs/loop/loopdb"
|
||||
"github.com/lightningnetwork/lnd"
|
||||
|
|
@ -38,6 +39,9 @@ func SetupLoggers(root *build.RotatingLogWriter, intercept signal.Interceptor) {
|
|||
root, liquidity.Subsystem, intercept, liquidity.UseLogger,
|
||||
)
|
||||
lnd.AddSubLogger(root, fsm.Subsystem, intercept, fsm.UseLogger)
|
||||
lnd.AddSubLogger(
|
||||
root, reservation.Subsystem, intercept, reservation.UseLogger,
|
||||
)
|
||||
}
|
||||
|
||||
// genSubLogger creates a logger for a subsystem. We provide an instance of
|
||||
|
|
|
|||
|
|
@ -96,4 +96,8 @@ var RequiredPermissions = map[string][]bakery.Op{
|
|||
Entity: "loop",
|
||||
Action: "in",
|
||||
}},
|
||||
"/looprpc.SwapClient/ListReservations": {{
|
||||
Entity: "reservation",
|
||||
Action: "read",
|
||||
}},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import (
|
|||
"github.com/lightninglabs/aperture/lsat"
|
||||
"github.com/lightninglabs/lndclient"
|
||||
"github.com/lightninglabs/loop"
|
||||
"github.com/lightninglabs/loop/instantout/reservation"
|
||||
"github.com/lightninglabs/loop/labels"
|
||||
"github.com/lightninglabs/loop/liquidity"
|
||||
"github.com/lightninglabs/loop/loopdb"
|
||||
|
|
@ -74,17 +75,18 @@ type swapClientServer struct {
|
|||
clientrpc.UnimplementedSwapClientServer
|
||||
clientrpc.UnimplementedDebugServer
|
||||
|
||||
config *Config
|
||||
network lndclient.Network
|
||||
impl *loop.Client
|
||||
liquidityMgr *liquidity.Manager
|
||||
lnd *lndclient.LndServices
|
||||
swaps map[lntypes.Hash]loop.SwapInfo
|
||||
subscribers map[int]chan<- interface{}
|
||||
statusChan chan loop.SwapInfo
|
||||
nextSubscriberID int
|
||||
swapsLock sync.Mutex
|
||||
mainCtx context.Context
|
||||
config *Config
|
||||
network lndclient.Network
|
||||
impl *loop.Client
|
||||
liquidityMgr *liquidity.Manager
|
||||
lnd *lndclient.LndServices
|
||||
reservationManager *reservation.Manager
|
||||
swaps map[lntypes.Hash]loop.SwapInfo
|
||||
subscribers map[int]chan<- interface{}
|
||||
statusChan chan loop.SwapInfo
|
||||
nextSubscriberID int
|
||||
swapsLock sync.Mutex
|
||||
mainCtx context.Context
|
||||
}
|
||||
|
||||
// LoopOut initiates a loop out swap with the given parameters. The call returns
|
||||
|
|
@ -1138,6 +1140,29 @@ func (s *swapClientServer) SuggestSwaps(ctx context.Context,
|
|||
return resp, nil
|
||||
}
|
||||
|
||||
// ListReservations lists all existing reservations the client has ever made.
|
||||
func (s *swapClientServer) ListReservations(ctx context.Context,
|
||||
_ *clientrpc.ListReservationsRequest) (
|
||||
*clientrpc.ListReservationsResponse, error) {
|
||||
|
||||
if s.reservationManager == nil {
|
||||
return nil, status.Error(codes.Unimplemented,
|
||||
"Restart loop with --experimental")
|
||||
}
|
||||
reservations, err := s.reservationManager.GetReservations(
|
||||
ctx,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &clientrpc.ListReservationsResponse{
|
||||
Reservations: ToClientReservations(
|
||||
reservations,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func rpcAutoloopReason(reason liquidity.Reason) (clientrpc.AutoReason, error) {
|
||||
switch reason {
|
||||
case liquidity.ReasonNone:
|
||||
|
|
@ -1397,3 +1422,40 @@ func getPublicationDeadline(unixTimestamp uint64) time.Time {
|
|||
return time.Unix(int64(unixTimestamp), 0)
|
||||
}
|
||||
}
|
||||
|
||||
// ToClientReservations converts a slice of server
|
||||
// reservations to a slice of client reservations.
|
||||
func ToClientReservations(
|
||||
res []*reservation.Reservation) []*clientrpc.ClientReservation {
|
||||
|
||||
var result []*clientrpc.ClientReservation
|
||||
for _, r := range res {
|
||||
result = append(result, toClientReservation(r))
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// toClientReservation converts a server reservation to a
|
||||
// client reservation.
|
||||
func toClientReservation(
|
||||
res *reservation.Reservation) *clientrpc.ClientReservation {
|
||||
|
||||
var (
|
||||
txid []byte
|
||||
vout uint32
|
||||
)
|
||||
if res.Outpoint != nil {
|
||||
txid = res.Outpoint.Hash[:]
|
||||
vout = res.Outpoint.Index
|
||||
}
|
||||
|
||||
return &clientrpc.ClientReservation{
|
||||
ReservationId: res.ID[:],
|
||||
State: string(res.State),
|
||||
Amount: uint64(res.Value),
|
||||
TxId: txid,
|
||||
Vout: vout,
|
||||
Expiry: res.Expiry,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
loopdb/sqlc/migrations/000003_reservations.down.sql
Normal file
2
loopdb/sqlc/migrations/000003_reservations.down.sql
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
DROP TABLE IF EXISTS reservation_updates;
|
||||
DROP TABLE IF EXISTS reservations;
|
||||
56
loopdb/sqlc/migrations/000003_reservations.up.sql
Normal file
56
loopdb/sqlc/migrations/000003_reservations.up.sql
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
-- reservations contains all the information about a reservation.
|
||||
CREATE TABLE IF NOT EXISTS reservations (
|
||||
-- id is the auto incrementing primary key.
|
||||
id INTEGER PRIMARY KEY,
|
||||
|
||||
-- reservation_id is the unique identifier for the reservation.
|
||||
reservation_id BLOB NOT NULL UNIQUE,
|
||||
|
||||
-- client_pubkey is the public key of the client.
|
||||
client_pubkey BLOB NOT NULL,
|
||||
|
||||
-- server_pubkey is the public key of the server.
|
||||
server_pubkey BLOB NOT NULL,
|
||||
|
||||
-- expiry is the absolute expiry height of the reservation.
|
||||
expiry INTEGER NOT NULL,
|
||||
|
||||
-- value is the value of the reservation.
|
||||
value BIGINT NOT NULL,
|
||||
|
||||
-- client_key_family is the key family of the client.
|
||||
client_key_family INTEGER NOT NULL,
|
||||
|
||||
-- client_key_index is the key index of the client.
|
||||
client_key_index INTEGER NOT NULL,
|
||||
|
||||
-- initiation_height is the height at which the reservation was initiated.
|
||||
initiation_height INTEGER NOT NULL,
|
||||
|
||||
-- tx_hash is the hash of the transaction that created the reservation.
|
||||
tx_hash BLOB,
|
||||
|
||||
-- out_index is the index of the output that created the reservation.
|
||||
out_index INTEGER,
|
||||
|
||||
-- confirmation_height is the height at which the reservation was confirmed.
|
||||
confirmation_height INTEGER
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS reservations_reservation_id_idx ON reservations(reservation_id);
|
||||
|
||||
-- reservation_updates contains all the updates to a reservation.
|
||||
CREATE TABLE IF NOT EXISTS reservation_updates (
|
||||
-- id is the auto incrementing primary key.
|
||||
id INTEGER PRIMARY KEY,
|
||||
|
||||
-- reservation_id is the unique identifier for the reservation.
|
||||
reservation_id BLOB NOT NULL REFERENCES reservations(reservation_id),
|
||||
|
||||
-- update_state is the state of the reservation at the time of the update.
|
||||
update_state TEXT NOT NULL,
|
||||
|
||||
-- update_timestamp is the timestamp of the update.
|
||||
update_timestamp TIMESTAMP NOT NULL
|
||||
);
|
||||
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
package sqlc
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
|
@ -43,6 +44,28 @@ type LoopoutSwap struct {
|
|||
PublicationDeadline time.Time
|
||||
}
|
||||
|
||||
type Reservation struct {
|
||||
ID int32
|
||||
ReservationID []byte
|
||||
ClientPubkey []byte
|
||||
ServerPubkey []byte
|
||||
Expiry int32
|
||||
Value int64
|
||||
ClientKeyFamily int32
|
||||
ClientKeyIndex int32
|
||||
InitiationHeight int32
|
||||
TxHash []byte
|
||||
OutIndex sql.NullInt32
|
||||
ConfirmationHeight sql.NullInt32
|
||||
}
|
||||
|
||||
type ReservationUpdate struct {
|
||||
ID int32
|
||||
ReservationID []byte
|
||||
UpdateState string
|
||||
UpdateTimestamp time.Time
|
||||
}
|
||||
|
||||
type Swap struct {
|
||||
ID int32
|
||||
SwapHash []byte
|
||||
|
|
|
|||
|
|
@ -9,17 +9,23 @@ import (
|
|||
)
|
||||
|
||||
type Querier interface {
|
||||
CreateReservation(ctx context.Context, arg CreateReservationParams) error
|
||||
FetchLiquidityParams(ctx context.Context) ([]byte, error)
|
||||
GetLoopInSwap(ctx context.Context, swapHash []byte) (GetLoopInSwapRow, error)
|
||||
GetLoopInSwaps(ctx context.Context) ([]GetLoopInSwapsRow, error)
|
||||
GetLoopOutSwap(ctx context.Context, swapHash []byte) (GetLoopOutSwapRow, error)
|
||||
GetLoopOutSwaps(ctx context.Context) ([]GetLoopOutSwapsRow, error)
|
||||
GetReservation(ctx context.Context, reservationID []byte) (Reservation, error)
|
||||
GetReservationUpdates(ctx context.Context, reservationID []byte) ([]ReservationUpdate, error)
|
||||
GetReservations(ctx context.Context) ([]Reservation, error)
|
||||
GetSwapUpdates(ctx context.Context, swapHash []byte) ([]SwapUpdate, error)
|
||||
InsertHtlcKeys(ctx context.Context, arg InsertHtlcKeysParams) error
|
||||
InsertLoopIn(ctx context.Context, arg InsertLoopInParams) error
|
||||
InsertLoopOut(ctx context.Context, arg InsertLoopOutParams) error
|
||||
InsertReservationUpdate(ctx context.Context, arg InsertReservationUpdateParams) error
|
||||
InsertSwap(ctx context.Context, arg InsertSwapParams) error
|
||||
InsertSwapUpdate(ctx context.Context, arg InsertSwapUpdateParams) error
|
||||
UpdateReservation(ctx context.Context, arg UpdateReservationParams) error
|
||||
UpsertLiquidityParams(ctx context.Context, params []byte) error
|
||||
}
|
||||
|
||||
|
|
|
|||
66
loopdb/sqlc/queries/reservations.sql
Normal file
66
loopdb/sqlc/queries/reservations.sql
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
-- name: CreateReservation :exec
|
||||
INSERT INTO reservations (
|
||||
reservation_id,
|
||||
client_pubkey,
|
||||
server_pubkey,
|
||||
expiry,
|
||||
value,
|
||||
client_key_family,
|
||||
client_key_index,
|
||||
initiation_height
|
||||
) VALUES (
|
||||
$1,
|
||||
$2,
|
||||
$3,
|
||||
$4,
|
||||
$5,
|
||||
$6,
|
||||
$7,
|
||||
$8
|
||||
);
|
||||
|
||||
-- name: UpdateReservation :exec
|
||||
UPDATE reservations
|
||||
SET
|
||||
tx_hash = $2,
|
||||
out_index = $3,
|
||||
confirmation_height = $4
|
||||
WHERE
|
||||
reservations.reservation_id = $1;
|
||||
|
||||
-- name: InsertReservationUpdate :exec
|
||||
INSERT INTO reservation_updates (
|
||||
reservation_id,
|
||||
update_state,
|
||||
update_timestamp
|
||||
) VALUES (
|
||||
$1,
|
||||
$2,
|
||||
$3
|
||||
);
|
||||
|
||||
-- name: GetReservation :one
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
reservations
|
||||
WHERE
|
||||
reservation_id = $1;
|
||||
|
||||
-- name: GetReservations :many
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
reservations
|
||||
ORDER BY
|
||||
id ASC;
|
||||
|
||||
-- name: GetReservationUpdates :many
|
||||
SELECT
|
||||
reservation_updates.*
|
||||
FROM
|
||||
reservation_updates
|
||||
WHERE
|
||||
reservation_id = $1
|
||||
ORDER BY
|
||||
id ASC;
|
||||
222
loopdb/sqlc/reservations.sql.go
Normal file
222
loopdb/sqlc/reservations.sql.go
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.17.2
|
||||
// source: reservations.sql
|
||||
|
||||
package sqlc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"time"
|
||||
)
|
||||
|
||||
const createReservation = `-- name: CreateReservation :exec
|
||||
INSERT INTO reservations (
|
||||
reservation_id,
|
||||
client_pubkey,
|
||||
server_pubkey,
|
||||
expiry,
|
||||
value,
|
||||
client_key_family,
|
||||
client_key_index,
|
||||
initiation_height
|
||||
) VALUES (
|
||||
$1,
|
||||
$2,
|
||||
$3,
|
||||
$4,
|
||||
$5,
|
||||
$6,
|
||||
$7,
|
||||
$8
|
||||
)
|
||||
`
|
||||
|
||||
type CreateReservationParams struct {
|
||||
ReservationID []byte
|
||||
ClientPubkey []byte
|
||||
ServerPubkey []byte
|
||||
Expiry int32
|
||||
Value int64
|
||||
ClientKeyFamily int32
|
||||
ClientKeyIndex int32
|
||||
InitiationHeight int32
|
||||
}
|
||||
|
||||
func (q *Queries) CreateReservation(ctx context.Context, arg CreateReservationParams) error {
|
||||
_, err := q.db.ExecContext(ctx, createReservation,
|
||||
arg.ReservationID,
|
||||
arg.ClientPubkey,
|
||||
arg.ServerPubkey,
|
||||
arg.Expiry,
|
||||
arg.Value,
|
||||
arg.ClientKeyFamily,
|
||||
arg.ClientKeyIndex,
|
||||
arg.InitiationHeight,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const getReservation = `-- name: GetReservation :one
|
||||
SELECT
|
||||
id, reservation_id, client_pubkey, server_pubkey, expiry, value, client_key_family, client_key_index, initiation_height, tx_hash, out_index, confirmation_height
|
||||
FROM
|
||||
reservations
|
||||
WHERE
|
||||
reservation_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetReservation(ctx context.Context, reservationID []byte) (Reservation, error) {
|
||||
row := q.db.QueryRowContext(ctx, getReservation, reservationID)
|
||||
var i Reservation
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.ReservationID,
|
||||
&i.ClientPubkey,
|
||||
&i.ServerPubkey,
|
||||
&i.Expiry,
|
||||
&i.Value,
|
||||
&i.ClientKeyFamily,
|
||||
&i.ClientKeyIndex,
|
||||
&i.InitiationHeight,
|
||||
&i.TxHash,
|
||||
&i.OutIndex,
|
||||
&i.ConfirmationHeight,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getReservationUpdates = `-- name: GetReservationUpdates :many
|
||||
SELECT
|
||||
reservation_updates.id, reservation_updates.reservation_id, reservation_updates.update_state, reservation_updates.update_timestamp
|
||||
FROM
|
||||
reservation_updates
|
||||
WHERE
|
||||
reservation_id = $1
|
||||
ORDER BY
|
||||
id ASC
|
||||
`
|
||||
|
||||
func (q *Queries) GetReservationUpdates(ctx context.Context, reservationID []byte) ([]ReservationUpdate, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getReservationUpdates, reservationID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []ReservationUpdate
|
||||
for rows.Next() {
|
||||
var i ReservationUpdate
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.ReservationID,
|
||||
&i.UpdateState,
|
||||
&i.UpdateTimestamp,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getReservations = `-- name: GetReservations :many
|
||||
SELECT
|
||||
id, reservation_id, client_pubkey, server_pubkey, expiry, value, client_key_family, client_key_index, initiation_height, tx_hash, out_index, confirmation_height
|
||||
FROM
|
||||
reservations
|
||||
ORDER BY
|
||||
id ASC
|
||||
`
|
||||
|
||||
func (q *Queries) GetReservations(ctx context.Context) ([]Reservation, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getReservations)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Reservation
|
||||
for rows.Next() {
|
||||
var i Reservation
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.ReservationID,
|
||||
&i.ClientPubkey,
|
||||
&i.ServerPubkey,
|
||||
&i.Expiry,
|
||||
&i.Value,
|
||||
&i.ClientKeyFamily,
|
||||
&i.ClientKeyIndex,
|
||||
&i.InitiationHeight,
|
||||
&i.TxHash,
|
||||
&i.OutIndex,
|
||||
&i.ConfirmationHeight,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const insertReservationUpdate = `-- name: InsertReservationUpdate :exec
|
||||
INSERT INTO reservation_updates (
|
||||
reservation_id,
|
||||
update_state,
|
||||
update_timestamp
|
||||
) VALUES (
|
||||
$1,
|
||||
$2,
|
||||
$3
|
||||
)
|
||||
`
|
||||
|
||||
type InsertReservationUpdateParams struct {
|
||||
ReservationID []byte
|
||||
UpdateState string
|
||||
UpdateTimestamp time.Time
|
||||
}
|
||||
|
||||
func (q *Queries) InsertReservationUpdate(ctx context.Context, arg InsertReservationUpdateParams) error {
|
||||
_, err := q.db.ExecContext(ctx, insertReservationUpdate, arg.ReservationID, arg.UpdateState, arg.UpdateTimestamp)
|
||||
return err
|
||||
}
|
||||
|
||||
const updateReservation = `-- name: UpdateReservation :exec
|
||||
UPDATE reservations
|
||||
SET
|
||||
tx_hash = $2,
|
||||
out_index = $3,
|
||||
confirmation_height = $4
|
||||
WHERE
|
||||
reservations.reservation_id = $1
|
||||
`
|
||||
|
||||
type UpdateReservationParams struct {
|
||||
ReservationID []byte
|
||||
TxHash []byte
|
||||
OutIndex sql.NullInt32
|
||||
ConfirmationHeight sql.NullInt32
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateReservation(ctx context.Context, arg UpdateReservationParams) error {
|
||||
_, err := q.db.ExecContext(ctx, updateReservation,
|
||||
arg.ReservationID,
|
||||
arg.TxHash,
|
||||
arg.OutIndex,
|
||||
arg.ConfirmationHeight,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
|
@ -468,9 +468,9 @@ type ListSwapsFilter_SwapTypeFilter int32
|
|||
const (
|
||||
// ANY indicates that no filter is applied.
|
||||
ListSwapsFilter_ANY ListSwapsFilter_SwapTypeFilter = 0
|
||||
// LOOP_OUT indicates an loop out swap (off-chain to on-chain)
|
||||
// LOOP_OUT indicates an loop out swap (off-chain to on-chain).
|
||||
ListSwapsFilter_LOOP_OUT ListSwapsFilter_SwapTypeFilter = 1
|
||||
// LOOP_IN indicates a loop in swap (on-chain to off-chain)
|
||||
// LOOP_IN indicates a loop in swap (on-chain to off-chain).
|
||||
ListSwapsFilter_LOOP_IN ListSwapsFilter_SwapTypeFilter = 2
|
||||
)
|
||||
|
||||
|
|
@ -3390,6 +3390,192 @@ func (*AbandonSwapResponse) Descriptor() ([]byte, []int) {
|
|||
return file_client_proto_rawDescGZIP(), []int{32}
|
||||
}
|
||||
|
||||
type ListReservationsRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
}
|
||||
|
||||
func (x *ListReservationsRequest) Reset() {
|
||||
*x = ListReservationsRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_client_proto_msgTypes[33]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ListReservationsRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ListReservationsRequest) ProtoMessage() {}
|
||||
|
||||
func (x *ListReservationsRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_client_proto_msgTypes[33]
|
||||
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 ListReservationsRequest.ProtoReflect.Descriptor instead.
|
||||
func (*ListReservationsRequest) Descriptor() ([]byte, []int) {
|
||||
return file_client_proto_rawDescGZIP(), []int{33}
|
||||
}
|
||||
|
||||
type ListReservationsResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
//
|
||||
//The list of all currently known reservations and their status.
|
||||
Reservations []*ClientReservation `protobuf:"bytes,1,rep,name=reservations,proto3" json:"reservations,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ListReservationsResponse) Reset() {
|
||||
*x = ListReservationsResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_client_proto_msgTypes[34]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ListReservationsResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ListReservationsResponse) ProtoMessage() {}
|
||||
|
||||
func (x *ListReservationsResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_client_proto_msgTypes[34]
|
||||
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 ListReservationsResponse.ProtoReflect.Descriptor instead.
|
||||
func (*ListReservationsResponse) Descriptor() ([]byte, []int) {
|
||||
return file_client_proto_rawDescGZIP(), []int{34}
|
||||
}
|
||||
|
||||
func (x *ListReservationsResponse) GetReservations() []*ClientReservation {
|
||||
if x != nil {
|
||||
return x.Reservations
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ClientReservation struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
//
|
||||
//The reservation id that identifies this reservation.
|
||||
ReservationId []byte `protobuf:"bytes,1,opt,name=reservation_id,json=reservationId,proto3" json:"reservation_id,omitempty"`
|
||||
//
|
||||
//The state the reservation is in.
|
||||
State string `protobuf:"bytes,2,opt,name=state,proto3" json:"state,omitempty"`
|
||||
//
|
||||
//The amount that the reservation is for.
|
||||
Amount uint64 `protobuf:"varint,3,opt,name=amount,proto3" json:"amount,omitempty"`
|
||||
//
|
||||
//The transaction id of the reservation.
|
||||
TxId []byte `protobuf:"bytes,4,opt,name=tx_id,json=txId,proto3" json:"tx_id,omitempty"`
|
||||
//
|
||||
//The vout of the reservation.
|
||||
Vout uint32 `protobuf:"varint,5,opt,name=vout,proto3" json:"vout,omitempty"`
|
||||
//
|
||||
//The expiry of the reservation.
|
||||
Expiry uint32 `protobuf:"varint,6,opt,name=expiry,proto3" json:"expiry,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ClientReservation) Reset() {
|
||||
*x = ClientReservation{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_client_proto_msgTypes[35]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ClientReservation) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ClientReservation) ProtoMessage() {}
|
||||
|
||||
func (x *ClientReservation) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_client_proto_msgTypes[35]
|
||||
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 ClientReservation.ProtoReflect.Descriptor instead.
|
||||
func (*ClientReservation) Descriptor() ([]byte, []int) {
|
||||
return file_client_proto_rawDescGZIP(), []int{35}
|
||||
}
|
||||
|
||||
func (x *ClientReservation) GetReservationId() []byte {
|
||||
if x != nil {
|
||||
return x.ReservationId
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ClientReservation) GetState() string {
|
||||
if x != nil {
|
||||
return x.State
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ClientReservation) GetAmount() uint64 {
|
||||
if x != nil {
|
||||
return x.Amount
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ClientReservation) GetTxId() []byte {
|
||||
if x != nil {
|
||||
return x.TxId
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ClientReservation) GetVout() uint32 {
|
||||
if x != nil {
|
||||
return x.Vout
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ClientReservation) GetExpiry() uint32 {
|
||||
if x != nil {
|
||||
return x.Expiry
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
var File_client_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_client_proto_rawDesc = []byte{
|
||||
|
|
@ -3805,142 +3991,166 @@ var file_client_proto_rawDesc = []byte{
|
|||
0x64, 0x6f, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x69, 0x4b, 0x6e,
|
||||
0x6f, 0x77, 0x57, 0x68, 0x61, 0x74, 0x49, 0x41, 0x6d, 0x44, 0x6f, 0x69, 0x6e, 0x67, 0x22, 0x15,
|
||||
0x0a, 0x13, 0x41, 0x62, 0x61, 0x6e, 0x64, 0x6f, 0x6e, 0x53, 0x77, 0x61, 0x70, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 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, 0xbe,
|
||||
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,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73,
|
||||
0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x22, 0x5a, 0x0a, 0x18, 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, 0x3e, 0x0a, 0x0c,
|
||||
0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03,
|
||||
0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6c, 0x69,
|
||||
0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c,
|
||||
0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xa9, 0x01, 0x0a,
|
||||
0x11, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x65,
|
||||
0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61,
|
||||
0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12,
|
||||
0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52,
|
||||
0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x13, 0x0a, 0x05, 0x74, 0x78, 0x5f, 0x69, 0x64,
|
||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x74, 0x78, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04,
|
||||
0x76, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x76, 0x6f, 0x75, 0x74,
|
||||
0x12, 0x16, 0x0a, 0x06, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d,
|
||||
0x52, 0x06, 0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 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, 0xbe, 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, 0x41, 0x42, 0x41, 0x4e, 0x44, 0x4f, 0x4e, 0x45, 0x44, 0x10, 0x07, 0x12, 0x31, 0x0a, 0x2d,
|
||||
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, 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, 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, 0xca, 0x08, 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, 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,
|
||||
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, 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, 0xa3, 0x09, 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, 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, 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, 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,
|
||||
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, 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,
|
||||
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, 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,
|
||||
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, 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 (
|
||||
|
|
@ -3956,7 +4166,7 @@ func file_client_proto_rawDescGZIP() []byte {
|
|||
}
|
||||
|
||||
var file_client_proto_enumTypes = make([]protoimpl.EnumInfo, 7)
|
||||
var file_client_proto_msgTypes = make([]protoimpl.MessageInfo, 33)
|
||||
var file_client_proto_msgTypes = make([]protoimpl.MessageInfo, 36)
|
||||
var file_client_proto_goTypes = []interface{}{
|
||||
(AddressType)(0), // 0: looprpc.AddressType
|
||||
(SwapType)(0), // 1: looprpc.SwapType
|
||||
|
|
@ -3998,19 +4208,22 @@ var file_client_proto_goTypes = []interface{}{
|
|||
(*SuggestSwapsResponse)(nil), // 37: looprpc.SuggestSwapsResponse
|
||||
(*AbandonSwapRequest)(nil), // 38: looprpc.AbandonSwapRequest
|
||||
(*AbandonSwapResponse)(nil), // 39: looprpc.AbandonSwapResponse
|
||||
(*swapserverrpc.RouteHint)(nil), // 40: looprpc.RouteHint
|
||||
(*ListReservationsRequest)(nil), // 40: looprpc.ListReservationsRequest
|
||||
(*ListReservationsResponse)(nil), // 41: looprpc.ListReservationsResponse
|
||||
(*ClientReservation)(nil), // 42: looprpc.ClientReservation
|
||||
(*swapserverrpc.RouteHint)(nil), // 43: looprpc.RouteHint
|
||||
}
|
||||
var file_client_proto_depIdxs = []int32{
|
||||
0, // 0: looprpc.LoopOutRequest.account_addr_type:type_name -> looprpc.AddressType
|
||||
40, // 1: looprpc.LoopInRequest.route_hints:type_name -> looprpc.RouteHint
|
||||
43, // 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
|
||||
40, // 8: looprpc.QuoteRequest.loop_in_route_hints:type_name -> looprpc.RouteHint
|
||||
40, // 9: looprpc.ProbeRequest.route_hints:type_name -> looprpc.RouteHint
|
||||
43, // 8: looprpc.QuoteRequest.loop_in_route_hints:type_name -> looprpc.RouteHint
|
||||
43, // 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
|
||||
|
|
@ -4023,43 +4236,46 @@ var file_client_proto_depIdxs = []int32{
|
|||
7, // 19: looprpc.SuggestSwapsResponse.loop_out:type_name -> looprpc.LoopOutRequest
|
||||
8, // 20: looprpc.SuggestSwapsResponse.loop_in:type_name -> looprpc.LoopInRequest
|
||||
36, // 21: looprpc.SuggestSwapsResponse.disqualified:type_name -> looprpc.Disqualified
|
||||
7, // 22: looprpc.SwapClient.LoopOut:input_type -> looprpc.LoopOutRequest
|
||||
8, // 23: looprpc.SwapClient.LoopIn:input_type -> looprpc.LoopInRequest
|
||||
10, // 24: looprpc.SwapClient.Monitor:input_type -> looprpc.MonitorRequest
|
||||
12, // 25: looprpc.SwapClient.ListSwaps:input_type -> looprpc.ListSwapsRequest
|
||||
15, // 26: looprpc.SwapClient.SwapInfo:input_type -> looprpc.SwapInfoRequest
|
||||
38, // 27: looprpc.SwapClient.AbandonSwap:input_type -> looprpc.AbandonSwapRequest
|
||||
16, // 28: looprpc.SwapClient.LoopOutTerms:input_type -> looprpc.TermsRequest
|
||||
19, // 29: looprpc.SwapClient.LoopOutQuote:input_type -> looprpc.QuoteRequest
|
||||
16, // 30: looprpc.SwapClient.GetLoopInTerms:input_type -> looprpc.TermsRequest
|
||||
19, // 31: looprpc.SwapClient.GetLoopInQuote:input_type -> looprpc.QuoteRequest
|
||||
22, // 32: looprpc.SwapClient.Probe:input_type -> looprpc.ProbeRequest
|
||||
24, // 33: looprpc.SwapClient.GetLsatTokens:input_type -> looprpc.TokensRequest
|
||||
28, // 34: looprpc.SwapClient.GetInfo:input_type -> looprpc.GetInfoRequest
|
||||
30, // 35: looprpc.SwapClient.GetLiquidityParams:input_type -> looprpc.GetLiquidityParamsRequest
|
||||
33, // 36: looprpc.SwapClient.SetLiquidityParams:input_type -> looprpc.SetLiquidityParamsRequest
|
||||
35, // 37: looprpc.SwapClient.SuggestSwaps:input_type -> looprpc.SuggestSwapsRequest
|
||||
9, // 38: looprpc.SwapClient.LoopOut:output_type -> looprpc.SwapResponse
|
||||
9, // 39: looprpc.SwapClient.LoopIn:output_type -> looprpc.SwapResponse
|
||||
11, // 40: looprpc.SwapClient.Monitor:output_type -> looprpc.SwapStatus
|
||||
14, // 41: looprpc.SwapClient.ListSwaps:output_type -> looprpc.ListSwapsResponse
|
||||
11, // 42: looprpc.SwapClient.SwapInfo:output_type -> looprpc.SwapStatus
|
||||
39, // 43: looprpc.SwapClient.AbandonSwap:output_type -> looprpc.AbandonSwapResponse
|
||||
18, // 44: looprpc.SwapClient.LoopOutTerms:output_type -> looprpc.OutTermsResponse
|
||||
21, // 45: looprpc.SwapClient.LoopOutQuote:output_type -> looprpc.OutQuoteResponse
|
||||
17, // 46: looprpc.SwapClient.GetLoopInTerms:output_type -> looprpc.InTermsResponse
|
||||
20, // 47: looprpc.SwapClient.GetLoopInQuote:output_type -> looprpc.InQuoteResponse
|
||||
23, // 48: looprpc.SwapClient.Probe:output_type -> looprpc.ProbeResponse
|
||||
25, // 49: looprpc.SwapClient.GetLsatTokens:output_type -> looprpc.TokensResponse
|
||||
29, // 50: looprpc.SwapClient.GetInfo:output_type -> looprpc.GetInfoResponse
|
||||
31, // 51: looprpc.SwapClient.GetLiquidityParams:output_type -> looprpc.LiquidityParameters
|
||||
34, // 52: looprpc.SwapClient.SetLiquidityParams:output_type -> looprpc.SetLiquidityParamsResponse
|
||||
37, // 53: looprpc.SwapClient.SuggestSwaps:output_type -> looprpc.SuggestSwapsResponse
|
||||
38, // [38:54] is the sub-list for method output_type
|
||||
22, // [22:38] is the sub-list for method input_type
|
||||
22, // [22:22] is the sub-list for extension type_name
|
||||
22, // [22:22] is the sub-list for extension extendee
|
||||
0, // [0:22] is the sub-list for field type_name
|
||||
42, // 22: looprpc.ListReservationsResponse.reservations:type_name -> looprpc.ClientReservation
|
||||
7, // 23: looprpc.SwapClient.LoopOut:input_type -> looprpc.LoopOutRequest
|
||||
8, // 24: looprpc.SwapClient.LoopIn:input_type -> looprpc.LoopInRequest
|
||||
10, // 25: looprpc.SwapClient.Monitor:input_type -> looprpc.MonitorRequest
|
||||
12, // 26: looprpc.SwapClient.ListSwaps:input_type -> looprpc.ListSwapsRequest
|
||||
15, // 27: looprpc.SwapClient.SwapInfo:input_type -> looprpc.SwapInfoRequest
|
||||
38, // 28: looprpc.SwapClient.AbandonSwap:input_type -> looprpc.AbandonSwapRequest
|
||||
16, // 29: looprpc.SwapClient.LoopOutTerms:input_type -> looprpc.TermsRequest
|
||||
19, // 30: looprpc.SwapClient.LoopOutQuote:input_type -> looprpc.QuoteRequest
|
||||
16, // 31: looprpc.SwapClient.GetLoopInTerms:input_type -> looprpc.TermsRequest
|
||||
19, // 32: looprpc.SwapClient.GetLoopInQuote:input_type -> looprpc.QuoteRequest
|
||||
22, // 33: looprpc.SwapClient.Probe:input_type -> looprpc.ProbeRequest
|
||||
24, // 34: looprpc.SwapClient.GetLsatTokens:input_type -> looprpc.TokensRequest
|
||||
28, // 35: looprpc.SwapClient.GetInfo:input_type -> looprpc.GetInfoRequest
|
||||
30, // 36: looprpc.SwapClient.GetLiquidityParams:input_type -> looprpc.GetLiquidityParamsRequest
|
||||
33, // 37: looprpc.SwapClient.SetLiquidityParams:input_type -> looprpc.SetLiquidityParamsRequest
|
||||
35, // 38: looprpc.SwapClient.SuggestSwaps:input_type -> looprpc.SuggestSwapsRequest
|
||||
40, // 39: looprpc.SwapClient.ListReservations:input_type -> looprpc.ListReservationsRequest
|
||||
9, // 40: looprpc.SwapClient.LoopOut:output_type -> looprpc.SwapResponse
|
||||
9, // 41: looprpc.SwapClient.LoopIn:output_type -> looprpc.SwapResponse
|
||||
11, // 42: looprpc.SwapClient.Monitor:output_type -> looprpc.SwapStatus
|
||||
14, // 43: looprpc.SwapClient.ListSwaps:output_type -> looprpc.ListSwapsResponse
|
||||
11, // 44: looprpc.SwapClient.SwapInfo:output_type -> looprpc.SwapStatus
|
||||
39, // 45: looprpc.SwapClient.AbandonSwap:output_type -> looprpc.AbandonSwapResponse
|
||||
18, // 46: looprpc.SwapClient.LoopOutTerms:output_type -> looprpc.OutTermsResponse
|
||||
21, // 47: looprpc.SwapClient.LoopOutQuote:output_type -> looprpc.OutQuoteResponse
|
||||
17, // 48: looprpc.SwapClient.GetLoopInTerms:output_type -> looprpc.InTermsResponse
|
||||
20, // 49: looprpc.SwapClient.GetLoopInQuote:output_type -> looprpc.InQuoteResponse
|
||||
23, // 50: looprpc.SwapClient.Probe:output_type -> looprpc.ProbeResponse
|
||||
25, // 51: looprpc.SwapClient.GetLsatTokens:output_type -> looprpc.TokensResponse
|
||||
29, // 52: looprpc.SwapClient.GetInfo:output_type -> looprpc.GetInfoResponse
|
||||
31, // 53: looprpc.SwapClient.GetLiquidityParams:output_type -> looprpc.LiquidityParameters
|
||||
34, // 54: looprpc.SwapClient.SetLiquidityParams:output_type -> looprpc.SetLiquidityParamsResponse
|
||||
37, // 55: looprpc.SwapClient.SuggestSwaps:output_type -> looprpc.SuggestSwapsResponse
|
||||
41, // 56: looprpc.SwapClient.ListReservations:output_type -> looprpc.ListReservationsResponse
|
||||
40, // [40:57] is the sub-list for method output_type
|
||||
23, // [23:40] is the sub-list for method input_type
|
||||
23, // [23:23] is the sub-list for extension type_name
|
||||
23, // [23:23] is the sub-list for extension extendee
|
||||
0, // [0:23] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_client_proto_init() }
|
||||
|
|
@ -4464,6 +4680,42 @@ func file_client_proto_init() {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
file_client_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ListReservationsRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_client_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ListReservationsResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_client_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ClientReservation); 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{
|
||||
|
|
@ -4471,7 +4723,7 @@ func file_client_proto_init() {
|
|||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_client_proto_rawDesc,
|
||||
NumEnums: 7,
|
||||
NumMessages: 33,
|
||||
NumMessages: 36,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -109,6 +109,12 @@ service SwapClient {
|
|||
[EXPERIMENTAL]: endpoint is subject to change.
|
||||
*/
|
||||
rpc SuggestSwaps (SuggestSwapsRequest) returns (SuggestSwapsResponse);
|
||||
|
||||
/* loop: `listreservations`
|
||||
ListReservations returns a list of all reservations the server opened to us.
|
||||
*/
|
||||
rpc ListReservations (ListReservationsRequest)
|
||||
returns (ListReservationsResponse);
|
||||
}
|
||||
|
||||
message LoopOutRequest {
|
||||
|
|
@ -1242,4 +1248,42 @@ message AbandonSwapRequest {
|
|||
}
|
||||
|
||||
message AbandonSwapResponse {
|
||||
}
|
||||
|
||||
message ListReservationsRequest {
|
||||
}
|
||||
|
||||
message ListReservationsResponse {
|
||||
/*
|
||||
The list of all currently known reservations and their status.
|
||||
*/
|
||||
repeated ClientReservation reservations = 1;
|
||||
}
|
||||
|
||||
message ClientReservation {
|
||||
/*
|
||||
The reservation id that identifies this reservation.
|
||||
*/
|
||||
bytes reservation_id = 1;
|
||||
|
||||
/*
|
||||
The state the reservation is in.
|
||||
*/
|
||||
string state = 2;
|
||||
/*
|
||||
The amount that the reservation is for.
|
||||
*/
|
||||
uint64 amount = 3;
|
||||
/*
|
||||
The transaction id of the reservation.
|
||||
*/
|
||||
bytes tx_id = 4;
|
||||
/*
|
||||
The vout of the reservation.
|
||||
*/
|
||||
uint32 vout = 5;
|
||||
/*
|
||||
The expiry of the reservation.
|
||||
*/
|
||||
uint32 expiry = 6;
|
||||
}
|
||||
|
|
@ -465,7 +465,7 @@
|
|||
"parameters": [
|
||||
{
|
||||
"name": "list_swap_filter.swap_type",
|
||||
"description": "The type of the swap.\n\n - ANY: ANY indicates that no filter is applied.\n - LOOP_OUT: LOOP_OUT indicates an loop out swap (off-chain to on-chain)\n - LOOP_IN: LOOP_IN indicates a loop in swap (on-chain to off-chain)",
|
||||
"description": "The type of the swap.\n\n - ANY: ANY indicates that no filter is applied.\n - LOOP_OUT: LOOP_OUT indicates an loop out swap (off-chain to on-chain).\n - LOOP_IN: LOOP_IN indicates a loop in swap (on-chain to off-chain).",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "string",
|
||||
|
|
@ -549,7 +549,7 @@
|
|||
"LOOP_IN"
|
||||
],
|
||||
"default": "ANY",
|
||||
"title": "- ANY: ANY indicates that no filter is applied.\n - LOOP_OUT: LOOP_OUT indicates an loop out swap (off-chain to on-chain)\n - LOOP_IN: LOOP_IN indicates a loop in swap (on-chain to off-chain)"
|
||||
"description": " - ANY: ANY indicates that no filter is applied.\n - LOOP_OUT: LOOP_OUT indicates an loop out swap (off-chain to on-chain).\n - LOOP_IN: LOOP_IN indicates a loop in swap (on-chain to off-chain)."
|
||||
},
|
||||
"looprpcAbandonSwapResponse": {
|
||||
"type": "object"
|
||||
|
|
@ -585,6 +585,40 @@
|
|||
"default": "AUTO_REASON_UNKNOWN",
|
||||
"description": " - AUTO_REASON_BUDGET_NOT_STARTED: Budget not started indicates that we do not recommend any swaps because\nthe start time for our budget has not arrived yet.\n - AUTO_REASON_SWEEP_FEES: Sweep fees indicates that the estimated fees to sweep swaps are too high\nright now.\n - AUTO_REASON_BUDGET_ELAPSED: Budget elapsed indicates that the autoloop budget for the period has been\nelapsed.\n - AUTO_REASON_IN_FLIGHT: In flight indicates that the limit on in-flight automatically dispatched\nswaps has already been reached.\n - AUTO_REASON_SWAP_FEE: Swap fee indicates that the server fee for a specific swap is too high.\n - AUTO_REASON_MINER_FEE: Miner fee indicates that the miner fee for a specific swap is to high.\n - AUTO_REASON_PREPAY: Prepay indicates that the prepay fee for a specific swap is too high.\n - AUTO_REASON_FAILURE_BACKOFF: Failure backoff indicates that a swap has recently failed for this target,\nand the backoff period has not yet passed.\n - AUTO_REASON_LOOP_OUT: Loop out indicates that a loop out swap is currently utilizing the channel,\nso it is not eligible.\n - AUTO_REASON_LOOP_IN: Loop In indicates that a loop in swap is currently in flight for the peer,\nso it is not eligible.\n - AUTO_REASON_LIQUIDITY_OK: Liquidity ok indicates that a target meets the liquidity balance expressed\nin its rule, so no swap is needed.\n - AUTO_REASON_BUDGET_INSUFFICIENT: Budget insufficient indicates that we cannot perform a swap because we do\nnot have enough pending budget available. This differs from budget elapsed,\nbecause we still have some budget available, but we have allocated it to\nother swaps.\n - AUTO_REASON_FEE_INSUFFICIENT: Fee insufficient indicates that the fee estimate for a swap is higher than\nthe portion of total swap amount that we allow fees to consume."
|
||||
},
|
||||
"looprpcClientReservation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"reservation_id": {
|
||||
"type": "string",
|
||||
"format": "byte",
|
||||
"description": "The reservation id that identifies this reservation."
|
||||
},
|
||||
"state": {
|
||||
"type": "string",
|
||||
"description": "The state the reservation is in."
|
||||
},
|
||||
"amount": {
|
||||
"type": "string",
|
||||
"format": "uint64",
|
||||
"description": "The amount that the reservation is for."
|
||||
},
|
||||
"tx_id": {
|
||||
"type": "string",
|
||||
"format": "byte",
|
||||
"description": "The transaction id of the reservation."
|
||||
},
|
||||
"vout": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"description": "The vout of the reservation."
|
||||
},
|
||||
"expiry": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"description": "The expiry of the reservation."
|
||||
}
|
||||
}
|
||||
},
|
||||
"looprpcDisqualified": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
@ -889,6 +923,18 @@
|
|||
],
|
||||
"default": "UNKNOWN"
|
||||
},
|
||||
"looprpcListReservationsResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"reservations": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/looprpcClientReservation"
|
||||
},
|
||||
"description": "The list of all currently known reservations and their status."
|
||||
}
|
||||
}
|
||||
},
|
||||
"looprpcListSwapsFilter": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
|||
|
|
@ -83,6 +83,9 @@ type SwapClientClient interface {
|
|||
//Note that only loop out suggestions are currently supported.
|
||||
//[EXPERIMENTAL]: endpoint is subject to change.
|
||||
SuggestSwaps(ctx context.Context, in *SuggestSwapsRequest, opts ...grpc.CallOption) (*SuggestSwapsResponse, error)
|
||||
// loop: `listreservations`
|
||||
//ListReservations returns a list of all reservations the server opened to us.
|
||||
ListReservations(ctx context.Context, in *ListReservationsRequest, opts ...grpc.CallOption) (*ListReservationsResponse, error)
|
||||
}
|
||||
|
||||
type swapClientClient struct {
|
||||
|
|
@ -260,6 +263,15 @@ func (c *swapClientClient) SuggestSwaps(ctx context.Context, in *SuggestSwapsReq
|
|||
return out, nil
|
||||
}
|
||||
|
||||
func (c *swapClientClient) ListReservations(ctx context.Context, in *ListReservationsRequest, opts ...grpc.CallOption) (*ListReservationsResponse, error) {
|
||||
out := new(ListReservationsResponse)
|
||||
err := c.cc.Invoke(ctx, "/looprpc.SwapClient/ListReservations", 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
|
||||
|
|
@ -329,6 +341,9 @@ type SwapClientServer interface {
|
|||
//Note that only loop out suggestions are currently supported.
|
||||
//[EXPERIMENTAL]: endpoint is subject to change.
|
||||
SuggestSwaps(context.Context, *SuggestSwapsRequest) (*SuggestSwapsResponse, error)
|
||||
// loop: `listreservations`
|
||||
//ListReservations returns a list of all reservations the server opened to us.
|
||||
ListReservations(context.Context, *ListReservationsRequest) (*ListReservationsResponse, error)
|
||||
mustEmbedUnimplementedSwapClientServer()
|
||||
}
|
||||
|
||||
|
|
@ -384,6 +399,9 @@ func (UnimplementedSwapClientServer) SetLiquidityParams(context.Context, *SetLiq
|
|||
func (UnimplementedSwapClientServer) SuggestSwaps(context.Context, *SuggestSwapsRequest) (*SuggestSwapsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SuggestSwaps not implemented")
|
||||
}
|
||||
func (UnimplementedSwapClientServer) ListReservations(context.Context, *ListReservationsRequest) (*ListReservationsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListReservations not implemented")
|
||||
}
|
||||
func (UnimplementedSwapClientServer) mustEmbedUnimplementedSwapClientServer() {}
|
||||
|
||||
// UnsafeSwapClientServer may be embedded to opt out of forward compatibility for this service.
|
||||
|
|
@ -688,6 +706,24 @@ func _SwapClient_SuggestSwaps_Handler(srv interface{}, ctx context.Context, dec
|
|||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SwapClient_ListReservations_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ListReservationsRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SwapClientServer).ListReservations(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/looprpc.SwapClient/ListReservations",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SwapClientServer).ListReservations(ctx, req.(*ListReservationsRequest))
|
||||
}
|
||||
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)
|
||||
|
|
@ -755,6 +791,10 @@ var SwapClient_ServiceDesc = grpc.ServiceDesc{
|
|||
MethodName: "SuggestSwaps",
|
||||
Handler: _SwapClient_SuggestSwaps_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ListReservations",
|
||||
Handler: _SwapClient_ListReservations_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
|
|
|
|||
|
|
@ -437,4 +437,29 @@ func RegisterSwapClientJSONCallbacks(registry map[string]func(ctx context.Contex
|
|||
}
|
||||
callback(string(respBytes), nil)
|
||||
}
|
||||
|
||||
registry["looprpc.SwapClient.ListReservations"] = func(ctx context.Context,
|
||||
conn *grpc.ClientConn, reqJSON string, callback func(string, error)) {
|
||||
|
||||
req := &ListReservationsRequest{}
|
||||
err := marshaler.Unmarshal([]byte(reqJSON), req)
|
||||
if err != nil {
|
||||
callback("", err)
|
||||
return
|
||||
}
|
||||
|
||||
client := NewSwapClientClient(conn)
|
||||
resp, err := client.ListReservations(ctx, req)
|
||||
if err != nil {
|
||||
callback("", err)
|
||||
return
|
||||
}
|
||||
|
||||
respBytes, err := marshaler.Marshal(resp)
|
||||
if err != nil {
|
||||
callback("", err)
|
||||
return
|
||||
}
|
||||
callback(string(respBytes), nil)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
#!/usr/bin/env bash
|
||||
go run ./fsm/stateparser/stateparser.go --out ./fsm/example_fsm.md --fsm example
|
||||
go run ./fsm/stateparser/stateparser.go --out ./fsm/example_fsm.md --fsm example
|
||||
go run ./fsm/stateparser/stateparser.go --out ./reservation/reservation_fsm.md --fsm reservation
|
||||
468
swapserverrpc/reservation.pb.go
Normal file
468
swapserverrpc/reservation.pb.go
Normal file
|
|
@ -0,0 +1,468 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.30.0
|
||||
// protoc v3.6.1
|
||||
// source: reservation.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)
|
||||
)
|
||||
|
||||
// ReservationProtocolVersion is the version of the reservation protocol.
|
||||
type ReservationProtocolVersion int32
|
||||
|
||||
const (
|
||||
// RESERVATION_NONE is the default value and means that the reservation
|
||||
// protocol version is not set.
|
||||
ReservationProtocolVersion_RESERVATION_NONE ReservationProtocolVersion = 0
|
||||
// RESERVATION_SERVER_REQUEST is the first version of the reservation
|
||||
// protocol where the server notifies the client about a reservation.
|
||||
ReservationProtocolVersion_RESERVATION_SERVER_NOTIFY ReservationProtocolVersion = 1
|
||||
)
|
||||
|
||||
// Enum value maps for ReservationProtocolVersion.
|
||||
var (
|
||||
ReservationProtocolVersion_name = map[int32]string{
|
||||
0: "RESERVATION_NONE",
|
||||
1: "RESERVATION_SERVER_NOTIFY",
|
||||
}
|
||||
ReservationProtocolVersion_value = map[string]int32{
|
||||
"RESERVATION_NONE": 0,
|
||||
"RESERVATION_SERVER_NOTIFY": 1,
|
||||
}
|
||||
)
|
||||
|
||||
func (x ReservationProtocolVersion) Enum() *ReservationProtocolVersion {
|
||||
p := new(ReservationProtocolVersion)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x ReservationProtocolVersion) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (ReservationProtocolVersion) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_reservation_proto_enumTypes[0].Descriptor()
|
||||
}
|
||||
|
||||
func (ReservationProtocolVersion) Type() protoreflect.EnumType {
|
||||
return &file_reservation_proto_enumTypes[0]
|
||||
}
|
||||
|
||||
func (x ReservationProtocolVersion) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ReservationProtocolVersion.Descriptor instead.
|
||||
func (ReservationProtocolVersion) EnumDescriptor() ([]byte, []int) {
|
||||
return file_reservation_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
// ReservationNotificationRequest is an empty request sent from the client to
|
||||
// the server to open a stream to receive reservation notifications.
|
||||
type ReservationNotificationRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
}
|
||||
|
||||
func (x *ReservationNotificationRequest) Reset() {
|
||||
*x = ReservationNotificationRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_reservation_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ReservationNotificationRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ReservationNotificationRequest) ProtoMessage() {}
|
||||
|
||||
func (x *ReservationNotificationRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_reservation_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 ReservationNotificationRequest.ProtoReflect.Descriptor instead.
|
||||
func (*ReservationNotificationRequest) Descriptor() ([]byte, []int) {
|
||||
return file_reservation_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
// ServerReservationNotification is a notification sent from the server to the
|
||||
// client if the server wants to open a reservation.
|
||||
type ServerReservationNotification struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// reservation_id is the id of the reservation.
|
||||
ReservationId []byte `protobuf:"bytes,1,opt,name=reservation_id,json=reservationId,proto3" json:"reservation_id,omitempty"`
|
||||
// value is the value of the reservation in satoshis.
|
||||
Value uint64 `protobuf:"varint,2,opt,name=value,proto3" json:"value,omitempty"`
|
||||
// server_key is the public key of the server.
|
||||
ServerKey []byte `protobuf:"bytes,3,opt,name=server_key,json=serverKey,proto3" json:"server_key,omitempty"`
|
||||
// expiry is the absolute expiry of the reservation.
|
||||
Expiry uint32 `protobuf:"varint,4,opt,name=expiry,proto3" json:"expiry,omitempty"`
|
||||
// protocol_version is the version of the reservation protocol.
|
||||
ProtocolVersion ReservationProtocolVersion `protobuf:"varint,5,opt,name=protocol_version,json=protocolVersion,proto3,enum=looprpc.ReservationProtocolVersion" json:"protocol_version,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ServerReservationNotification) Reset() {
|
||||
*x = ServerReservationNotification{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_reservation_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ServerReservationNotification) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ServerReservationNotification) ProtoMessage() {}
|
||||
|
||||
func (x *ServerReservationNotification) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_reservation_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 ServerReservationNotification.ProtoReflect.Descriptor instead.
|
||||
func (*ServerReservationNotification) Descriptor() ([]byte, []int) {
|
||||
return file_reservation_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *ServerReservationNotification) GetReservationId() []byte {
|
||||
if x != nil {
|
||||
return x.ReservationId
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ServerReservationNotification) GetValue() uint64 {
|
||||
if x != nil {
|
||||
return x.Value
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ServerReservationNotification) GetServerKey() []byte {
|
||||
if x != nil {
|
||||
return x.ServerKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ServerReservationNotification) GetExpiry() uint32 {
|
||||
if x != nil {
|
||||
return x.Expiry
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ServerReservationNotification) GetProtocolVersion() ReservationProtocolVersion {
|
||||
if x != nil {
|
||||
return x.ProtocolVersion
|
||||
}
|
||||
return ReservationProtocolVersion_RESERVATION_NONE
|
||||
}
|
||||
|
||||
// ServerOpenReservationRequest is a request sent from the client to the server
|
||||
// to confirm a reservation opening.
|
||||
type ServerOpenReservationRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// reservation_id is the id of the reservation.
|
||||
ReservationId []byte `protobuf:"bytes,1,opt,name=reservation_id,json=reservationId,proto3" json:"reservation_id,omitempty"`
|
||||
// client_key is the public key of the client.
|
||||
ClientKey []byte `protobuf:"bytes,2,opt,name=client_key,json=clientKey,proto3" json:"client_key,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ServerOpenReservationRequest) Reset() {
|
||||
*x = ServerOpenReservationRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_reservation_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ServerOpenReservationRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ServerOpenReservationRequest) ProtoMessage() {}
|
||||
|
||||
func (x *ServerOpenReservationRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_reservation_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 ServerOpenReservationRequest.ProtoReflect.Descriptor instead.
|
||||
func (*ServerOpenReservationRequest) Descriptor() ([]byte, []int) {
|
||||
return file_reservation_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *ServerOpenReservationRequest) GetReservationId() []byte {
|
||||
if x != nil {
|
||||
return x.ReservationId
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ServerOpenReservationRequest) GetClientKey() []byte {
|
||||
if x != nil {
|
||||
return x.ClientKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ServerOpenReservationResponse is a response sent from the server to the
|
||||
// client to confirm a reservation opening.
|
||||
type ServerOpenReservationResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
}
|
||||
|
||||
func (x *ServerOpenReservationResponse) Reset() {
|
||||
*x = ServerOpenReservationResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_reservation_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ServerOpenReservationResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ServerOpenReservationResponse) ProtoMessage() {}
|
||||
|
||||
func (x *ServerOpenReservationResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_reservation_proto_msgTypes[3]
|
||||
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 ServerOpenReservationResponse.ProtoReflect.Descriptor instead.
|
||||
func (*ServerOpenReservationResponse) Descriptor() ([]byte, []int) {
|
||||
return file_reservation_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
var File_reservation_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_reservation_proto_rawDesc = []byte{
|
||||
0x0a, 0x11, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x12, 0x07, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x22, 0x20, 0x0a, 0x1e,
|
||||
0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x74, 0x69, 0x66,
|
||||
0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xe3,
|
||||
0x01, 0x0a, 0x1d, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f,
|
||||
0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1d, 0x0a,
|
||||
0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28,
|
||||
0x0c, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06,
|
||||
0x65, 0x78, 0x70, 0x69, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x65, 0x78,
|
||||
0x70, 0x69, 0x72, 0x79, 0x12, 0x4e, 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c,
|
||||
0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23,
|
||||
0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x56, 0x65, 0x72,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x22, 0x64, 0x0a, 0x1c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4f, 0x70,
|
||||
0x65, 0x6e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x72, 0x65,
|
||||
0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63,
|
||||
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52,
|
||||
0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x22, 0x1f, 0x0a, 0x1d, 0x53, 0x65,
|
||||
0x72, 0x76, 0x65, 0x72, 0x4f, 0x70, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x51, 0x0a, 0x1a, 0x52,
|
||||
0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63,
|
||||
0x6f, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x10, 0x52, 0x45, 0x53,
|
||||
0x45, 0x52, 0x56, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12,
|
||||
0x1d, 0x0a, 0x19, 0x52, 0x45, 0x53, 0x45, 0x52, 0x56, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53,
|
||||
0x45, 0x52, 0x56, 0x45, 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x49, 0x46, 0x59, 0x10, 0x01, 0x32, 0xea,
|
||||
0x01, 0x0a, 0x12, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65,
|
||||
0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x72, 0x0a, 0x1d, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x27, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63,
|
||||
0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x74, 0x69,
|
||||
0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||
0x26, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
|
||||
0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x74, 0x69, 0x66,
|
||||
0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x30, 0x01, 0x12, 0x60, 0x0a, 0x0f, 0x4f, 0x70, 0x65,
|
||||
0x6e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x2e, 0x6c,
|
||||
0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4f, 0x70, 0x65,
|
||||
0x6e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x6c, 0x6f, 0x6f, 0x70, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65,
|
||||
0x72, 0x76, 0x65, 0x72, 0x4f, 0x70, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 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_reservation_proto_rawDescOnce sync.Once
|
||||
file_reservation_proto_rawDescData = file_reservation_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_reservation_proto_rawDescGZIP() []byte {
|
||||
file_reservation_proto_rawDescOnce.Do(func() {
|
||||
file_reservation_proto_rawDescData = protoimpl.X.CompressGZIP(file_reservation_proto_rawDescData)
|
||||
})
|
||||
return file_reservation_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_reservation_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||
var file_reservation_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
|
||||
var file_reservation_proto_goTypes = []interface{}{
|
||||
(ReservationProtocolVersion)(0), // 0: looprpc.ReservationProtocolVersion
|
||||
(*ReservationNotificationRequest)(nil), // 1: looprpc.ReservationNotificationRequest
|
||||
(*ServerReservationNotification)(nil), // 2: looprpc.ServerReservationNotification
|
||||
(*ServerOpenReservationRequest)(nil), // 3: looprpc.ServerOpenReservationRequest
|
||||
(*ServerOpenReservationResponse)(nil), // 4: looprpc.ServerOpenReservationResponse
|
||||
}
|
||||
var file_reservation_proto_depIdxs = []int32{
|
||||
0, // 0: looprpc.ServerReservationNotification.protocol_version:type_name -> looprpc.ReservationProtocolVersion
|
||||
1, // 1: looprpc.ReservationService.ReservationNotificationStream:input_type -> looprpc.ReservationNotificationRequest
|
||||
3, // 2: looprpc.ReservationService.OpenReservation:input_type -> looprpc.ServerOpenReservationRequest
|
||||
2, // 3: looprpc.ReservationService.ReservationNotificationStream:output_type -> looprpc.ServerReservationNotification
|
||||
4, // 4: looprpc.ReservationService.OpenReservation:output_type -> looprpc.ServerOpenReservationResponse
|
||||
3, // [3:5] is the sub-list for method output_type
|
||||
1, // [1:3] 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_reservation_proto_init() }
|
||||
func file_reservation_proto_init() {
|
||||
if File_reservation_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_reservation_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ReservationNotificationRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_reservation_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ServerReservationNotification); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_reservation_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ServerOpenReservationRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_reservation_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ServerOpenReservationResponse); 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_reservation_proto_rawDesc,
|
||||
NumEnums: 1,
|
||||
NumMessages: 4,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_reservation_proto_goTypes,
|
||||
DependencyIndexes: file_reservation_proto_depIdxs,
|
||||
EnumInfos: file_reservation_proto_enumTypes,
|
||||
MessageInfos: file_reservation_proto_msgTypes,
|
||||
}.Build()
|
||||
File_reservation_proto = out.File
|
||||
file_reservation_proto_rawDesc = nil
|
||||
file_reservation_proto_goTypes = nil
|
||||
file_reservation_proto_depIdxs = nil
|
||||
}
|
||||
70
swapserverrpc/reservation.proto
Normal file
70
swapserverrpc/reservation.proto
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
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 ReservationService {
|
||||
// ReservationNotificationStream is a server side stream that sends
|
||||
// notifications if the server wants to open a reservation to the client.
|
||||
rpc ReservationNotificationStream (ReservationNotificationRequest)
|
||||
returns (stream ServerReservationNotification);
|
||||
|
||||
// OpenReservation requests a new reservation UTXO from the server.
|
||||
rpc OpenReservation (ServerOpenReservationRequest)
|
||||
returns (ServerOpenReservationResponse);
|
||||
}
|
||||
|
||||
// ReservationNotificationRequest is an empty request sent from the client to
|
||||
// the server to open a stream to receive reservation notifications.
|
||||
message ReservationNotificationRequest {
|
||||
}
|
||||
|
||||
// ServerReservationNotification is a notification sent from the server to the
|
||||
// client if the server wants to open a reservation.
|
||||
message ServerReservationNotification {
|
||||
// reservation_id is the id of the reservation.
|
||||
bytes reservation_id = 1;
|
||||
|
||||
// value is the value of the reservation in satoshis.
|
||||
uint64 value = 2;
|
||||
|
||||
// server_key is the public key of the server.
|
||||
bytes server_key = 3;
|
||||
|
||||
// expiry is the absolute expiry of the reservation.
|
||||
uint32 expiry = 4;
|
||||
|
||||
// protocol_version is the version of the reservation protocol.
|
||||
ReservationProtocolVersion protocol_version = 5;
|
||||
}
|
||||
|
||||
// ServerOpenReservationRequest is a request sent from the client to the server
|
||||
// to confirm a reservation opening.
|
||||
message ServerOpenReservationRequest {
|
||||
// reservation_id is the id of the reservation.
|
||||
bytes reservation_id = 1;
|
||||
|
||||
// client_key is the public key of the client.
|
||||
bytes client_key = 2;
|
||||
}
|
||||
|
||||
// ServerOpenReservationResponse is a response sent from the server to the
|
||||
// client to confirm a reservation opening.
|
||||
message ServerOpenReservationResponse {
|
||||
}
|
||||
|
||||
// ReservationProtocolVersion is the version of the reservation protocol.
|
||||
enum ReservationProtocolVersion {
|
||||
// RESERVATION_NONE is the default value and means that the reservation
|
||||
// protocol version is not set.
|
||||
RESERVATION_NONE = 0;
|
||||
|
||||
// RESERVATION_SERVER_REQUEST is the first version of the reservation
|
||||
// protocol where the server notifies the client about a reservation.
|
||||
RESERVATION_SERVER_NOTIFY = 1;
|
||||
};
|
||||
171
swapserverrpc/reservation_grpc.pb.go
Normal file
171
swapserverrpc/reservation_grpc.pb.go
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
// 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
|
||||
|
||||
// ReservationServiceClient is the client API for ReservationService 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 ReservationServiceClient interface {
|
||||
// ReservationNotificationStream is a server side stream that sends
|
||||
// notifications if the server wants to open a reservation to the client.
|
||||
ReservationNotificationStream(ctx context.Context, in *ReservationNotificationRequest, opts ...grpc.CallOption) (ReservationService_ReservationNotificationStreamClient, error)
|
||||
// OpenReservation requests a new reservation UTXO from the server.
|
||||
OpenReservation(ctx context.Context, in *ServerOpenReservationRequest, opts ...grpc.CallOption) (*ServerOpenReservationResponse, error)
|
||||
}
|
||||
|
||||
type reservationServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewReservationServiceClient(cc grpc.ClientConnInterface) ReservationServiceClient {
|
||||
return &reservationServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *reservationServiceClient) ReservationNotificationStream(ctx context.Context, in *ReservationNotificationRequest, opts ...grpc.CallOption) (ReservationService_ReservationNotificationStreamClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &ReservationService_ServiceDesc.Streams[0], "/looprpc.ReservationService/ReservationNotificationStream", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &reservationServiceReservationNotificationStreamClient{stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type ReservationService_ReservationNotificationStreamClient interface {
|
||||
Recv() (*ServerReservationNotification, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type reservationServiceReservationNotificationStreamClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *reservationServiceReservationNotificationStreamClient) Recv() (*ServerReservationNotification, error) {
|
||||
m := new(ServerReservationNotification)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (c *reservationServiceClient) OpenReservation(ctx context.Context, in *ServerOpenReservationRequest, opts ...grpc.CallOption) (*ServerOpenReservationResponse, error) {
|
||||
out := new(ServerOpenReservationResponse)
|
||||
err := c.cc.Invoke(ctx, "/looprpc.ReservationService/OpenReservation", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// ReservationServiceServer is the server API for ReservationService service.
|
||||
// All implementations must embed UnimplementedReservationServiceServer
|
||||
// for forward compatibility
|
||||
type ReservationServiceServer interface {
|
||||
// ReservationNotificationStream is a server side stream that sends
|
||||
// notifications if the server wants to open a reservation to the client.
|
||||
ReservationNotificationStream(*ReservationNotificationRequest, ReservationService_ReservationNotificationStreamServer) error
|
||||
// OpenReservation requests a new reservation UTXO from the server.
|
||||
OpenReservation(context.Context, *ServerOpenReservationRequest) (*ServerOpenReservationResponse, error)
|
||||
mustEmbedUnimplementedReservationServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedReservationServiceServer must be embedded to have forward compatible implementations.
|
||||
type UnimplementedReservationServiceServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedReservationServiceServer) ReservationNotificationStream(*ReservationNotificationRequest, ReservationService_ReservationNotificationStreamServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method ReservationNotificationStream not implemented")
|
||||
}
|
||||
func (UnimplementedReservationServiceServer) OpenReservation(context.Context, *ServerOpenReservationRequest) (*ServerOpenReservationResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method OpenReservation not implemented")
|
||||
}
|
||||
func (UnimplementedReservationServiceServer) mustEmbedUnimplementedReservationServiceServer() {}
|
||||
|
||||
// UnsafeReservationServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to ReservationServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeReservationServiceServer interface {
|
||||
mustEmbedUnimplementedReservationServiceServer()
|
||||
}
|
||||
|
||||
func RegisterReservationServiceServer(s grpc.ServiceRegistrar, srv ReservationServiceServer) {
|
||||
s.RegisterService(&ReservationService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _ReservationService_ReservationNotificationStream_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(ReservationNotificationRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(ReservationServiceServer).ReservationNotificationStream(m, &reservationServiceReservationNotificationStreamServer{stream})
|
||||
}
|
||||
|
||||
type ReservationService_ReservationNotificationStreamServer interface {
|
||||
Send(*ServerReservationNotification) error
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type reservationServiceReservationNotificationStreamServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *reservationServiceReservationNotificationStreamServer) Send(m *ServerReservationNotification) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func _ReservationService_OpenReservation_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ServerOpenReservationRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ReservationServiceServer).OpenReservation(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/looprpc.ReservationService/OpenReservation",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ReservationServiceServer).OpenReservation(ctx, req.(*ServerOpenReservationRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// ReservationService_ServiceDesc is the grpc.ServiceDesc for ReservationService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var ReservationService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "looprpc.ReservationService",
|
||||
HandlerType: (*ReservationServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "OpenReservation",
|
||||
Handler: _ReservationService_OpenReservation_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "ReservationNotificationStream",
|
||||
Handler: _ReservationService_ReservationNotificationStream_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "reservation.proto",
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue