diff --git a/config.go b/config.go index 7855caf..1430cf6 100644 --- a/config.go +++ b/config.go @@ -33,6 +33,10 @@ type NodeConfig struct { // Number of blocks after which an opened channel is considered confirmed. TargetConf uint32 `json:"targetConf,string"` + // Minimum number of confirmations inputs for zero conf channel opens should + // have. + MinConfs uint32 `json:"minConfs,string"` + // Smallest htlc amount routed over channels opened with the OpenChannel // rpc call. MinHtlcMsat uint64 `json:"minHtlcMsat,string"` diff --git a/intercept.go b/intercept.go index 1e9dbff..dea1aa7 100644 --- a/intercept.go +++ b/intercept.go @@ -37,6 +37,7 @@ var ( var payHashGroup singleflight.Group var feeEstimator chain.FeeEstimator +var feeStrategy chain.FeeStrategy type interceptResult struct { action interceptAction @@ -247,7 +248,7 @@ func openChannel(client LightningClient, config *NodeConfig, paymentHash, destin if feeEstimator != nil { fee, err := feeEstimator.EstimateFeeRate( context.Background(), - chain.FeeStrategyMinimum, + feeStrategy, ) if err == nil { feeEstimation = &fee.SatPerVByte @@ -269,7 +270,7 @@ func openChannel(client LightningClient, config *NodeConfig, paymentHash, destin channelPoint, err := client.OpenChannel(&OpenChannelRequest{ Destination: destination, CapacitySat: uint64(capacity), - MinConfs: 6, + MinConfs: config.MinConfs, IsPrivate: true, IsZeroConf: true, FeeSatPerVByte: feeEstimation, diff --git a/itest/lspd_node.go b/itest/lspd_node.go index 2749094..abfab8b 100644 --- a/itest/lspd_node.go +++ b/itest/lspd_node.go @@ -99,7 +99,7 @@ func newLspd(h *lntest.TestHarness, name string, lnd *string, cln *string, envEx nodes := fmt.Sprintf( `NODES='[ { "name": "%s", "lspdPrivateKey": "%x", "token": "hello", "host": "host:port",`+ ` "publicChannelAmount": "1000183", "channelAmount": "100000", "channelPrivate": false,`+ - ` "targetConf": "6", "minHtlcMsat": "600", "baseFeeMsat": "1000", "feeRate": "0.000001",`+ + ` "targetConf": "6", "minConfs": "1", "minHtlcMsat": "600", "baseFeeMsat": "1000", "feeRate": "0.000001",`+ ` "timeLockDelta": "144", "channelFeePermyriad": "40", "channelMinimumFeeMsat": "2000000",`+ ` "additionalChannelCapacity": "100000", "maxInactiveDuration": "3888000", %s}]'`, name, @@ -112,6 +112,7 @@ func newLspd(h *lntest.TestHarness, name string, lnd *string, cln *string, envEx fmt.Sprintf("LISTEN_ADDRESS=%s", grpcAddress), fmt.Sprintf("USE_MEMPOOL_FEE_ESTIMATION=true"), fmt.Sprintf("MEMPOOL_API_BASE_URL=https://mempool.space/api/v1/"), + fmt.Sprintf("MEMPOOL_PRIORITY=economy"), } env = append(env, envExt...) diff --git a/main.go b/main.go index e55c4f3..975cff3 100644 --- a/main.go +++ b/main.go @@ -6,9 +6,11 @@ import ( "log" "os" "os/signal" + "strings" "sync" "syscall" + "github.com/breez/lspd/chain" "github.com/breez/lspd/mempool" "github.com/btcsuite/btcd/btcec/v2" ) @@ -42,7 +44,22 @@ func main() { log.Fatalf("failed to initialize mempool client: %v", err) } - log.Printf("using mempool api for fee estimation: %v", mempoolUrl) + envFeeStrategy := os.Getenv("MEMPOOL_PRIORITY") + switch strings.ToLower(envFeeStrategy) { + case "minimum": + feeStrategy = chain.FeeStrategyMinimum + case "economy": + feeStrategy = chain.FeeStrategyEconomy + case "hour": + feeStrategy = chain.FeeStrategyHour + case "halfhour": + feeStrategy = chain.FeeStrategyHalfHour + case "fastest": + feeStrategy = chain.FeeStrategyFastest + default: + feeStrategy = chain.FeeStrategyEconomy + } + log.Printf("using mempool api for fee estimation: %v, fee strategy: %v:%v", mempoolUrl, envFeeStrategy, feeStrategy) } var interceptors []HtlcInterceptor diff --git a/sample.env b/sample.env index 4a2d7ad..f266c14 100644 --- a/sample.env +++ b/sample.env @@ -36,6 +36,11 @@ CHANNELMISMATCH_NOTIFICATION_FROM="Name4 " USE_MEMPOOL_FEE_ESTIMATION=true MEMPOOL_API_BASE_URL=https://mempool.space/api/v1/ +# Priority to use for opening channels when using the mempool api. +# Valid options are: fastest, halfhour, hour, economy, minimum +# Defaults to economy +MEMPOOL_PRIORITY=economy + # lspd can be connected to multiple nodes at once. The NODES variable takes an # array of nodes. Each node is either a cln or an lnd node and should have the # corresponding "cln" or "lnd" key set. @@ -53,4 +58,4 @@ MEMPOOL_API_BASE_URL=https://mempool.space/api/v1/ # from the app to lspd. # # For other specific settings see the fields in `config.go` NodeConfig struct. -NODES='[ { "name": "", "nodePubkey": "", "lspdPrivateKey": "", "token": "", "host": "", "publicChannelAmount": "1000183", "channelAmount": "100000", "channelPrivate": false, "targetConf": "6", "minHtlcMsat": "600", "baseFeeMsat": "1000", "feeRate": "0.000001", "timeLockDelta": "144", "channelFeePermyriad": "40", "channelMinimumFeeMsat": "2000000", "additionalChannelCapacity": "100000", "maxInactiveDuration": "3888000", "lnd": { "address": "", "cert": "", "macaroon": "" } }, { "name": "", "nodePubkey": "", "lspdPrivateKey": "", "token": "", "host": "", "publicChannelAmount": "1000183", "channelAmount": "100000", "channelPrivate": false, "targetConf": "6", "minHtlcMsat": "600", "baseFeeMsat": "1000", "feeRate": "0.000001", "timeLockDelta": "144", "channelFeePermyriad": "40", "channelMinimumFeeMsat": "2000000", "additionalChannelCapacity": "100000", "maxInactiveDuration": "3888000", "cln": { "pluginAddress": "
", "socketPath": "" } } ]' +NODES='[ { "name": "", "nodePubkey": "", "lspdPrivateKey": "", "token": "", "host": "", "publicChannelAmount": "1000183", "channelAmount": "100000", "channelPrivate": false, "targetConf": "6", "minConfs": "6", "minHtlcMsat": "600", "baseFeeMsat": "1000", "feeRate": "0.000001", "timeLockDelta": "144", "channelFeePermyriad": "40", "channelMinimumFeeMsat": "2000000", "additionalChannelCapacity": "100000", "maxInactiveDuration": "3888000", "lnd": { "address": "", "cert": "", "macaroon": "" } }, { "name": "", "nodePubkey": "", "lspdPrivateKey": "", "token": "", "host": "", "publicChannelAmount": "1000183", "channelAmount": "100000", "channelPrivate": false, "targetConf": "6", "minConfs": "6", "minHtlcMsat": "600", "baseFeeMsat": "1000", "feeRate": "0.000001", "timeLockDelta": "144", "channelFeePermyriad": "40", "channelMinimumFeeMsat": "2000000", "additionalChannelCapacity": "100000", "maxInactiveDuration": "3888000", "cln": { "pluginAddress": "
", "socketPath": "" } } ]'