diff --git a/itest/cln_lspd_node.go b/itest/cln_lspd_node.go index 1697e26..30a9f7e 100644 --- a/itest/cln_lspd_node.go +++ b/itest/cln_lspd_node.go @@ -42,7 +42,7 @@ type clnLspNodeRuntime struct { cleanups []*lntest.Cleanup } -func NewClnLspdNode(h *lntest.TestHarness, m *lntest.Miner, name string, nodeConfig *config.NodeConfig) LspNode { +func NewClnLspdNode(h *lntest.TestHarness, m *lntest.Miner, mem *mempoolApi, name string, nodeConfig *config.NodeConfig) LspNode { scriptDir := h.GetDirectory("lspd") pluginBinary := *clnPluginExec pluginPort, err := lntest.GetPort() @@ -65,7 +65,7 @@ func NewClnLspdNode(h *lntest.TestHarness, m *lntest.Miner, name string, nodeCon PluginAddress: pluginAddress, SocketPath: filepath.Join(lightningNode.SocketDir(), lightningNode.SocketFile()), } - lspbase, err := newLspd(h, name, nodeConfig, nil, cln) + lspbase, err := newLspd(h, mem, name, nodeConfig, nil, cln) if err != nil { h.T.Fatalf("failed to initialize lspd") } diff --git a/itest/config_test.go b/itest/config_test.go index 760b89d..cf69ea8 100644 --- a/itest/config_test.go +++ b/itest/config_test.go @@ -19,7 +19,10 @@ func TestConfigParameters(t *testing.T) { m := lntest.NewMiner(h) m.Start() - lsp := NewClnLspdNode(h, m, "lsp", nil) + mem := NewMempoolApi(h) + mem.Start() + + lsp := NewClnLspdNode(h, m, mem, "lsp", nil) lsp.Start() log.Printf("Waiting %v to allow lsp server to activate.", htlcInterceptorDelay) diff --git a/itest/lnd_lspd_node.go b/itest/lnd_lspd_node.go index 9f7e0ce..4864815 100644 --- a/itest/lnd_lspd_node.go +++ b/itest/lnd_lspd_node.go @@ -38,7 +38,7 @@ type lndLspNodeRuntime struct { cleanups []*lntest.Cleanup } -func NewLndLspdNode(h *lntest.TestHarness, m *lntest.Miner, name string, nodeConfig *config.NodeConfig) LspNode { +func NewLndLspdNode(h *lntest.TestHarness, m *lntest.Miner, mem *mempoolApi, name string, nodeConfig *config.NodeConfig) LspNode { args := []string{ "--protocol.zero-conf", "--protocol.option-scid-alias", @@ -56,7 +56,7 @@ func NewLndLspdNode(h *lntest.TestHarness, m *lntest.Miner, name string, nodeCon Cert: string(lightningNode.TlsCert()), Macaroon: hex.EncodeToString(lightningNode.Macaroon()), } - lspBase, err := newLspd(h, name, nodeConfig, lnd, nil) + lspBase, err := newLspd(h, mem, name, nodeConfig, lnd, nil) if err != nil { h.T.Fatalf("failed to initialize lspd") } diff --git a/itest/lspd_node.go b/itest/lspd_node.go index e4f01b3..a4100c1 100644 --- a/itest/lspd_node.go +++ b/itest/lspd_node.go @@ -60,7 +60,7 @@ type lspBase struct { postgresBackend *PostgresContainer } -func newLspd(h *lntest.TestHarness, name string, nodeConfig *config.NodeConfig, lnd *config.LndConfig, cln *config.ClnConfig, envExt ...string) (*lspBase, error) { +func newLspd(h *lntest.TestHarness, mem *mempoolApi, name string, nodeConfig *config.NodeConfig, lnd *config.LndConfig, cln *config.ClnConfig, envExt ...string) (*lspBase, error) { scriptDir := h.GetDirectory(fmt.Sprintf("lspd-%s", name)) log.Printf("%s: Creating LSPD in dir %s", name, scriptDir) @@ -129,7 +129,7 @@ func newLspd(h *lntest.TestHarness, name string, nodeConfig *config.NodeConfig, nodes, fmt.Sprintf("DATABASE_URL=%s", postgresBackend.ConnectionString()), fmt.Sprintf("LISTEN_ADDRESS=%s", grpcAddress), - "MEMPOOL_API_BASE_URL=https://mempool.space/api/v1/", + fmt.Sprintf("MEMPOOL_API_BASE_URL=%s", mem.Address()), "MEMPOOL_PRIORITY=economy", } diff --git a/itest/lspd_test.go b/itest/lspd_test.go index 8c6c73b..e6dd3ff 100644 --- a/itest/lspd_test.go +++ b/itest/lspd_test.go @@ -18,12 +18,12 @@ func TestLspd(t *testing.T) { runTests(t, testCases, "CLN-lspd", clnLspFunc, clnClientFunc) } -func lndLspFunc(h *lntest.TestHarness, m *lntest.Miner, c *config.NodeConfig) LspNode { - return NewLndLspdNode(h, m, "lsp", c) +func lndLspFunc(h *lntest.TestHarness, m *lntest.Miner, mem *mempoolApi, c *config.NodeConfig) LspNode { + return NewLndLspdNode(h, m, mem, "lsp", c) } -func clnLspFunc(h *lntest.TestHarness, m *lntest.Miner, c *config.NodeConfig) LspNode { - return NewClnLspdNode(h, m, "lsp", c) +func clnLspFunc(h *lntest.TestHarness, m *lntest.Miner, mem *mempoolApi, c *config.NodeConfig) LspNode { + return NewClnLspdNode(h, m, mem, "lsp", c) } func lndClientFunc(h *lntest.TestHarness, m *lntest.Miner) BreezClient { @@ -72,10 +72,15 @@ func runTest( log.Printf("Creating miner") miner := lntest.NewMiner(h) miner.Start() + + log.Printf("Creating mempool api") + mem := NewMempoolApi(h) + mem.Start() + log.Printf("Creating lsp") var lsp LspNode if !testCase.skipCreateLsp { - lsp = lspFunc(h, miner, nil) + lsp = lspFunc(h, miner, mem, nil) lsp.Start() } c := clientFunc(h, miner) @@ -85,6 +90,7 @@ func runTest( t: t, h: h, m: miner, + mem: mem, c: c, lsp: lsp, lspFunc: lspFunc, diff --git a/itest/mempool_api.go b/itest/mempool_api.go new file mode 100644 index 0000000..44a5676 --- /dev/null +++ b/itest/mempool_api.go @@ -0,0 +1,85 @@ +package itest + +import ( + "encoding/json" + "fmt" + "net" + "net/http" + + "github.com/breez/lntest" +) + +type RecommendedFeesResponse struct { + FastestFee float64 `json:"fastestFee"` + HalfHourFee float64 `json:"halfHourFee"` + HourFee float64 `json:"hourFee"` + EconomyFee float64 `json:"economyFee"` + MinimumFee float64 `json:"minimumFee"` +} + +type mempoolApi struct { + addr string + h *lntest.TestHarness + fees *RecommendedFeesResponse + lis net.Listener +} + +func NewMempoolApi(h *lntest.TestHarness) *mempoolApi { + port, err := lntest.GetPort() + if err != nil { + h.T.Fatalf("Failed to get port for mempool api: %v", err) + } + + return &mempoolApi{ + addr: fmt.Sprintf("127.0.0.1:%d", port), + h: h, + fees: &RecommendedFeesResponse{ + MinimumFee: 1, + EconomyFee: 1, + HourFee: 1, + HalfHourFee: 1, + FastestFee: 1, + }, + } +} + +func (m *mempoolApi) Address() string { + return fmt.Sprintf("http://%s/api/v1/", m.addr) +} + +func (m *mempoolApi) SetFees(fees *RecommendedFeesResponse) { + m.fees = fees +} + +func (m *mempoolApi) Start() { + mux := http.NewServeMux() + mux.HandleFunc("/api/v1/fees/recommended", func(w http.ResponseWriter, r *http.Request) { + j, err := json.Marshal(m.fees) + if err != nil { + m.h.T.Fatalf("Failed to marshal mempool fees: %v", err) + } + _, err = w.Write(j) + if err != nil { + m.h.T.Fatalf("Failed to write mempool response: %v", err) + } + }) + lis, err := net.Listen("tcp", m.addr) + if err != nil { + m.h.T.Fatalf("failed to start mempool api: %v", err) + } + + m.lis = lis + m.h.AddStoppable(m) + + go http.Serve(lis, mux) +} + +func (m *mempoolApi) Stop() error { + lis := m.lis + if lis == nil { + return nil + } + + m.lis = nil + return lis.Close() +} diff --git a/itest/test_params.go b/itest/test_params.go index a3d420d..ab9b416 100644 --- a/itest/test_params.go +++ b/itest/test_params.go @@ -7,13 +7,14 @@ import ( "github.com/breez/lspd/config" ) -type LspFunc func(h *lntest.TestHarness, m *lntest.Miner, c *config.NodeConfig) LspNode +type LspFunc func(h *lntest.TestHarness, m *lntest.Miner, mem *mempoolApi, c *config.NodeConfig) LspNode type ClientFunc func(h *lntest.TestHarness, m *lntest.Miner) BreezClient type testParams struct { t *testing.T h *lntest.TestHarness m *lntest.Miner + mem *mempoolApi c BreezClient lsp LspNode lspFunc LspFunc @@ -28,6 +29,10 @@ func (h *testParams) Miner() *lntest.Miner { return h.m } +func (h *testParams) Mempool() *mempoolApi { + return h.mem +} + func (h *testParams) Lsp() LspNode { return h.lsp } diff --git a/itest/zero_conf_utxo_test.go b/itest/zero_conf_utxo_test.go index ea991fc..44ab3d1 100644 --- a/itest/zero_conf_utxo_test.go +++ b/itest/zero_conf_utxo_test.go @@ -16,7 +16,7 @@ func testOpenZeroConfUtxo(p *testParams) { alice.Fund(10000000) minConfs := uint32(0) - lsp := p.lspFunc(p.h, p.m, &config.NodeConfig{MinConfs: &minConfs}) + lsp := p.lspFunc(p.h, p.m, p.mem, &config.NodeConfig{MinConfs: &minConfs}) lsp.Start() log.Print("Opening channel between Alice and the lsp")