From 2e48ead6d64bbb61b36d4e440bf315591c3c1550 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Thu, 28 Mar 2019 13:29:21 +0100 Subject: [PATCH] loopd: loop in from external address Allow user to specify that htlc will be published by an external source. In that case no internal htlc tx will be published. To facilitate sending to the htlc address, the swap initiation response is extended with that address. --- client.go | 28 ++++-- client_test.go | 6 +- cmd/loop/loopin.go | 12 ++- cmd/loop/loopout.go | 5 +- cmd/loopd/swapclient_server.go | 11 ++- interface.go | 4 + loopdb/loopin.go | 12 +++ loopdb/store_test.go | 1 + loopin.go | 24 +++-- looprpc/client.pb.go | 172 +++++++++++++++++++-------------- looprpc/client.proto | 11 +++ looprpc/client.swagger.json | 4 + 12 files changed, 191 insertions(+), 99 deletions(-) diff --git a/client.go b/client.go index 28af7a0..0fa3b6a 100644 --- a/client.go +++ b/client.go @@ -248,7 +248,7 @@ func (s *Client) resumeSwaps(ctx context.Context, // // The return value is a hash that uniquely identifies the new swap. func (s *Client) LoopOut(globalCtx context.Context, - request *OutRequest) (*lntypes.Hash, error) { + request *OutRequest) (*lntypes.Hash, btcutil.Address, error) { logger.Infof("LoopOut %v to %v (channel: %v)", request.Amount, request.DestAddr, @@ -256,7 +256,7 @@ func (s *Client) LoopOut(globalCtx context.Context, ) if err := s.waitForInitialized(globalCtx); err != nil { - return nil, err + return nil, nil, err } // Create a new swap object for this swap. @@ -270,15 +270,21 @@ func (s *Client) LoopOut(globalCtx context.Context, globalCtx, swapCfg, initiationHeight, request, ) if err != nil { - return nil, err + return nil, nil, err } // Post swap to the main loop. s.executor.initiateSwap(globalCtx, swap) + // Retrieve htlc address. + htlcAddress, err := swap.htlc.Address(s.lndServices.ChainParams) + if err != nil { + return nil, nil, err + } + // Return hash so that the caller can identify this swap in the updates // stream. - return &swap.hash, nil + return &swap.hash, htlcAddress, nil } // LoopOutQuote takes a LoopOut amount and returns a break down of estimated @@ -347,7 +353,7 @@ func (s *Client) waitForInitialized(ctx context.Context) error { // LoopIn initiates a loop in swap. func (s *Client) LoopIn(globalCtx context.Context, - request *LoopInRequest) (*lntypes.Hash, error) { + request *LoopInRequest) (*lntypes.Hash, btcutil.Address, error) { logger.Infof("Loop in %v (channel: %v)", request.Amount, @@ -355,7 +361,7 @@ func (s *Client) LoopIn(globalCtx context.Context, ) if err := s.waitForInitialized(globalCtx); err != nil { - return nil, err + return nil, nil, err } // Create a new swap object for this swap. @@ -369,15 +375,21 @@ func (s *Client) LoopIn(globalCtx context.Context, globalCtx, &swapCfg, initiationHeight, request, ) if err != nil { - return nil, err + return nil, nil, err } // Post swap to the main loop. s.executor.initiateSwap(globalCtx, swap) + // Retrieve htlc address. + htlcAddress, err := swap.htlc.Address(s.lndServices.ChainParams) + if err != nil { + return nil, nil, err + } + // Return hash so that the caller can identify this swap in the updates // stream. - return &swap.hash, nil + return &swap.hash, htlcAddress, nil } // LoopInQuote takes an amount and returns a break down of estimated diff --git a/client_test.go b/client_test.go index 5e8f08d..09b921a 100644 --- a/client_test.go +++ b/client_test.go @@ -43,7 +43,7 @@ func TestSuccess(t *testing.T) { // Initiate uncharge. - hash, err := ctx.swapClient.LoopOut(context.Background(), testRequest) + hash, _, err := ctx.swapClient.LoopOut(context.Background(), testRequest) if err != nil { t.Fatal(err) } @@ -70,7 +70,7 @@ func TestFailOffchain(t *testing.T) { ctx := createClientTestContext(t, nil) - _, err := ctx.swapClient.LoopOut(context.Background(), testRequest) + _, _, err := ctx.swapClient.LoopOut(context.Background(), testRequest) if err != nil { t.Fatal(err) } @@ -108,7 +108,7 @@ func TestFailWrongAmount(t *testing.T) { // Modify mock for this subtest. modifier(ctx.serverMock) - _, err := ctx.swapClient.LoopOut( + _, _, err := ctx.swapClient.LoopOut( context.Background(), testRequest, ) if err != expectedErr { diff --git a/cmd/loop/loopin.go b/cmd/loop/loopin.go index 68de775..050285e 100644 --- a/cmd/loop/loopin.go +++ b/cmd/loop/loopin.go @@ -24,6 +24,10 @@ var loopInCommand = cli.Command{ Name: "amt", Usage: "the amount in satoshis to loop out", }, + cli.BoolFlag{ + Name: "external", + Usage: "expect htlc to be published externally", + }, }, Action: loopIn, } @@ -81,13 +85,17 @@ func loopIn(ctx *cli.Context) error { MaxMinerFee: int64(limits.maxMinerFee), MaxSwapFee: int64(limits.maxSwapFee), LoopInChannel: loopInChannel, + ExternalHtlc: ctx.Bool("external"), }) if err != nil { return err } - fmt.Printf("Swap initiated with id: %v\n", resp.Id[:8]) - fmt.Printf("Run swapcli without a command to monitor progress.\n") + fmt.Printf("Swap initiated\n") + fmt.Printf("ID: %v\n", resp.Id) + fmt.Printf("HTLC address: %v\n", resp.HtlcAddress) + fmt.Println() + fmt.Printf("Run `loop monitor` to monitor progress.\n") return nil } diff --git a/cmd/loop/loopout.go b/cmd/loop/loopout.go index 328f90f..4b13794 100644 --- a/cmd/loop/loopout.go +++ b/cmd/loop/loopout.go @@ -107,7 +107,10 @@ func loopOut(ctx *cli.Context) error { return err } - fmt.Printf("Swap initiated with id: %v\n", resp.Id[:8]) + fmt.Printf("Swap initiated\n") + fmt.Printf("ID: %v\n", resp.Id) + fmt.Printf("HTLC address: %v\n", resp.HtlcAddress) + fmt.Println() fmt.Printf("Run `loop monitor` to monitor progress.\n") return nil diff --git a/cmd/loopd/swapclient_server.go b/cmd/loopd/swapclient_server.go index 391f346..2668dc0 100644 --- a/cmd/loopd/swapclient_server.go +++ b/cmd/loopd/swapclient_server.go @@ -72,14 +72,15 @@ func (s *swapClientServer) LoopOut(ctx context.Context, if in.LoopOutChannel != 0 { req.LoopOutChannel = &in.LoopOutChannel } - hash, err := s.impl.LoopOut(ctx, req) + hash, htlc, err := s.impl.LoopOut(ctx, req) if err != nil { logger.Errorf("LoopOut: %v", err) return nil, err } return &looprpc.SwapResponse{ - Id: hash.String(), + Id: hash.String(), + HtlcAddress: htlc.String(), }, nil } @@ -333,17 +334,19 @@ func (s *swapClientServer) LoopIn(ctx context.Context, MaxMinerFee: btcutil.Amount(in.MaxMinerFee), MaxSwapFee: btcutil.Amount(in.MaxSwapFee), HtlcConfTarget: defaultConfTarget, + ExternalHtlc: in.ExternalHtlc, } if in.LoopInChannel != 0 { req.LoopInChannel = &in.LoopInChannel } - hash, err := s.impl.LoopIn(ctx, req) + hash, htlc, err := s.impl.LoopIn(ctx, req) if err != nil { logger.Errorf("Loop in: %v", err) return nil, err } return &looprpc.SwapResponse{ - Id: hash.String(), + Id: hash.String(), + HtlcAddress: htlc.String(), }, nil } diff --git a/interface.go b/interface.go index d4010f2..ee0bb7a 100644 --- a/interface.go +++ b/interface.go @@ -186,6 +186,10 @@ type LoopInRequest struct { // LoopInChannel optionally specifies the short channel id of the // channel to charge. LoopInChannel *uint64 + + // ExternalHtlc specifies whether the htlc is published by an external + // source. + ExternalHtlc bool } // LoopInTerms are the server terms on which it executes charge swaps. diff --git a/loopdb/loopin.go b/loopdb/loopin.go index 13d45d6..efe0bbe 100644 --- a/loopdb/loopin.go +++ b/loopdb/loopin.go @@ -19,6 +19,10 @@ type LoopInContract struct { // LoopInChannel is the channel to charge. If zero, any channel may // be used. LoopInChannel *uint64 + + // ExternalHtlc specifies whether the htlc is published by an external + // source. + ExternalHtlc bool } // LoopIn is a combination of the contract and the updates. @@ -100,6 +104,10 @@ func serializeLoopInContract(swap *LoopInContract) ( return nil, err } + if err := binary.Write(&b, byteOrder, swap.ExternalHtlc); err != nil { + return nil, err + } + return b.Bytes(), nil } @@ -164,5 +172,9 @@ func deserializeLoopInContract(value []byte) (*LoopInContract, error) { contract.LoopInChannel = &loopInChannel } + if err := binary.Read(r, byteOrder, &contract.ExternalHtlc); err != nil { + return nil, err + } + return &contract, nil } diff --git a/loopdb/store_test.go b/loopdb/store_test.go index 4d6bbe2..f2a0869 100644 --- a/loopdb/store_test.go +++ b/loopdb/store_test.go @@ -207,6 +207,7 @@ func TestLoopInStore(t *testing.T) { }, HtlcConfTarget: 2, LoopInChannel: &loopInChannel, + ExternalHtlc: true, } // checkSwap is a test helper function that'll assert the state of a diff --git a/loopin.go b/loopin.go index 25af146..b8a8959 100644 --- a/loopin.go +++ b/loopin.go @@ -136,6 +136,7 @@ func newLoopInSwap(globalCtx context.Context, cfg *swapConfig, contract := loopdb.LoopInContract{ HtlcConfTarget: request.HtlcConfTarget, LoopInChannel: request.LoopInChannel, + ExternalHtlc: request.ExternalHtlc, SwapContract: loopdb.SwapContract{ InitiationHeight: currentHeight, InitiationTime: initiationTime, @@ -277,12 +278,23 @@ func (s *loopInSwap) executeSwap(globalCtx context.Context) error { // on-chain htlc. Only do this is we haven't already done so in a // previous run. if s.state == loopdb.StateInitiated { - published, err := s.publishOnChainHtlc(globalCtx) - if err != nil { - return err - } - if !published { - return nil + if s.ExternalHtlc { + // If an external htlc was indicated, we can move to the + // HtlcPublished state directly and wait for + // confirmation. + s.state = loopdb.StateHtlcPublished + err = s.persistState(globalCtx) + if err != nil { + return err + } + } else { + published, err := s.publishOnChainHtlc(globalCtx) + if err != nil { + return err + } + if !published { + return nil + } } } diff --git a/looprpc/client.pb.go b/looprpc/client.pb.go index c2bcd06..5988c6d 100644 --- a/looprpc/client.pb.go +++ b/looprpc/client.pb.go @@ -46,7 +46,7 @@ func (x SwapType) String() string { return proto.EnumName(SwapType_name, int32(x)) } func (SwapType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_client_e75b35e98d3b3b20, []int{0} + return fileDescriptor_client_3d2c5dccaa4d32eb, []int{0} } type SwapState int32 @@ -97,7 +97,7 @@ func (x SwapState) String() string { return proto.EnumName(SwapState_name, int32(x)) } func (SwapState) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_client_e75b35e98d3b3b20, []int{1} + return fileDescriptor_client_3d2c5dccaa4d32eb, []int{1} } type LoopOutRequest struct { @@ -155,7 +155,7 @@ func (m *LoopOutRequest) Reset() { *m = LoopOutRequest{} } func (m *LoopOutRequest) String() string { return proto.CompactTextString(m) } func (*LoopOutRequest) ProtoMessage() {} func (*LoopOutRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_client_e75b35e98d3b3b20, []int{0} + return fileDescriptor_client_3d2c5dccaa4d32eb, []int{0} } func (m *LoopOutRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_LoopOutRequest.Unmarshal(m, b) @@ -240,7 +240,7 @@ type LoopInRequest struct { // Maximum we are willing to pay the server for the swap. This value is not // disclosed in the swap initiation call, but if the server asks for a // higher fee, we abort the swap. Typically this value is taken from the - // response of the GetQuote call. It includes the prepay amount. + // response of the GetQuote call. MaxSwapFee int64 `protobuf:"varint,2,opt,name=max_swap_fee,json=maxSwapFee,proto3" json:"max_swap_fee,omitempty"` // * // Maximum in on-chain fees that we are willing to spent. If we want to @@ -252,7 +252,11 @@ type LoopInRequest struct { // * // The channel to loop in. If zero, the channel to loop in is selected based // on the lowest routing fee for the swap payment from the server. - LoopInChannel uint64 `protobuf:"varint,4,opt,name=loop_in_channel,json=loopInChannel,proto3" json:"loop_in_channel,omitempty"` + LoopInChannel uint64 `protobuf:"varint,4,opt,name=loop_in_channel,json=loopInChannel,proto3" json:"loop_in_channel,omitempty"` + // * + // If external_htlc is true, we expect the htlc to be published by an external + // actor. + ExternalHtlc bool `protobuf:"varint,5,opt,name=external_htlc,json=externalHtlc,proto3" json:"external_htlc,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -262,7 +266,7 @@ func (m *LoopInRequest) Reset() { *m = LoopInRequest{} } func (m *LoopInRequest) String() string { return proto.CompactTextString(m) } func (*LoopInRequest) ProtoMessage() {} func (*LoopInRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_client_e75b35e98d3b3b20, []int{1} + return fileDescriptor_client_3d2c5dccaa4d32eb, []int{1} } func (m *LoopInRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_LoopInRequest.Unmarshal(m, b) @@ -310,11 +314,21 @@ func (m *LoopInRequest) GetLoopInChannel() uint64 { return 0 } +func (m *LoopInRequest) GetExternalHtlc() bool { + if m != nil { + return m.ExternalHtlc + } + return false +} + type SwapResponse struct { // * // Swap identifier to track status in the update stream that is returned from // the Start() call. Currently this is the hash that locks the htlcs. - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // * + // The address of the on-chain htlc. + HtlcAddress string `protobuf:"bytes,2,opt,name=htlc_address,json=htlcAddress,proto3" json:"htlc_address,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -324,7 +338,7 @@ func (m *SwapResponse) Reset() { *m = SwapResponse{} } func (m *SwapResponse) String() string { return proto.CompactTextString(m) } func (*SwapResponse) ProtoMessage() {} func (*SwapResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_client_e75b35e98d3b3b20, []int{2} + return fileDescriptor_client_3d2c5dccaa4d32eb, []int{2} } func (m *SwapResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SwapResponse.Unmarshal(m, b) @@ -351,6 +365,13 @@ func (m *SwapResponse) GetId() string { return "" } +func (m *SwapResponse) GetHtlcAddress() string { + if m != nil { + return m.HtlcAddress + } + return "" +} + type MonitorRequest struct { XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -361,7 +382,7 @@ func (m *MonitorRequest) Reset() { *m = MonitorRequest{} } func (m *MonitorRequest) String() string { return proto.CompactTextString(m) } func (*MonitorRequest) ProtoMessage() {} func (*MonitorRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_client_e75b35e98d3b3b20, []int{3} + return fileDescriptor_client_3d2c5dccaa4d32eb, []int{3} } func (m *MonitorRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_MonitorRequest.Unmarshal(m, b) @@ -414,7 +435,7 @@ func (m *SwapStatus) Reset() { *m = SwapStatus{} } func (m *SwapStatus) String() string { return proto.CompactTextString(m) } func (*SwapStatus) ProtoMessage() {} func (*SwapStatus) Descriptor() ([]byte, []int) { - return fileDescriptor_client_e75b35e98d3b3b20, []int{4} + return fileDescriptor_client_3d2c5dccaa4d32eb, []int{4} } func (m *SwapStatus) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_SwapStatus.Unmarshal(m, b) @@ -493,7 +514,7 @@ func (m *TermsRequest) Reset() { *m = TermsRequest{} } func (m *TermsRequest) String() string { return proto.CompactTextString(m) } func (*TermsRequest) ProtoMessage() {} func (*TermsRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_client_e75b35e98d3b3b20, []int{5} + return fileDescriptor_client_3d2c5dccaa4d32eb, []int{5} } func (m *TermsRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_TermsRequest.Unmarshal(m, b) @@ -545,7 +566,7 @@ func (m *TermsResponse) Reset() { *m = TermsResponse{} } func (m *TermsResponse) String() string { return proto.CompactTextString(m) } func (*TermsResponse) ProtoMessage() {} func (*TermsResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_client_e75b35e98d3b3b20, []int{6} + return fileDescriptor_client_3d2c5dccaa4d32eb, []int{6} } func (m *TermsResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_TermsResponse.Unmarshal(m, b) @@ -627,7 +648,7 @@ func (m *QuoteRequest) Reset() { *m = QuoteRequest{} } func (m *QuoteRequest) String() string { return proto.CompactTextString(m) } func (*QuoteRequest) ProtoMessage() {} func (*QuoteRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_client_e75b35e98d3b3b20, []int{7} + return fileDescriptor_client_3d2c5dccaa4d32eb, []int{7} } func (m *QuoteRequest) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_QuoteRequest.Unmarshal(m, b) @@ -673,7 +694,7 @@ func (m *QuoteResponse) Reset() { *m = QuoteResponse{} } func (m *QuoteResponse) String() string { return proto.CompactTextString(m) } func (*QuoteResponse) ProtoMessage() {} func (*QuoteResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_client_e75b35e98d3b3b20, []int{8} + return fileDescriptor_client_3d2c5dccaa4d32eb, []int{8} } func (m *QuoteResponse) XXX_Unmarshal(b []byte) error { return xxx_messageInfo_QuoteResponse.Unmarshal(m, b) @@ -1070,65 +1091,66 @@ var _SwapClient_serviceDesc = grpc.ServiceDesc{ Metadata: "client.proto", } -func init() { proto.RegisterFile("client.proto", fileDescriptor_client_e75b35e98d3b3b20) } - -var fileDescriptor_client_e75b35e98d3b3b20 = []byte{ - // 901 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xdd, 0x72, 0xdb, 0x44, - 0x18, 0xad, 0x64, 0xc7, 0x3f, 0x5f, 0x64, 0x45, 0xde, 0xb6, 0xa9, 0x31, 0x94, 0x31, 0x1a, 0x5a, - 0x3c, 0xb9, 0x88, 0x21, 0xbd, 0x60, 0xe0, 0x86, 0x71, 0x6d, 0xb7, 0xf5, 0x8c, 0xd3, 0x18, 0xd9, - 0x61, 0x86, 0x1b, 0x34, 0x5b, 0x7b, 0x9b, 0x6a, 0x46, 0xda, 0x55, 0xa5, 0x55, 0x9b, 0x0c, 0xc3, - 0x0d, 0x2f, 0xc0, 0x00, 0x6f, 0xc2, 0xab, 0xf0, 0x0a, 0xbc, 0x02, 0xf7, 0xcc, 0xfe, 0x48, 0x95, - 0x1c, 0x72, 0x93, 0x3b, 0xf9, 0xdb, 0xb3, 0x67, 0xcf, 0x9e, 0xef, 0x7c, 0x6b, 0xb0, 0x36, 0x61, - 0x40, 0x28, 0x3f, 0x8e, 0x13, 0xc6, 0x19, 0x6a, 0x86, 0x8c, 0xc5, 0x49, 0xbc, 0xe9, 0x7f, 0x72, - 0xc1, 0xd8, 0x45, 0x48, 0x46, 0x38, 0x0e, 0x46, 0x98, 0x52, 0xc6, 0x31, 0x0f, 0x18, 0x4d, 0x15, - 0xcc, 0xfd, 0xcb, 0x04, 0x7b, 0xc1, 0x58, 0x7c, 0x96, 0x71, 0x8f, 0xbc, 0xcd, 0x48, 0xca, 0x91, - 0x03, 0x35, 0x1c, 0xf1, 0x9e, 0x31, 0x30, 0x86, 0x35, 0x4f, 0x7c, 0x22, 0x04, 0xf5, 0x2d, 0x49, - 0x79, 0xcf, 0x1c, 0x18, 0xc3, 0xb6, 0x27, 0xbf, 0xd1, 0x08, 0xee, 0x45, 0xf8, 0xd2, 0x4f, 0xdf, - 0xe3, 0xd8, 0x4f, 0x58, 0xc6, 0x03, 0x7a, 0xe1, 0xbf, 0x26, 0xa4, 0x57, 0x93, 0xdb, 0xba, 0x11, - 0xbe, 0x5c, 0xbd, 0xc7, 0xb1, 0xa7, 0x56, 0x9e, 0x11, 0x82, 0x9e, 0xc0, 0xa1, 0xd8, 0x10, 0x27, - 0x24, 0xc6, 0x57, 0x95, 0x2d, 0x75, 0xb9, 0xe5, 0x6e, 0x84, 0x2f, 0x97, 0x72, 0xb1, 0xb4, 0x69, - 0x00, 0x56, 0x71, 0x8a, 0x80, 0xee, 0x49, 0x28, 0x68, 0x76, 0x81, 0xf8, 0x1c, 0xec, 0x12, 0xad, - 0x10, 0xde, 0x90, 0x18, 0xab, 0xa0, 0x1b, 0x47, 0x1c, 0xb9, 0xd0, 0x11, 0xa8, 0x28, 0xa0, 0x24, - 0x91, 0x44, 0x4d, 0x09, 0xda, 0x8f, 0xf0, 0xe5, 0xa9, 0xa8, 0x09, 0xa6, 0x21, 0x38, 0xc2, 0x33, - 0x9f, 0x65, 0xdc, 0xdf, 0xbc, 0xc1, 0x94, 0x92, 0xb0, 0xd7, 0x1a, 0x18, 0xc3, 0xba, 0x67, 0x87, - 0xca, 0xa1, 0x89, 0xaa, 0xba, 0xbf, 0x19, 0xd0, 0x11, 0xa6, 0xcd, 0xe9, 0xcd, 0x9e, 0xed, 0x2a, - 0x37, 0xaf, 0x29, 0xbf, 0xa6, 0xa9, 0x76, 0x5d, 0xd3, 0x63, 0x38, 0x90, 0x9a, 0x02, 0x5a, 0x48, - 0xaa, 0x4b, 0x49, 0x9d, 0x50, 0x9e, 0x9f, 0x2b, 0xfa, 0x14, 0x2c, 0x69, 0x37, 0x49, 0x63, 0x46, - 0x53, 0x82, 0x6c, 0x30, 0x83, 0xad, 0x94, 0xd3, 0xf6, 0xcc, 0x60, 0xeb, 0x3a, 0x60, 0x9f, 0x32, - 0x1a, 0x70, 0x96, 0x68, 0xc5, 0xee, 0xbf, 0x06, 0x80, 0xd8, 0xb2, 0xe2, 0x98, 0x67, 0xe9, 0xff, - 0x5c, 0x40, 0x51, 0x98, 0x39, 0x05, 0x7a, 0x04, 0x75, 0x7e, 0x15, 0x2b, 0x95, 0xf6, 0x49, 0xf7, - 0x58, 0xe7, 0xeb, 0x58, 0x90, 0xac, 0xaf, 0x62, 0xe2, 0xc9, 0x65, 0x34, 0x84, 0xbd, 0x94, 0x63, - 0xae, 0xba, 0x6a, 0x9f, 0xa0, 0x0a, 0x4e, 0x1c, 0x46, 0x3c, 0x05, 0x40, 0x5f, 0xc0, 0x41, 0x40, - 0x03, 0x1e, 0xc8, 0x3c, 0xfa, 0x3c, 0x88, 0xf2, 0xf6, 0xda, 0x1f, 0xca, 0xeb, 0x20, 0x52, 0x8d, - 0xc1, 0x29, 0xf7, 0xb3, 0x78, 0x8b, 0x39, 0x51, 0x48, 0xd5, 0x64, 0x5b, 0xd4, 0xcf, 0x65, 0x59, - 0x22, 0x3f, 0x03, 0xeb, 0x0d, 0x0f, 0x37, 0x3e, 0xde, 0x6e, 0x13, 0x92, 0xa6, 0xb2, 0xcb, 0x6d, - 0x6f, 0x5f, 0xd4, 0xc6, 0xaa, 0xe4, 0xda, 0x60, 0xad, 0x49, 0x12, 0xa5, 0xb9, 0x0f, 0xbf, 0x9b, - 0xd0, 0xd1, 0x05, 0xed, 0xdd, 0x11, 0x74, 0x65, 0xd7, 0x62, 0x7c, 0x15, 0x11, 0xca, 0x7d, 0x19, - 0x7d, 0x65, 0xe5, 0x81, 0x58, 0x58, 0xaa, 0xfa, 0x54, 0xf4, 0xdd, 0x85, 0x4e, 0xde, 0x61, 0xff, - 0x15, 0x4e, 0xf3, 0x36, 0xef, 0xa7, 0xaa, 0xc7, 0x4f, 0x71, 0x4a, 0x2a, 0x98, 0x44, 0x38, 0x53, - 0xab, 0x60, 0x3c, 0xe1, 0xc5, 0x43, 0x80, 0x52, 0x82, 0xd5, 0x40, 0xb4, 0xe3, 0x22, 0xbe, 0x8f, - 0xe1, 0x20, 0x0a, 0xa8, 0x0a, 0x13, 0x8e, 0x58, 0x46, 0xb9, 0xb6, 0xaa, 0x13, 0x05, 0x54, 0x18, - 0x3b, 0x96, 0x45, 0x89, 0xcb, 0x43, 0xa7, 0x71, 0x0d, 0x8d, 0x53, 0xb9, 0xd3, 0xb8, 0x87, 0x00, - 0x9b, 0x90, 0xbf, 0xf3, 0xb7, 0x24, 0xe4, 0x58, 0xba, 0xb4, 0xe7, 0xb5, 0x45, 0x65, 0x2a, 0x0a, - 0xee, 0x00, 0xac, 0xef, 0x33, 0xc6, 0xc9, 0x8d, 0xe9, 0x76, 0x5f, 0x43, 0x47, 0x23, 0xb4, 0x69, - 0x1f, 0x41, 0xab, 0x88, 0xba, 0xc2, 0x35, 0xf5, 0xfd, 0x76, 0xee, 0x66, 0xee, 0xde, 0xed, 0x63, - 0x68, 0xef, 0x8e, 0x40, 0x2b, 0xd2, 0xf9, 0x3f, 0x7a, 0x04, 0xad, 0x3c, 0x5f, 0xc8, 0x82, 0xd6, - 0xe2, 0xec, 0x6c, 0xe9, 0x9f, 0x9d, 0xaf, 0x9d, 0x3b, 0x68, 0x1f, 0x9a, 0xf2, 0xd7, 0xfc, 0xa5, - 0x63, 0x1c, 0xfd, 0x04, 0xed, 0x22, 0x5e, 0xa8, 0x03, 0xed, 0xf9, 0xcb, 0xf9, 0x7a, 0x3e, 0x5e, - 0xcf, 0xa6, 0xce, 0x1d, 0x74, 0x1f, 0xba, 0x4b, 0x6f, 0x36, 0x3f, 0x1d, 0x3f, 0x9f, 0xf9, 0xde, - 0xec, 0x87, 0xd9, 0x78, 0x31, 0x9b, 0x3a, 0x06, 0x42, 0x60, 0xbf, 0x58, 0x2f, 0x26, 0xfe, 0xf2, - 0xfc, 0xe9, 0x62, 0xbe, 0x7a, 0x31, 0x9b, 0x3a, 0xa6, 0xe0, 0x5c, 0x9d, 0x4f, 0x26, 0xb3, 0xd5, - 0xca, 0xa9, 0x21, 0x80, 0xc6, 0xb3, 0xf1, 0x5c, 0x80, 0xeb, 0x27, 0x7f, 0xd4, 0xd5, 0xb0, 0x4c, - 0xe4, 0x0b, 0x8b, 0x3c, 0x68, 0xea, 0x37, 0x13, 0x3d, 0x28, 0xf2, 0x5d, 0x7d, 0x45, 0xfb, 0xf7, - 0x2b, 0xc1, 0xcf, 0x7d, 0x72, 0x1f, 0xfc, 0xfa, 0xf7, 0x3f, 0x7f, 0x9a, 0x5d, 0xd7, 0x1a, 0xbd, - 0xfb, 0x6a, 0x24, 0x10, 0x23, 0x96, 0xf1, 0x6f, 0x8d, 0x23, 0xf4, 0x35, 0x34, 0xd4, 0x93, 0x82, - 0x0e, 0x2b, 0x94, 0xc5, 0x1b, 0x73, 0x03, 0x23, 0xfa, 0x06, 0x9a, 0x7a, 0xb4, 0x4b, 0x62, 0xaa, - 0xc3, 0xde, 0xbf, 0x7b, 0x6d, 0x0a, 0xb3, 0xf4, 0x4b, 0x03, 0xfd, 0x08, 0x96, 0x56, 0x2d, 0x27, - 0x00, 0x7d, 0x38, 0xa1, 0x3c, 0x22, 0xfd, 0xc3, 0xdd, 0xb2, 0xbe, 0x4b, 0x5f, 0xde, 0xe5, 0x1e, - 0x42, 0xe5, 0xbb, 0x8c, 0xb8, 0xa4, 0xf2, 0x0b, 0x6a, 0x99, 0x93, 0x12, 0x75, 0x39, 0x59, 0x25, - 0xea, 0x4a, 0x9c, 0xdc, 0x81, 0xa4, 0xee, 0xa3, 0x5e, 0x85, 0xfa, 0xad, 0xc0, 0x8c, 0x7e, 0xc6, - 0x11, 0xff, 0x05, 0x7d, 0x07, 0xf6, 0x73, 0xc2, 0x95, 0x43, 0xb7, 0x51, 0x5f, 0x21, 0xb8, 0x8d, - 0xc6, 0x57, 0x0d, 0xf9, 0x0f, 0xfa, 0xe4, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x17, 0x23, 0x70, - 0x9a, 0x78, 0x07, 0x00, 0x00, +func init() { proto.RegisterFile("client.proto", fileDescriptor_client_3d2c5dccaa4d32eb) } + +var fileDescriptor_client_3d2c5dccaa4d32eb = []byte{ + // 925 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xdd, 0x8e, 0xdb, 0x44, + 0x18, 0xad, 0x9d, 0x6c, 0x7e, 0xbe, 0x75, 0xbc, 0xce, 0xb4, 0xdd, 0x86, 0x40, 0xa5, 0x60, 0x68, + 0x89, 0xf6, 0x62, 0x03, 0xdb, 0x0b, 0x04, 0x37, 0x28, 0x4d, 0xd2, 0x6e, 0xa4, 0x6c, 0x37, 0x38, + 0x59, 0x24, 0x6e, 0xb0, 0xa6, 0xc9, 0x74, 0x6b, 0xc9, 0x9e, 0x71, 0xed, 0x71, 0x9b, 0x15, 0xe2, + 0x86, 0x37, 0x00, 0xde, 0x04, 0xf1, 0x26, 0xbc, 0x02, 0xaf, 0xc0, 0x3d, 0x9a, 0x9f, 0xb8, 0x76, + 0xc2, 0xde, 0xf4, 0xce, 0xf9, 0xe6, 0xcc, 0x99, 0xef, 0x3b, 0x73, 0xce, 0x04, 0xac, 0x55, 0x18, + 0x10, 0xca, 0x4f, 0xe3, 0x84, 0x71, 0x86, 0xea, 0x21, 0x63, 0x71, 0x12, 0xaf, 0xba, 0x9f, 0x5c, + 0x33, 0x76, 0x1d, 0x92, 0x01, 0x8e, 0x83, 0x01, 0xa6, 0x94, 0x71, 0xcc, 0x03, 0x46, 0x53, 0x05, + 0x73, 0xff, 0x34, 0xc1, 0x9e, 0x31, 0x16, 0x5f, 0x66, 0xdc, 0x23, 0x6f, 0x32, 0x92, 0x72, 0xe4, + 0x40, 0x05, 0x47, 0xbc, 0x63, 0xf4, 0x8c, 0x7e, 0xc5, 0x13, 0x9f, 0x08, 0x41, 0x75, 0x4d, 0x52, + 0xde, 0x31, 0x7b, 0x46, 0xbf, 0xe9, 0xc9, 0x6f, 0x34, 0x80, 0x7b, 0x11, 0xde, 0xf8, 0xe9, 0x3b, + 0x1c, 0xfb, 0x09, 0xcb, 0x78, 0x40, 0xaf, 0xfd, 0x57, 0x84, 0x74, 0x2a, 0x72, 0x5b, 0x3b, 0xc2, + 0x9b, 0xc5, 0x3b, 0x1c, 0x7b, 0x6a, 0xe5, 0x19, 0x21, 0xe8, 0x09, 0x1c, 0x8b, 0x0d, 0x71, 0x42, + 0x62, 0x7c, 0x53, 0xda, 0x52, 0x95, 0x5b, 0xee, 0x46, 0x78, 0x33, 0x97, 0x8b, 0x85, 0x4d, 0x3d, + 0xb0, 0xf2, 0x53, 0x04, 0xf4, 0x40, 0x42, 0x41, 0xb3, 0x0b, 0xc4, 0xe7, 0x60, 0x17, 0x68, 0x45, + 0xe3, 0x35, 0x89, 0xb1, 0x72, 0xba, 0x61, 0xc4, 0x91, 0x0b, 0x2d, 0x81, 0x8a, 0x02, 0x4a, 0x12, + 0x49, 0x54, 0x97, 0xa0, 0xc3, 0x08, 0x6f, 0x2e, 0x44, 0x4d, 0x30, 0xf5, 0xc1, 0x11, 0x9a, 0xf9, + 0x2c, 0xe3, 0xfe, 0xea, 0x35, 0xa6, 0x94, 0x84, 0x9d, 0x46, 0xcf, 0xe8, 0x57, 0x3d, 0x3b, 0x54, + 0x0a, 0x8d, 0x54, 0xd5, 0xfd, 0xcb, 0x80, 0x96, 0x10, 0x6d, 0x4a, 0x6f, 0xd7, 0x6c, 0xb7, 0x73, + 0x73, 0xaf, 0xf3, 0xbd, 0x9e, 0x2a, 0xfb, 0x3d, 0x3d, 0x86, 0x23, 0xd9, 0x53, 0x40, 0xf3, 0x96, + 0xaa, 0xb2, 0xa5, 0x56, 0x28, 0xcf, 0xd7, 0x1d, 0xa1, 0xcf, 0xa0, 0x45, 0x36, 0x9c, 0x24, 0x14, + 0x87, 0xfe, 0x6b, 0x1e, 0xae, 0xa4, 0x50, 0x0d, 0xcf, 0xda, 0x16, 0xcf, 0x79, 0xb8, 0x72, 0x87, + 0x60, 0xc9, 0x3b, 0x21, 0x69, 0xcc, 0x68, 0x4a, 0x90, 0x0d, 0x66, 0xb0, 0x96, 0x3d, 0x37, 0x3d, + 0x33, 0x58, 0xa3, 0x4f, 0xc1, 0x12, 0x7b, 0x7d, 0xbc, 0x5e, 0x27, 0x24, 0x4d, 0xf5, 0x75, 0x1f, + 0x8a, 0xda, 0x50, 0x95, 0x5c, 0x07, 0xec, 0x0b, 0x46, 0x03, 0xce, 0x12, 0x3d, 0xb9, 0xfb, 0xaf, + 0x01, 0x20, 0x58, 0x17, 0x1c, 0xf3, 0x2c, 0xfd, 0x1f, 0x21, 0xd4, 0x29, 0x66, 0x7e, 0xca, 0x23, + 0xa8, 0xf2, 0x9b, 0x58, 0x4d, 0x6b, 0x9f, 0xb5, 0x4f, 0xb5, 0x4f, 0x4f, 0x05, 0xc9, 0xf2, 0x26, + 0x26, 0x9e, 0x5c, 0x46, 0x7d, 0x38, 0x48, 0x39, 0xe6, 0xca, 0x1d, 0xf6, 0x19, 0x2a, 0xe1, 0xc4, + 0x61, 0xc4, 0x53, 0x00, 0xf4, 0x05, 0x1c, 0x05, 0x34, 0xe0, 0x81, 0xf4, 0xb5, 0xcf, 0x83, 0x68, + 0x6b, 0x13, 0xfb, 0x7d, 0x79, 0x19, 0x44, 0xea, 0x82, 0x71, 0xca, 0xfd, 0x2c, 0x5e, 0x63, 0x4e, + 0x14, 0x52, 0x99, 0xc5, 0x16, 0xf5, 0x2b, 0x59, 0x96, 0xc8, 0x5d, 0x25, 0xea, 0xfb, 0x4a, 0xd8, + 0x60, 0x2d, 0x49, 0x12, 0xa5, 0x5b, 0x1d, 0x7e, 0x33, 0xa1, 0xa5, 0x0b, 0x5a, 0xde, 0x13, 0x68, + 0xcb, 0xdb, 0x8f, 0xf1, 0x4d, 0x44, 0x28, 0xf7, 0x65, 0x84, 0x94, 0xda, 0x47, 0x62, 0x61, 0xae, + 0xea, 0x63, 0xe1, 0x1f, 0x17, 0x5a, 0x5b, 0xa7, 0xf8, 0x2f, 0x71, 0xba, 0xb5, 0xcb, 0x61, 0xaa, + 0xbc, 0xf2, 0x14, 0xa7, 0xa4, 0x84, 0x49, 0x84, 0x32, 0x95, 0x12, 0xc6, 0x13, 0x5a, 0x3c, 0x04, + 0x28, 0x24, 0x41, 0x05, 0xab, 0x19, 0xe7, 0x31, 0x78, 0x0c, 0x47, 0x51, 0x40, 0x95, 0x29, 0x71, + 0xc4, 0x32, 0xca, 0xb5, 0x54, 0xad, 0x28, 0xa0, 0x42, 0xd8, 0xa1, 0x2c, 0x4a, 0xdc, 0xd6, 0xbc, + 0x1a, 0x57, 0xd3, 0x38, 0xe5, 0x5f, 0x8d, 0x7b, 0x08, 0xb0, 0x0a, 0xf9, 0x5b, 0x7f, 0x4d, 0x42, + 0x8e, 0xa5, 0x4a, 0x07, 0x5e, 0x53, 0x54, 0xc6, 0xa2, 0xe0, 0xf6, 0xc0, 0xfa, 0x3e, 0x63, 0x9c, + 0xdc, 0x9a, 0x12, 0xf7, 0x15, 0xb4, 0x34, 0x42, 0x8b, 0xf6, 0x11, 0x34, 0xf2, 0xc8, 0x28, 0x5c, + 0x5d, 0xcf, 0xb7, 0x33, 0x9b, 0xb9, 0x3b, 0xdb, 0xc7, 0xd0, 0xdc, 0x8d, 0x52, 0x23, 0xd2, 0x39, + 0x3a, 0x79, 0x04, 0x8d, 0xad, 0xbf, 0x90, 0x05, 0x8d, 0xd9, 0xe5, 0xe5, 0xdc, 0xbf, 0xbc, 0x5a, + 0x3a, 0x77, 0xd0, 0x21, 0xd4, 0xe5, 0xaf, 0xe9, 0x0b, 0xc7, 0x38, 0xf9, 0x09, 0x9a, 0xb9, 0xbd, + 0x50, 0x0b, 0x9a, 0xd3, 0x17, 0xd3, 0xe5, 0x74, 0xb8, 0x9c, 0x8c, 0x9d, 0x3b, 0xe8, 0x3e, 0xb4, + 0xe7, 0xde, 0x64, 0x7a, 0x31, 0x7c, 0x3e, 0xf1, 0xbd, 0xc9, 0x0f, 0x93, 0xe1, 0x6c, 0x32, 0x76, + 0x0c, 0x84, 0xc0, 0x3e, 0x5f, 0xce, 0x46, 0xfe, 0xfc, 0xea, 0xe9, 0x6c, 0xba, 0x38, 0x9f, 0x8c, + 0x1d, 0x53, 0x70, 0x2e, 0xae, 0x46, 0xa3, 0xc9, 0x62, 0xe1, 0x54, 0x10, 0x40, 0xed, 0xd9, 0x70, + 0x2a, 0xc0, 0xd5, 0xb3, 0xdf, 0xab, 0x2a, 0x2c, 0x23, 0xf9, 0x52, 0x23, 0x0f, 0xea, 0xfa, 0xed, + 0x45, 0x0f, 0x72, 0x7f, 0x97, 0x5f, 0xe3, 0xee, 0xfd, 0x92, 0xf1, 0xb7, 0x3a, 0xb9, 0x0f, 0x7e, + 0xfd, 0xfb, 0x9f, 0x3f, 0xcc, 0xb6, 0x6b, 0x0d, 0xde, 0x7e, 0x35, 0x10, 0x88, 0x01, 0xcb, 0xf8, + 0xb7, 0xc6, 0x09, 0xfa, 0x1a, 0x6a, 0xea, 0x69, 0x42, 0xc7, 0x25, 0xca, 0xfc, 0xad, 0xba, 0x85, + 0x11, 0x7d, 0x03, 0x75, 0x1d, 0xed, 0x42, 0x33, 0xe5, 0xb0, 0x77, 0xef, 0xee, 0xa5, 0x30, 0x4b, + 0xbf, 0x34, 0xd0, 0x8f, 0x60, 0xe9, 0xae, 0x65, 0x02, 0xd0, 0xfb, 0x13, 0x8a, 0x11, 0xe9, 0x1e, + 0xef, 0x96, 0xf5, 0x2c, 0x5d, 0x39, 0xcb, 0x3d, 0x84, 0x8a, 0xb3, 0x0c, 0xb8, 0xa4, 0xf2, 0x73, + 0x6a, 0xe9, 0x93, 0x02, 0x75, 0xd1, 0x59, 0x05, 0xea, 0x92, 0x9d, 0xdc, 0x9e, 0xa4, 0xee, 0xa2, + 0x4e, 0x89, 0xfa, 0x8d, 0xc0, 0x0c, 0x7e, 0xc6, 0x11, 0xff, 0x05, 0x7d, 0x07, 0xf6, 0x73, 0xc2, + 0x95, 0x42, 0x1f, 0xd2, 0x7d, 0x89, 0xe0, 0x43, 0x7a, 0x7c, 0x59, 0x93, 0xff, 0xc4, 0x4f, 0xfe, + 0x0b, 0x00, 0x00, 0xff, 0xff, 0xe3, 0xae, 0x80, 0xa3, 0xc0, 0x07, 0x00, 0x00, } diff --git a/looprpc/client.proto b/looprpc/client.proto index d7d5e7e..099b55b 100644 --- a/looprpc/client.proto +++ b/looprpc/client.proto @@ -158,6 +158,12 @@ message LoopInRequest { on the lowest routing fee for the swap payment from the server. */ uint64 loop_in_channel = 4; + + /** + If external_htlc is true, we expect the htlc to be published by an external + actor. + */ + bool external_htlc = 5; } message SwapResponse { @@ -166,6 +172,11 @@ message SwapResponse { the Start() call. Currently this is the hash that locks the htlcs. */ string id = 1; + + /** + The address of the on-chain htlc. + */ + string htlc_address = 2; } message MonitorRequest{ diff --git a/looprpc/client.swagger.json b/looprpc/client.swagger.json index 71fe251..6a1203c 100644 --- a/looprpc/client.swagger.json +++ b/looprpc/client.swagger.json @@ -157,6 +157,10 @@ "id": { "type": "string", "description": "*\nSwap identifier to track status in the update stream that is returned from\nthe Start() call. Currently this is the hash that locks the htlcs." + }, + "htlc_address": { + "type": "string", + "description": "*\nThe address of the on-chain htlc." } } },