Skip to content

Commit

Permalink
test: add integration test for LWK
Browse files Browse the repository at this point in the history
The integration test for LWK is added to ensure
that the swap functionality works as expected
with the LWK and electrs support.

The setup functions are implemented to create the necessary test
environment, including lwk, Bitcoin and Liquid nodes,
 as well as two lightning nodes with the PeerSwap.
This setup is crucial for testing the swap-in process
in an environment that closely mimics production.

also, added Electrs and LWK structs for testing framework.
- Implement `Electrs` struct to manage electrs daemon processes
- Implement `LWK` struct to manage LWK daemon processes
- Provide constructors for both structs to
initialize with dynamic ports and configurations
- Include methods to run the processes and connect
  • Loading branch information
YusukeShimizu committed Mar 27, 2024
1 parent c00f647 commit 61113a6
Show file tree
Hide file tree
Showing 6 changed files with 340 additions and 6 deletions.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ require (
github.com/gorilla/websocket v1.5.0 // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgconn v1.13.0 // indirect
github.com/jackc/pgio v1.0.0 // indirect
Expand Down Expand Up @@ -154,6 +155,7 @@ require (
github.com/lightningnetwork/lnd/queue v1.1.0 // indirect
github.com/lightningnetwork/lnd/ticker v1.1.0 // indirect
github.com/lightningnetwork/lnd/tlv v1.0.3 // indirect
go.uber.org/mock v0.4.0
)

// This fork contains some options we need to reconnect to lnd.
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,8 @@ github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dvyukov/go-fuzz v0.0.0-20220726122315-1d375ef9f9f6 h1:sE4tvxWw01v7K3MAHwKF2UF3xQbgy23PRURntuV1CkU=
github.com/dvyukov/go-fuzz v0.0.0-20220726122315-1d375ef9f9f6/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
github.com/elementsproject/glightning v0.0.0-20240224063423-55240d61b52a h1:xnVQmVqGmSs3m8zPQF4iYEYiUAmJx8MlT9vJ3lAaOjc=
github.com/elementsproject/glightning v0.0.0-20240224063423-55240d61b52a/go.mod h1:YAdIeSyx8VEhDCtEaGOJLmWNpPaQ3x4vYSAj9Vrppdo=
github.com/elementsproject/glightning v0.0.0-20231126051537-e32b4dae6cbb h1:ob08+u2vJvk9uFoPhwFe/DWom1pgUFLGh+VXUbfarWs=
github.com/elementsproject/glightning v0.0.0-20231126051537-e32b4dae6cbb/go.mod h1:YAdIeSyx8VEhDCtEaGOJLmWNpPaQ3x4vYSAj9Vrppdo=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
Expand Down
88 changes: 88 additions & 0 deletions test/lwk_cln_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package test

import (
"math"
"os"
"testing"

"github.com/elementsproject/peerswap/clightning"
"github.com/elementsproject/peerswap/swap"
"github.com/stretchr/testify/require"
)

func Test_ClnCln_LWK_SwapIn(t *testing.T) {
t.Skip("Skipping test until we have lwk and electrs support on nix")
IsIntegrationTest(t)
t.Parallel()

t.Run("claim_normal", func(t *testing.T) {
t.Parallel()
require := require.New(t)

bitcoind, liquidd, lightningds, scid := clnclnLWKSetup(t, uint64(math.Pow10(9)))
defer func() {
if t.Failed() {
filter := os.Getenv("PEERSWAP_TEST_FILTER")
pprintFail(
tailableProcess{
p: bitcoind.DaemonProcess,
lines: defaultLines,
},
tailableProcess{
p: liquidd.DaemonProcess,
lines: defaultLines,
},
tailableProcess{
p: lightningds[0].DaemonProcess,
filter: filter,
lines: defaultLines,
},
tailableProcess{
p: lightningds[1].DaemonProcess,
filter: filter,
lines: defaultLines,
},
)
}
}()

var channelBalances []uint64
var walletBalances []uint64
for _, lightningd := range lightningds {
b, err := lightningd.GetBtcBalanceSat()
require.NoError(err)
walletBalances = append(walletBalances, b)

b, err = lightningd.GetChannelBalanceSat(scid)
require.NoError(err)
channelBalances = append(channelBalances, b)
}

params := &testParams{
swapAmt: channelBalances[0] / 2,
scid: scid,
origTakerWallet: walletBalances[0],
origMakerWallet: walletBalances[1],
origTakerBalance: channelBalances[0],
origMakerBalance: channelBalances[1],
takerNode: lightningds[0],
makerNode: lightningds[1],
takerPeerswap: lightningds[0].DaemonProcess,
makerPeerswap: lightningds[1].DaemonProcess,
chainRpc: liquidd.RpcProxy,
chaind: liquidd,
confirms: LiquidConfirms,
csv: LiquidCsv,
swapType: swap.SWAPTYPE_IN,
}
asset := "lbtc"

// Do swap.
go func() {
var response map[string]interface{}
lightningds[1].Rpc.Request(&clightning.SwapIn{SatAmt: params.swapAmt, ShortChannelId: params.scid, Asset: asset}, &response)

}()
preimageClaimTest(t, params)
})
}
172 changes: 168 additions & 4 deletions test/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func clnclnSetupWithConfig(t *testing.T, fundAmt, pushAmt uint64, clnConf []stri
os.ModePerm,
)

// Use lightningd with --developer turned on
// Use lightningd with --developer turned on
lightningd.WithCmd("lightningd")

// Add plugin to cmd line options
Expand Down Expand Up @@ -243,7 +243,7 @@ func mixedSetup(t *testing.T, fundAmt uint64, funder fundingNode) (*testframewor
os.ModePerm,
)

// Use lightningd with --developer turned on
// Use lightningd with --developer turned on
cln.WithCmd("lightningd")

// Add plugin to cmd line options
Expand Down Expand Up @@ -405,7 +405,7 @@ func clnclnElementsSetup(t *testing.T, fundAmt uint64) (*testframework.BitcoinNo
os.ModePerm,
)

// Use lightningd with --developer turned on
// Use lightningd with --developer turned on
lightningd.WithCmd("lightningd")

// Add plugin to cmd line options
Expand Down Expand Up @@ -665,7 +665,7 @@ func mixedElementsSetup(t *testing.T, fundAmt uint64, funder fundingNode) (*test
os.ModePerm,
)

// Use lightningd with --developer turned on
// Use lightningd with --developer turned on
cln.WithCmd("lightningd")

// Add plugin to cmd line options
Expand Down Expand Up @@ -799,3 +799,167 @@ func (n *LndNodeWithLiquid) GetBtcBalanceSat() (uint64, error) {
}
return r.SatAmount, nil
}

