make mempool fee estimation optional

This commit is contained in:
Jesse de Wit
2024-02-02 12:40:43 +01:00
parent b5276d4b53
commit 95ecf1abe9
6 changed files with 83 additions and 59 deletions

View File

@@ -0,0 +1,22 @@
package chain
import "context"
type DefaultFeeEstimator struct {
targetConf uint32
}
func NewDefaultFeeEstimator(targetConf uint32) *DefaultFeeEstimator {
return &DefaultFeeEstimator{
targetConf: targetConf,
}
}
func (e *DefaultFeeEstimator) EstimateFeeRate(
context.Context,
FeeStrategy,
) (*FeeEstimation, error) {
return &FeeEstimation{
TargetConf: &e.targetConf,
}, nil
}

View File

@@ -1,6 +1,9 @@
package chain package chain
import "context" import (
"context"
"fmt"
)
type FeeStrategy int type FeeStrategy int
@@ -13,7 +16,20 @@ const (
) )
type FeeEstimation struct { type FeeEstimation struct {
SatPerVByte float64 SatPerVByte *float64
TargetConf *uint32
}
func (f *FeeEstimation) String() string {
feeStr := "<nil>"
confStr := "<nil>"
if f.SatPerVByte != nil {
feeStr = fmt.Sprintf("%.5f", *f.SatPerVByte)
}
if f.TargetConf != nil {
confStr = fmt.Sprintf("%v", *f.TargetConf)
}
return fmt.Sprintf("satPerVbyte %s, targetConf %s", feeStr, confStr)
} }
type FeeEstimator interface { type FeeEstimator interface {

View File

@@ -4,7 +4,6 @@ import (
"bytes" "bytes"
"context" "context"
"encoding/hex" "encoding/hex"
"fmt"
"log" "log"
"math/big" "math/big"
"time" "time"
@@ -354,32 +353,23 @@ func (i *Interceptor) openChannel(paymentHash, destination []byte, incomingAmoun
capacity++ capacity++
} }
var targetConf *uint32
confStr := "<nil>"
var feeEstimation *float64
feeStr := "<nil>"
if i.feeEstimator != nil {
fee, err := i.feeEstimator.EstimateFeeRate( fee, err := i.feeEstimator.EstimateFeeRate(
context.Background(), context.Background(),
i.feeStrategy, i.feeStrategy,
) )
if err == nil { if err != nil || fee == nil {
feeEstimation = &fee.SatPerVByte
feeStr = fmt.Sprintf("%.5f", *feeEstimation)
} else {
log.Printf("Error estimating chain fee, fallback to target conf: %v", err) log.Printf("Error estimating chain fee, fallback to target conf: %v", err)
targetConf = &i.config.TargetConf fee = &chain.FeeEstimation{
confStr = fmt.Sprintf("%v", *targetConf) TargetConf: &i.config.TargetConf,
} }
} }
log.Printf( log.Printf(
"Opening zero conf channel. Paymenthash: %x, Destination: %x, capacity: %v, fee: %s, targetConf: %s", "Opening zero conf channel. Paymenthash: %x, Destination: %x, capacity: %v, fee: %s",
paymentHash, paymentHash,
destination, destination,
capacity, capacity,
feeStr, fee.String(),
confStr,
) )
channelPoint, err := i.client.OpenChannel(&lightning.OpenChannelRequest{ channelPoint, err := i.client.OpenChannel(&lightning.OpenChannelRequest{
Destination: destination, Destination: destination,
@@ -387,8 +377,8 @@ func (i *Interceptor) openChannel(paymentHash, destination []byte, incomingAmoun
MinConfs: i.config.MinConfs, MinConfs: i.config.MinConfs,
IsPrivate: true, IsPrivate: true,
IsZeroConf: true, IsZeroConf: true,
FeeSatPerVByte: feeEstimation, FeeSatPerVByte: fee.SatPerVByte,
TargetConf: targetConf, TargetConf: fee.TargetConf,
}) })
if err != nil { if err != nil {
log.Printf("paymenthash %x, client.OpenChannelSync(%x, %v) error: %v", paymentHash, destination, capacity, err) log.Printf("paymenthash %x, client.OpenChannelSync(%x, %v) error: %v", paymentHash, destination, capacity, err)

View File

@@ -3,7 +3,6 @@ package lsps2
import ( import (
"context" "context"
"encoding/hex" "encoding/hex"
"fmt"
"log" "log"
"math" "math"
"strings" "strings"
@@ -414,23 +413,14 @@ func (i *Interceptor) ensureChannelOpen(payment *paymentState) {
return return
} }
var targetConf *uint32
confStr := "<nil>"
var feeEstimation *float64
feeStr := "<nil>"
if i.feeEstimator != nil {
fee, err := i.feeEstimator.EstimateFeeRate( fee, err := i.feeEstimator.EstimateFeeRate(
context.Background(), context.Background(),
i.config.FeeStrategy, i.config.FeeStrategy,
) )
if err == nil { if err != nil || fee == nil {
feeEstimation = &fee.SatPerVByte log.Printf("Error estimating chain fee, fallback to target conf: %v", err)
feeStr = fmt.Sprintf("%.5f", *feeEstimation) fee = &chain.FeeEstimation{
} else { TargetConf: &i.config.TargetConf,
log.Printf("Error estimating chain fee, fallback to target "+
"conf: %v", err)
targetConf = &i.config.TargetConf
confStr = fmt.Sprintf("%v", *targetConf)
} }
} }
@@ -439,11 +429,10 @@ func (i *Interceptor) ensureChannelOpen(payment *paymentState) {
log.Printf( log.Printf(
"LSPS2: Opening zero conf channel. Destination: %x, capacity: %v, "+ "LSPS2: Opening zero conf channel. Destination: %x, capacity: %v, "+
"fee: %s, targetConf: %s", "fee: %s",
destination, destination,
capacity, capacity,
feeStr, fee.String(),
confStr,
) )
channelPoint, err := i.client.OpenChannel(&lightning.OpenChannelRequest{ channelPoint, err := i.client.OpenChannel(&lightning.OpenChannelRequest{
@@ -452,8 +441,8 @@ func (i *Interceptor) ensureChannelOpen(payment *paymentState) {
MinConfs: i.config.MinConfs, MinConfs: i.config.MinConfs,
IsPrivate: true, IsPrivate: true,
IsZeroConf: true, IsZeroConf: true,
FeeSatPerVByte: feeEstimation, FeeSatPerVByte: fee.SatPerVByte,
TargetConf: targetConf, TargetConf: fee.TargetConf,
}) })
if err != nil { if err != nil {
log.Printf( log.Printf(

27
main.go
View File

@@ -59,16 +59,6 @@ func main() {
log.Fatalf("failed to create nodes service: %v", err) log.Fatalf("failed to create nodes service: %v", err)
} }
mempoolUrl := os.Getenv("MEMPOOL_API_BASE_URL")
if mempoolUrl == "" {
log.Fatalf("No mempool url configured.")
}
feeEstimator, err := mempool.NewMempoolClient(mempoolUrl)
if err != nil {
log.Fatalf("failed to initialize mempool client: %v", err)
}
var feeStrategy chain.FeeStrategy var feeStrategy chain.FeeStrategy
envFeeStrategy := os.Getenv("MEMPOOL_PRIORITY") envFeeStrategy := os.Getenv("MEMPOOL_PRIORITY")
switch strings.ToLower(envFeeStrategy) { switch strings.ToLower(envFeeStrategy) {
@@ -85,7 +75,17 @@ func main() {
default: default:
feeStrategy = chain.FeeStrategyEconomy feeStrategy = chain.FeeStrategyEconomy
} }
var mempoolClient *mempool.MempoolClient
mempoolUrl := os.Getenv("MEMPOOL_API_BASE_URL")
if mempoolUrl != "" {
mempoolClient, err = mempool.NewMempoolClient(mempoolUrl)
if err != nil {
log.Fatalf("failed to initialize mempool client: %v", err)
}
log.Printf("using mempool api for fee estimation: %v, fee strategy: %v:%v", mempoolUrl, envFeeStrategy, feeStrategy) log.Printf("using mempool api for fee estimation: %v, fee strategy: %v:%v", mempoolUrl, envFeeStrategy, feeStrategy)
}
databaseUrl := os.Getenv("DATABASE_URL") databaseUrl := os.Getenv("DATABASE_URL")
pool, err := postgresql.PgConnect(databaseUrl) pool, err := postgresql.PgConnect(databaseUrl)
@@ -111,6 +111,13 @@ func main() {
var interceptors []interceptor.HtlcInterceptor var interceptors []interceptor.HtlcInterceptor
for _, node := range nodes { for _, node := range nodes {
var htlcInterceptor interceptor.HtlcInterceptor var htlcInterceptor interceptor.HtlcInterceptor
var feeEstimator chain.FeeEstimator
if mempoolClient == nil {
feeEstimator = chain.NewDefaultFeeEstimator(node.NodeConfig.TargetConf)
} else {
feeEstimator = mempoolClient
}
if node.NodeConfig.Lnd != nil { if node.NodeConfig.Lnd != nil {
client, err := lnd.NewLndClient(node.NodeConfig.Lnd) client, err := lnd.NewLndClient(node.NodeConfig.Lnd)
if err != nil { if err != nil {

View File

@@ -85,6 +85,6 @@ func (m *MempoolClient) EstimateFeeRate(
} }
return &chain.FeeEstimation{ return &chain.FeeEstimation{
SatPerVByte: rate, SatPerVByte: &rate,
}, nil }, nil
} }