verify validity before open JIT channel

.
This commit is contained in:
Jesse de Wit
2023-05-11 15:26:27 +02:00
parent d76b79e0d7
commit 4379dee7c8
3 changed files with 47 additions and 7 deletions

View File

@@ -9,6 +9,7 @@ import (
"math/big" "math/big"
"time" "time"
"github.com/breez/lspd/basetypes"
"github.com/breez/lspd/chain" "github.com/breez/lspd/chain"
"github.com/breez/lspd/config" "github.com/breez/lspd/config"
"github.com/breez/lspd/lightning" "github.com/breez/lspd/lightning"
@@ -75,7 +76,7 @@ func NewInterceptor(
func (i *Interceptor) Intercept(nextHop string, reqPaymentHash []byte, reqOutgoingAmountMsat uint64, reqOutgoingExpiry uint32, reqIncomingExpiry uint32) InterceptResult { func (i *Interceptor) Intercept(nextHop string, reqPaymentHash []byte, reqOutgoingAmountMsat uint64, reqOutgoingExpiry uint32, reqIncomingExpiry uint32) InterceptResult {
reqPaymentHashStr := hex.EncodeToString(reqPaymentHash) reqPaymentHashStr := hex.EncodeToString(reqPaymentHash)
resp, _, _ := i.payHashGroup.Do(reqPaymentHashStr, func() (interface{}, error) { resp, _, _ := i.payHashGroup.Do(reqPaymentHashStr, func() (interface{}, error) {
paymentHash, paymentSecret, destination, incomingAmountMsat, outgoingAmountMsat, channelPoint, err := i.store.PaymentInfo(reqPaymentHash) params, paymentHash, paymentSecret, destination, incomingAmountMsat, outgoingAmountMsat, channelPoint, err := i.store.PaymentInfo(reqPaymentHash)
if err != nil { if err != nil {
log.Printf("paymentInfo(%x) error: %v", reqPaymentHash, err) log.Printf("paymentInfo(%x) error: %v", reqPaymentHash, err)
return InterceptResult{ return InterceptResult{
@@ -93,6 +94,18 @@ func (i *Interceptor) Intercept(nextHop string, reqPaymentHash []byte, reqOutgoi
if channelPoint == nil { if channelPoint == nil {
if bytes.Equal(paymentHash, reqPaymentHash) { if bytes.Equal(paymentHash, reqPaymentHash) {
// TODO: When opening_fee_params is enforced, turn this check in a temporary channel failure.
if params == nil {
log.Printf("DEPRECATED: Intercepted htlc with deprecated fee mechanism.")
params = &OpeningFeeParams{
MinMsat: uint64(i.config.ChannelMinimumFeeMsat),
Proportional: uint32(i.config.ChannelFeePermyriad * 100),
ValidUntil: time.Now().UTC().Add(time.Duration(time.Hour * 24)).Format(basetypes.TIME_FORMAT),
MaxIdleTime: uint32(i.config.MaxInactiveDuration / 600),
MaxClientToSelfDelay: uint32(i.config.MaxClientToSelfDelay),
}
}
if int64(reqIncomingExpiry)-int64(reqOutgoingExpiry) < int64(i.config.TimeLockDelta) { if int64(reqIncomingExpiry)-int64(reqOutgoingExpiry) < int64(i.config.TimeLockDelta) {
return InterceptResult{ return InterceptResult{
Action: INTERCEPT_FAIL_HTLC_WITH_CODE, Action: INTERCEPT_FAIL_HTLC_WITH_CODE,
@@ -100,6 +113,23 @@ func (i *Interceptor) Intercept(nextHop string, reqPaymentHash []byte, reqOutgoi
}, nil }, nil
} }
validUntil, err := time.Parse(basetypes.TIME_FORMAT, params.ValidUntil)
if err != nil {
log.Printf("time.Parse(%s, %s) failed. Failing channel open: %v", basetypes.TIME_FORMAT, params.ValidUntil, err)
return InterceptResult{
Action: INTERCEPT_FAIL_HTLC_WITH_CODE,
FailureCode: FAILURE_TEMPORARY_CHANNEL_FAILURE,
}, nil
}
if time.Now().UTC().After(validUntil) {
log.Printf("Intercepted expired payment registration. Failing payment. payment hash: %x, valid until: %s", paymentHash, params.ValidUntil)
return InterceptResult{
Action: INTERCEPT_FAIL_HTLC_WITH_CODE,
FailureCode: FAILURE_TEMPORARY_CHANNEL_FAILURE,
}, nil
}
channelPoint, err = i.openChannel(reqPaymentHash, destination, incomingAmountMsat) channelPoint, err = i.openChannel(reqPaymentHash, destination, incomingAmountMsat)
if err != nil { if err != nil {
log.Printf("openChannel(%x, %v) err: %v", destination, incomingAmountMsat, err) log.Printf("openChannel(%x, %v) err: %v", destination, incomingAmountMsat, err)

View File

@@ -16,7 +16,7 @@ type OpeningFeeParams struct {
} }
type InterceptStore interface { type InterceptStore interface {
PaymentInfo(htlcPaymentHash []byte) ([]byte, []byte, []byte, int64, int64, *wire.OutPoint, error) PaymentInfo(htlcPaymentHash []byte) (*OpeningFeeParams, []byte, []byte, []byte, int64, int64, *wire.OutPoint, error)
SetFundingTx(paymentHash []byte, channelPoint *wire.OutPoint) error SetFundingTx(paymentHash []byte, channelPoint *wire.OutPoint) error
RegisterPayment(params *OpeningFeeParams, destination, paymentHash, paymentSecret []byte, incomingAmountMsat, outgoingAmountMsat int64, tag string) error RegisterPayment(params *OpeningFeeParams, destination, paymentHash, paymentSecret []byte, incomingAmountMsat, outgoingAmountMsat int64, tag string) error
InsertChannel(initialChanID, confirmedChanId uint64, channelPoint string, nodeID []byte, lastUpdate time.Time) error InsertChannel(initialChanID, confirmedChanId uint64, channelPoint string, nodeID []byte, lastUpdate time.Time) error

View File

@@ -23,23 +23,24 @@ func NewPostgresInterceptStore(pool *pgxpool.Pool) *PostgresInterceptStore {
return &PostgresInterceptStore{pool: pool} return &PostgresInterceptStore{pool: pool}
} }
func (s *PostgresInterceptStore) PaymentInfo(htlcPaymentHash []byte) ([]byte, []byte, []byte, int64, int64, *wire.OutPoint, error) { func (s *PostgresInterceptStore) PaymentInfo(htlcPaymentHash []byte) (*interceptor.OpeningFeeParams, []byte, []byte, []byte, int64, int64, *wire.OutPoint, error) {
var ( var (
p *string
paymentHash, paymentSecret, destination []byte paymentHash, paymentSecret, destination []byte
incomingAmountMsat, outgoingAmountMsat int64 incomingAmountMsat, outgoingAmountMsat int64
fundingTxID []byte fundingTxID []byte
fundingTxOutnum pgtype.Int4 fundingTxOutnum pgtype.Int4
) )
err := s.pool.QueryRow(context.Background(), err := s.pool.QueryRow(context.Background(),
`SELECT payment_hash, payment_secret, destination, incoming_amount_msat, outgoing_amount_msat, funding_tx_id, funding_tx_outnum `SELECT payment_hash, payment_secret, destination, incoming_amount_msat, outgoing_amount_msat, funding_tx_id, funding_tx_outnum, opening_fee_params
FROM payments FROM payments
WHERE payment_hash=$1 OR sha256('probing-01:' || payment_hash)=$1`, WHERE payment_hash=$1 OR sha256('probing-01:' || payment_hash)=$1`,
htlcPaymentHash).Scan(&paymentHash, &paymentSecret, &destination, &incomingAmountMsat, &outgoingAmountMsat, &fundingTxID, &fundingTxOutnum) htlcPaymentHash).Scan(&paymentHash, &paymentSecret, &destination, &incomingAmountMsat, &outgoingAmountMsat, &fundingTxID, &fundingTxOutnum, &p)
if err != nil { if err != nil {
if err == pgx.ErrNoRows { if err == pgx.ErrNoRows {
err = nil err = nil
} }
return nil, nil, nil, 0, 0, nil, err return nil, nil, nil, nil, 0, 0, nil, err
} }
var cp *wire.OutPoint var cp *wire.OutPoint
@@ -49,7 +50,16 @@ func (s *PostgresInterceptStore) PaymentInfo(htlcPaymentHash []byte) ([]byte, []
log.Printf("invalid funding txid in database %x", fundingTxID) log.Printf("invalid funding txid in database %x", fundingTxID)
} }
} }
return paymentHash, paymentSecret, destination, incomingAmountMsat, outgoingAmountMsat, cp, nil
var params *interceptor.OpeningFeeParams
if p != nil {
err = json.Unmarshal([]byte(*p), &params)
if err != nil {
log.Printf("Failed to unmarshal OpeningFeeParams '%s': %v", *p, err)
return nil, nil, nil, nil, 0, 0, nil, err
}
}
return params, paymentHash, paymentSecret, destination, incomingAmountMsat, outgoingAmountMsat, cp, nil
} }
func (s *PostgresInterceptStore) SetFundingTx(paymentHash []byte, channelPoint *wire.OutPoint) error { func (s *PostgresInterceptStore) SetFundingTx(paymentHash []byte, channelPoint *wire.OutPoint) error {