func clnclnLWKSetup(t *testing.T, fundAmt uint64) (*testframework.BitcoinNode, *testframework.LiquidNode, []*CLightningNodeWithLiquid, string) {
/// Get PeerSwap plugin path and test dir
_, filename, _, _ := runtime.Caller(0)
pathToPlugin := filepath.Join(filename, "..", "..", "out", "test-builds", "peerswap")
testDir := t.TempDir()

// Setup nodes (1 bitcoind, 1 liquidd, 2 lightningd)
bitcoind, err := testframework.NewBitcoinNode(testDir, 1)
if err != nil {
t.Fatalf("could not create bitcoind %v", err)
}
t.Cleanup(bitcoind.Kill)

liquidd, err := testframework.NewLiquidNode(testDir, bitcoind, 1)
if err != nil {
t.Fatal("error creating liquidd node", err)
}
t.Cleanup(liquidd.Kill)

electrsd, err := testframework.NewElectrs(testDir, 1, liquidd)
if err != nil {
t.Fatal("error creating electrsd node", err)
}
t.Cleanup(electrsd.Process.Kill)

lwk, err := testframework.NewLWK(testDir, 1, electrsd)
if err != nil {
t.Fatal("error creating electrsd node", err)
}
t.Cleanup(lwk.Process.Kill)

var lightningds []*testframework.CLightningNode
for i := 1; i <= 2; i++ {
lightningd, err := testframework.NewCLightningNode(testDir, bitcoind, i)
if err != nil {
t.Fatalf("could not create liquidd %v", err)
}
t.Cleanup(lightningd.Kill)
defer printFailedFiltered(t, lightningd.DaemonProcess)

// Create policy file and accept all peers
err = os.MkdirAll(filepath.Join(lightningd.GetDataDir(), "peerswap"), os.ModePerm)
if err != nil {
t.Fatal("could not create dir", err)
}
err = os.WriteFile(filepath.Join(lightningd.GetDataDir(), "peerswap", "policy.conf"), []byte("accept_all_peers=1\n"), os.ModePerm)
if err != nil {
t.Fatal("could not create policy file", err)
}

// Set wallet name
walletName := fmt.Sprintf("swap%d", i)

// Create config file
fileConf := struct {
LWK struct {
SignerName string
WalletName string
LWKEndpoint string
ElectrumEndpoint string
Network string
LiquidSwaps bool
}
}{
LWK: struct {
SignerName string
WalletName string
LWKEndpoint string
ElectrumEndpoint string
Network string
LiquidSwaps bool
}{
WalletName: walletName,
SignerName: walletName + "-" + "signer",
LiquidSwaps: true,
},
}
data, err := toml.Marshal(fileConf)
require.NoError(t, err)

configPath := filepath.Join(lightningd.GetDataDir(), "peerswap", "peerswap.conf")
os.WriteFile(
configPath,
data,
os.ModePerm,
)

// Use lightningd with --developer turned on
lightningd.WithCmd("lightningd")

// Add plugin to cmd line options
lightningd.AppendCmdLine([]string{
"--dev-bitcoind-poll=1",
"--dev-fast-gossip",
"--large-channels",
fmt.Sprint("--plugin=", pathToPlugin),
})

lightningds = append(lightningds, lightningd)
}

// Start nodes
err = bitcoind.Run(true)
if err != nil {
t.Fatalf("bitcoind.Run() got err %v", err)
}

err = liquidd.Run(true)
if err != nil {
t.Fatalf("Run() got err %v", err)
}

ctx := context.Background()
ctx, cancel := context.WithTimeout(ctx, testframework.TIMEOUT)
defer cancel()
require.NoError(t, electrsd.Run(ctx))
lwk.Process.Run()

for _, lightningd := range lightningds {
err = lightningd.Run(true, true)
if err != nil {
t.Fatalf("lightningd.Run() got err %v", err)
}
err = lightningd.WaitForLog("peerswap initialized", testframework.TIMEOUT)
if err != nil {
t.Fatalf("lightningd.WaitForLog() got err %v", err)
}
}

// Give liquid funds to nodes to have something to swap.
for _, lightningd := range lightningds {
var result clightning.GetAddressResponse
lightningd.Rpc.Request(&clightning.LiquidGetAddress{}, &result)
_ = liquidd.GenerateBlocks(20)
_, err = liquidd.Rpc.Call("sendtoaddress", result.LiquidAddress, 10., "", "", false, false, 1, "UNSET")
require.NoError(t, err)
}

// Lock txs.
_, err = liquidd.Rpc.Call("generatetoaddress", 1, testframework.LBTC_BURN)
require.NoError(t, err)

// Setup channel ([0] fundAmt(10^7) ---- 0 [1]).
scid, err := lightningds[0].OpenChannel(lightningds[1], fundAmt, 0, true, true, true)
if err != nil {
t.Fatalf("lightingds[0].OpenChannel() %v", err)
}

// Sync peer polling
var result interface{}
err = lightningds[0].Rpc.Request(&clightning.ReloadPolicyFile{}, &result)
if err != nil {
t.Fatalf("ListPeers %v", err)
}
err = lightningds[1].Rpc.Request(&clightning.ReloadPolicyFile{}, &result)
if err != nil {
t.Fatalf("ListPeers %v", err)
}

syncPoll(&clnPollableNode{lightningds[0]}, &clnPollableNode{lightningds[1]})

return bitcoind, liquidd, []*CLightningNodeWithLiquid{{lightningds[0]}, {lightningds[1]}}, scid
}
48 changes: 48 additions & 0 deletions testframework/electrs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package testframework

