Skip to content

Commit

Permalink
lsps2: implement get_info
Browse files Browse the repository at this point in the history
  • Loading branch information
JssDWt committed Aug 12, 2023
1 parent 24a2c44 commit 3c431ce
Show file tree
Hide file tree
Showing 4 changed files with 237 additions and 6 deletions.
3 changes: 3 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ type NodeConfig struct {
// peer is offline.
NotificationTimeout string `json:"notificationTimeout,string"`

MinPaymentSizeMsat uint64 `json:"minPaymentSizeMsat,string"`
MaxPaymentSizeMsat uint64 `json:"maxPaymentSizeMsat,string"`

// Set this field to connect to an LND node.
Lnd *LndConfig `json:"lnd,omitempty"`

Expand Down
104 changes: 99 additions & 5 deletions lsps2/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,116 @@ package lsps2

import (
"context"
"log"

"github.com/breez/lspd/lsps0"
"github.com/breez/lspd/lsps0/codes"
"github.com/breez/lspd/lsps0/status"
"github.com/breez/lspd/shared"
)

var SupportedVersion uint32 = 1

type GetVersionsRequest struct {
}

type GetVersionsResponse struct {
Versions []int32 `json:"versions"`
Versions []uint32 `json:"versions"`
}

type GetInfoRequest struct {
Version uint32 `json:"version"`
Token *string `json:"token,omitempty"`
}

type GetInfoResponse struct {
OpeningFeeParamsMenu []*OpeningFeeParams `json:"opening_fee_params_menu"`
MinPaymentSizeMsat uint64 `json:"min_payment_size_msat,string"`
MaxPaymentSizeMsat uint64 `json:"max_payment_size_msat,string"`
}

type OpeningFeeParams struct {
MinFeeMsat uint64 `json:"min_fee_msat,string"`
Proportional uint32 `json:"proportional"`
ValidUntil string `json:"valid_until"`
MinLifetime uint32 `json:"min_lifetime"`
MaxClientToSelfDelay uint32 `json:"max_client_to_self_delay"`
Promise string `json:"promise"`
}

type Lsps2Server interface {
GetVersions(ctx context.Context, request *GetVersionsRequest) (*GetVersionsResponse, error)
GetInfo(ctx context.Context, request *GetInfoRequest) (*GetInfoResponse, error)
}
type server struct {
openingService shared.OpeningService
nodesService shared.NodesService
}
type server struct{}

func NewLsps2Server() Lsps2Server {
return &server{}
func NewLsps2Server(
openingService shared.OpeningService,
nodesService shared.NodesService,
) Lsps2Server {
return &server{
openingService: openingService,
nodesService: nodesService,
}
}

func (s *server) GetVersions(
ctx context.Context,
request *GetVersionsRequest,
) (*GetVersionsResponse, error) {
return &GetVersionsResponse{
Versions: []int32{1},
Versions: []uint32{SupportedVersion},
}, nil
}

func (s *server) GetInfo(
ctx context.Context,
request *GetInfoRequest,
) (*GetInfoResponse, error) {
if request.Version != uint32(SupportedVersion) {
return nil, status.New(codes.Code(1), "unsupported_version").Err()
}

if request.Token == nil || *request.Token == "" {
return nil, status.New(codes.Code(2), "unrecognized_or_stale_token").Err()
}

node, err := s.nodesService.GetNode(*request.Token)
if err == shared.ErrNodeNotFound {
return nil, status.New(codes.Code(2), "unrecognized_or_stale_token").Err()
}
if err != nil {
log.Printf("Lsps2Server.GetInfo: nodesService.GetNode(%s) err: %v", *request.Token, err)
return nil, status.New(codes.InternalError, "internal error").Err()
}

m, err := s.openingService.GetFeeParamsMenu(*request.Token)
if err == shared.ErrNodeNotFound {
return nil, status.New(codes.Code(2), "unrecognized_or_stale_token").Err()
}
if err != nil {
log.Printf("Lsps2Server.GetInfo: openingService.GetFeeParamsMenu(%s) err: %v", *request.Token, err)
return nil, status.New(codes.InternalError, "internal error").Err()
}

menu := []*OpeningFeeParams{}
for _, p := range m {
menu = append(menu, &OpeningFeeParams{
MinFeeMsat: p.MinFeeMsat,
Proportional: p.Proportional,
ValidUntil: p.ValidUntil,
MinLifetime: p.MinLifetime,
MaxClientToSelfDelay: p.MaxClientToSelfDelay,
Promise: p.Promise,
})
}
return &GetInfoResponse{
OpeningFeeParamsMenu: menu,
MinPaymentSizeMsat: node.NodeConfig.MinPaymentSizeMsat,
MaxPaymentSizeMsat: node.NodeConfig.MaxPaymentSizeMsat,
}, nil
}

Expand All @@ -47,6 +131,16 @@ func RegisterLsps2Server(s lsps0.ServiceRegistrar, l Lsps2Server) {
return srv.(Lsps2Server).GetVersions(ctx, in)
},
},
{
MethodName: "lsps2.get_info",
Handler: func(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
in := new(GetInfoRequest)
if err := dec(in); err != nil {
return nil, err
}
return srv.(Lsps2Server).GetInfo(ctx, in)
},
},
},
},
l,
Expand Down
134 changes: 134 additions & 0 deletions lsps2/server_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package lsps2

