diff --git a/init_lnd.go b/init_lnd.go index 195a1de..092797a 100644 --- a/init_lnd.go +++ b/init_lnd.go @@ -27,7 +27,7 @@ func InitLNClient(c *service.Config, logger *lecho.Logger, ctx context.Context) } } func InitLNDCluster(c *service.Config, logger *lecho.Logger, ctx context.Context) (result lnd.LightningClientWrapper, err error) { - nodes := []*lnd.LNDWrapper{} + nodes := []lnd.LightningClientWrapper{} //interpret lnd address, macaroon file & cert file as comma seperated values addresses := strings.Split(c.LNDAddress, ",") macaroons := strings.Split(c.LNDMacaroonFile, ",") diff --git a/integration_tests/lnd_cluster_test.go b/integration_tests/lnd_cluster_test.go new file mode 100644 index 0000000..b8b7a42 --- /dev/null +++ b/integration_tests/lnd_cluster_test.go @@ -0,0 +1,57 @@ +package integration_tests + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/getAlby/lndhub.go/lib" + "github.com/getAlby/lndhub.go/lnd" + "github.com/lightningnetwork/lnd/lnrpc" + "github.com/stretchr/testify/assert" +) + +func TestLNDCluster(t *testing.T) { + mockClients := []lnd.LightningClientWrapper{} + mockLND1, err := NewMockLND("1234567890abcdef", 0, make(chan (*lnrpc.Invoice))) + assert.NoError(t, err) + mockLND2, err := NewMockLND("1234567890abcdefff", 0, make(chan (*lnrpc.Invoice))) + assert.NoError(t, err) + mockClients = append(mockClients, mockLND1, mockLND2) + lndMockCluster := lnd.LNDCluster{ + Nodes: mockClients, + ActiveNode: mockClients[0], + ActiveChannelRatio: 0.5, + Logger: lib.Logger(""), + LivenessCheckPeriod: 1, + } + ctx, cancel := context.WithCancel(context.Background()) + go lndMockCluster.StartLivenessLoop(ctx) + //record pubkey of lnd-1, lnd-2 + info1, err := mockLND1.GetInfo(ctx, &lnrpc.GetInfoRequest{}) + assert.NoError(t, err) + info2, err := mockLND2.GetInfo(ctx, &lnrpc.GetInfoRequest{}) + assert.NoError(t, err) + //call getinfo - should be lnd1 that responds + resp, err := lndMockCluster.GetInfo(ctx, &lnrpc.GetInfoRequest{}) + assert.NoError(t, err) + assert.Equal(t, info1.IdentityPubkey, resp.IdentityPubkey) + //make lnd-1 return the error + mockLND1.GetInfoError = fmt.Errorf("some error") + //sleep a bit again + time.Sleep(2 * time.Second) + //call getinfo, should be lnd2 that responds + resp, err = lndMockCluster.GetInfo(ctx, &lnrpc.GetInfoRequest{}) + assert.NoError(t, err) + assert.Equal(t, info2.IdentityPubkey, resp.IdentityPubkey) + //make lnd-1 return no error + mockLND1.GetInfoError = nil + //sleep a bit again + time.Sleep(2 * time.Second) + //call getinfo, should be lnd1 that responds + resp, err = lndMockCluster.GetInfo(ctx, &lnrpc.GetInfoRequest{}) + assert.NoError(t, err) + assert.Equal(t, info1.IdentityPubkey, resp.IdentityPubkey) + cancel() +} diff --git a/integration_tests/lnd_mock.go b/integration_tests/lnd_mock.go index 47a758d..26812a9 100644 --- a/integration_tests/lnd_mock.go +++ b/integration_tests/lnd_mock.go @@ -27,6 +27,7 @@ type MockLND struct { privKey *btcec.PrivateKey pubKey *btcec.PublicKey addIndexCounter uint64 + GetInfoError error } func NewMockLND(privkey string, fee int64, invoiceChan chan (*lnrpc.Invoice)) (*MockLND, error) { @@ -195,7 +196,9 @@ func (mlnd *MockLND) SubscribeInvoices(ctx context.Context, req *lnrpc.InvoiceSu } func (mlnd *MockLND) GetInfo(ctx context.Context, req *lnrpc.GetInfoRequest, options ...grpc.CallOption) (*lnrpc.GetInfoResponse, error) { - + if mlnd.GetInfoError != nil { + return nil, mlnd.GetInfoError + } return &lnrpc.GetInfoResponse{ Version: "v1.0.0", CommitHash: "abc123", diff --git a/lnd/lnd_cluster.go b/lnd/lnd_cluster.go index 6649d30..fb47c1e 100644 --- a/lnd/lnd_cluster.go +++ b/lnd/lnd_cluster.go @@ -13,8 +13,8 @@ import ( ) type LNDCluster struct { - Nodes []*LNDWrapper - ActiveNode *LNDWrapper + Nodes []LightningClientWrapper + ActiveNode LightningClientWrapper ActiveChannelRatio float64 Logger *lecho.Logger LivenessCheckPeriod int