import (
"context"
"fmt"
"net/url"

"github.com/checksum0/go-electrum/electrum"
)

type Electrs struct {
Process *DaemonProcess
rpcURL *url.URL
}

func NewElectrs(testDir string, id int, elements *LiquidNode) (*Electrs, error) {
rpcPort, err := GetFreePort()
if err != nil {
return nil, err
}
u, err := url.Parse(fmt.Sprintf("127.0.0.1:%d", rpcPort))
if err != nil {
return nil, err
}
cmdLine := []string{
"electrs",
"-v",
"--network=liquidregtest",
fmt.Sprintf("daemon-rpc-addr=%s:%d", elements.rpcHost, elements.rpcPort),
fmt.Sprintf("electrum-rpc-addr=:%s", u.String()),
fmt.Sprintf("cookie=%s", elements.RpcUser+":"+elements.RpcPassword),
fmt.Sprintf("daemon-dir=%s", elements.DataDir),
"- --jsonrpc-import",
}
return &Electrs{
Process: NewDaemonProcess(cmdLine, fmt.Sprintf("electrs-%d", id)),
rpcURL: u,
}, nil
}

func (e *Electrs) Run(ctx context.Context) error {
e.Process.Run()
ec, err := electrum.NewClientTCP(ctx, e.rpcURL.String())
if err != nil {
return err
}
return ec.Ping(ctx)
}
Loading

0 comments on commit 61113a6

Please sign in to comment.