import (
"context"
"testing"

"github.com/breez/lspd/config"
"github.com/breez/lspd/lsps0/status"
"github.com/breez/lspd/shared"
"github.com/stretchr/testify/assert"
)

type mockNodesService struct {
node *shared.Node
err error
}

func (m *mockNodesService) GetNode(token string) (*shared.Node, error) {
return m.node, m.err
}

type mockOpeningService struct {
menu []*shared.OpeningFeeParams
err error
valid bool
}

func (m *mockOpeningService) GetFeeParamsMenu(token string) ([]*shared.OpeningFeeParams, error) {
return m.menu, m.err
}

func (m *mockOpeningService) ValidateOpeningFeeParams(token string, params *shared.OpeningFeeParams) bool {
return m.valid
}

var token = "blah"
var node = &shared.Node{
NodeConfig: &config.NodeConfig{
MinPaymentSizeMsat: 123,
MaxPaymentSizeMsat: 456,
},
}

func Test_GetInfo_UnsupportedVersion(t *testing.T) {
n := &mockNodesService{}
o := &mockOpeningService{}
s := NewLsps2Server(o, n)
_, err := s.GetInfo(context.Background(), &GetInfoRequest{
Version: 2,
Token: &token,
})

st := status.Convert(err)
assert.Equal(t, uint32(1), uint32(st.Code))
assert.Equal(t, "unsupported_version", st.Message)
}

func Test_GetInfo_InvalidToken(t *testing.T) {
n := &mockNodesService{
err: shared.ErrNodeNotFound,
}
o := &mockOpeningService{}
s := NewLsps2Server(o, n)
_, err := s.GetInfo(context.Background(), &GetInfoRequest{
Version: 1,
Token: &token,
})

st := status.Convert(err)
assert.Equal(t, uint32(2), uint32(st.Code))
assert.Equal(t, "unrecognized_or_stale_token", st.Message)
}

func Test_GetInfo_EmptyMenu(t *testing.T) {
n := &mockNodesService{node: node}
o := &mockOpeningService{menu: []*shared.OpeningFeeParams{}}
s := NewLsps2Server(o, n)
resp, err := s.GetInfo(context.Background(), &GetInfoRequest{
Version: 1,
Token: &token,
})

assert.Nil(t, err)
assert.Equal(t, []*OpeningFeeParams{}, resp.OpeningFeeParamsMenu)
assert.Equal(t, node.NodeConfig.MinPaymentSizeMsat, resp.MinPaymentSizeMsat)
assert.Equal(t, node.NodeConfig.MaxPaymentSizeMsat, resp.MaxPaymentSizeMsat)
}

func Test_GetInfo_PopulatedMenu_Ordered(t *testing.T) {
n := &mockNodesService{node: node}
o := &mockOpeningService{menu: []*shared.OpeningFeeParams{
{
MinFeeMsat: 1,
Proportional: 2,
ValidUntil: "a",
MinLifetime: 3,
MaxClientToSelfDelay: 4,
Promise: "b",
},
{
MinFeeMsat: 5,
Proportional: 6,
ValidUntil: "c",
MinLifetime: 7,
MaxClientToSelfDelay: 8,
Promise: "d",
},
}}
s := NewLsps2Server(o, n)
resp, err := s.GetInfo(context.Background(), &GetInfoRequest{
Version: 1,
Token: &token,
})

assert.Nil(t, err)
assert.Len(t, resp.OpeningFeeParamsMenu, 2)

assert.Equal(t, uint64(1), resp.OpeningFeeParamsMenu[0].MinFeeMsat)
assert.Equal(t, uint32(2), resp.OpeningFeeParamsMenu[0].Proportional)
assert.Equal(t, "a", resp.OpeningFeeParamsMenu[0].ValidUntil)
assert.Equal(t, uint32(3), resp.OpeningFeeParamsMenu[0].MinLifetime)
assert.Equal(t, uint32(4), resp.OpeningFeeParamsMenu[0].MaxClientToSelfDelay)
assert.Equal(t, "b", resp.OpeningFeeParamsMenu[0].Promise)

assert.Equal(t, uint64(5), resp.OpeningFeeParamsMenu[1].MinFeeMsat)
assert.Equal(t, uint32(6), resp.OpeningFeeParamsMenu[1].Proportional)
assert.Equal(t, "c", resp.OpeningFeeParamsMenu[1].ValidUntil)
assert.Equal(t, uint32(7), resp.OpeningFeeParamsMenu[1].MinLifetime)
assert.Equal(t, uint32(8), resp.OpeningFeeParamsMenu[1].MaxClientToSelfDelay)
assert.Equal(t, "d", resp.OpeningFeeParamsMenu[1].Promise)

assert.Equal(t, node.NodeConfig.MinPaymentSizeMsat, resp.MinPaymentSizeMsat)
assert.Equal(t, node.NodeConfig.MaxPaymentSizeMsat, resp.MaxPaymentSizeMsat)
}
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ func main() {
go msgClient.Start()
msgServer := lsps0.NewServer()
protocolServer := lsps0.NewProtocolServer([]uint32{2})
lsps2Server := lsps2.NewLsps2Server()
lsps2Server := lsps2.NewLsps2Server(openingService, nodesService)
lsps0.RegisterProtocolServer(msgServer, protocolServer)
lsps2.RegisterLsps2Server(msgServer, lsps2Server)
msgClient.WaitStarted()
Expand Down

0 comments on commit 3c431ce

Please sign in to comment.