Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement LSPS2 for LND #149

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/integration_tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
pull_request:
env:
BITCOIN_VERSION: '25.0'
LSP_REF: 'breez-node-v0.17.2-beta'
LSP_REF: 'unencrypted-failure-messages'
CLIENT_REF: 'v0.16.4-breez-3'
GO_VERSION: '^1.19'
CLN_VERSION: 'v23.11'
Expand Down Expand Up @@ -158,6 +158,7 @@ jobs:
testLsps2ZeroConfUtxo
]
lsp: [
LND,
CLN
]
client: [
Expand Down
6 changes: 4 additions & 2 deletions cln/cln_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"sync"
"time"

"github.com/breez/lspd/common"
"github.com/breez/lspd/lightning"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
Expand Down Expand Up @@ -88,8 +89,9 @@ func (c *ClnClient) GetInfo() (*lightning.GetInfoResult, error) {
}

return &lightning.GetInfoResult{
Alias: info.Alias,
Pubkey: info.Id,
ChainHash: common.MapChainHash(info.Network),
Alias: info.Alias,
Pubkey: info.Id,
}, nil
}

Expand Down
32 changes: 6 additions & 26 deletions cln/cln_interceptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ func (i *ClnHtlcInterceptor) intercept() error {
interceptorClient.Send(i.resumeWithOnion(request, interceptResult))
case common.INTERCEPT_FAIL_HTLC_WITH_CODE:
interceptorClient.Send(
i.failWithCode(request, interceptResult.FailureCode),
i.failWithMessage(request, interceptResult.FailureMessage),
)
case common.INTERCEPT_IGNORE:
// Do nothing
Expand Down Expand Up @@ -202,12 +202,12 @@ func (i *ClnHtlcInterceptor) resumeWithOnion(request *proto.HtlcAccepted, interc
payload, err := hex.DecodeString(request.Onion.Payload)
if err != nil {
log.Printf("paymenthash: %s, resumeWithOnion: hex.DecodeString(%v) error: %v", request.Htlc.PaymentHash, request.Onion.Payload, err)
return i.failWithCode(request, common.FAILURE_TEMPORARY_CHANNEL_FAILURE)
return i.failWithMessage(request, common.FAILURE_TEMPORARY_CHANNEL_FAILURE)
}
newPayload, err := encodePayloadWithNextHop(payload, interceptResult.Scid, interceptResult.AmountMsat, interceptResult.FeeMsat)
if err != nil {
log.Printf("paymenthash: %s, encodePayloadWithNextHop error: %v", request.Htlc.PaymentHash, err)
return i.failWithCode(request, common.FAILURE_TEMPORARY_CHANNEL_FAILURE)
return i.failWithMessage(request, common.FAILURE_TEMPORARY_CHANNEL_FAILURE)
}

newPayloadStr := hex.EncodeToString(newPayload)
Expand All @@ -234,14 +234,14 @@ func (i *ClnHtlcInterceptor) defaultResolution(request *proto.HtlcAccepted) *pro
}
}

func (i *ClnHtlcInterceptor) failWithCode(request *proto.HtlcAccepted, code common.InterceptFailureCode) *proto.HtlcResolution {
log.Printf("paymenthash: %s, failing htlc with code: '%x'", request.Htlc.PaymentHash, code)
func (i *ClnHtlcInterceptor) failWithMessage(request *proto.HtlcAccepted, message []byte) *proto.HtlcResolution {
log.Printf("paymenthash: %s, failing htlc with message '%x'", request.Htlc.PaymentHash, message)
return &proto.HtlcResolution{
Correlationid: request.Correlationid,
Outcome: &proto.HtlcResolution_Fail{
Fail: &proto.HtlcFail{
Failure: &proto.HtlcFail_FailureMessage{
FailureMessage: i.mapFailureCode(code),
FailureMessage: hex.EncodeToString(message),
},
},
},
Expand Down Expand Up @@ -305,23 +305,3 @@ func encodePayloadWithNextHop(payload []byte, scid lightning.ShortChannelID, amo
}
return newPayloadBuf.Bytes(), nil
}

func (i *ClnHtlcInterceptor) mapFailureCode(original common.InterceptFailureCode) string {
switch original {
case common.FAILURE_TEMPORARY_CHANNEL_FAILURE:
return "1007"
case common.FAILURE_AMOUNT_BELOW_MINIMUM:
return "100B"
case common.FAILURE_INCORRECT_CLTV_EXPIRY:
return "100D"
case common.FAILURE_TEMPORARY_NODE_FAILURE:
return "2002"
case common.FAILURE_UNKNOWN_NEXT_PEER:
return "400A"
case common.FAILURE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS:
return "400F"
default:
log.Printf("Unknown failure code %v, default to temporary channel failure.", original)
return "1007" // temporary channel failure
}
}
19 changes: 19 additions & 0 deletions common/chain_hash.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package common

import (
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/chaincfg/chainhash"
)

func MapChainHash(network string) *chainhash.Hash {
switch network {
case "bitcoin":
return chaincfg.MainNetParams.GenesisHash
case "testnet":
return chaincfg.TestNet3Params.GenesisHash
case "regtest":
return chaincfg.RegressionNetParams.GenesisHash
default:
return chaincfg.MainNetParams.GenesisHash
}
}
38 changes: 38 additions & 0 deletions common/chan_update.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package common

import (
"bytes"
"time"

"github.com/breez/lspd/lightning"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/lightningnetwork/lnd/lnwire"
)

func ConstructChanUpdate(
chainhash chainhash.Hash,
node []byte,
destination []byte,
scid lightning.ShortChannelID,
timeLockDelta uint16,
htlcMinimumMsat,
htlcMaximumMsat uint64,
) lnwire.ChannelUpdate {
channelFlags := lnwire.ChanUpdateChanFlags(0)
if bytes.Compare(node, destination) > 0 {
channelFlags = 1
}

return lnwire.ChannelUpdate{
ChainHash: chainhash,
ShortChannelID: scid.ToLnwire(),
Timestamp: uint32(time.Now().Unix()),
TimeLockDelta: timeLockDelta,
HtlcMinimumMsat: lnwire.MilliSatoshi(htlcMinimumMsat),
HtlcMaximumMsat: lnwire.MilliSatoshi(htlcMaximumMsat),
BaseFee: 0,
FeeRate: 0,
MessageFlags: lnwire.ChanUpdateRequiredMaxHtlc,
ChannelFlags: channelFlags,
}
}
43 changes: 35 additions & 8 deletions common/intercept_handler.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package common

import (
"bytes"
"fmt"
"log"

"github.com/breez/lspd/lightning"
"github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/lnwire"
)

type InterceptAction int
Expand All @@ -16,17 +19,41 @@ const (
INTERCEPT_IGNORE InterceptAction = 3
)

type InterceptFailureCode uint16
type InterceptFailureCode []byte

var (
FAILURE_TEMPORARY_CHANNEL_FAILURE InterceptFailureCode = 0x1007
FAILURE_AMOUNT_BELOW_MINIMUM InterceptFailureCode = 0x100B
FAILURE_INCORRECT_CLTV_EXPIRY InterceptFailureCode = 0x100D
FAILURE_TEMPORARY_NODE_FAILURE InterceptFailureCode = 0x2002
FAILURE_UNKNOWN_NEXT_PEER InterceptFailureCode = 0x400A
FAILURE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS InterceptFailureCode = 0x400F
FAILURE_TEMPORARY_CHANNEL_FAILURE InterceptFailureCode = []byte{0x10, 0x07}
FAILURE_AMOUNT_BELOW_MINIMUM InterceptFailureCode = []byte{0x10, 0x0B}
FAILURE_INCORRECT_CLTV_EXPIRY InterceptFailureCode = []byte{0x10, 0x0D}
FAILURE_TEMPORARY_NODE_FAILURE InterceptFailureCode = []byte{0x20, 0x02}
FAILURE_UNKNOWN_NEXT_PEER InterceptFailureCode = []byte{0x40, 0x0A}
FAILURE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS InterceptFailureCode = []byte{0x40, 0x0F}
)

func FailureTemporaryChannelFailure(update *lnwire.ChannelUpdate) []byte {
var buf bytes.Buffer
msg := lnwire.NewTemporaryChannelFailure(update)
err := lnwire.EncodeFailureMessage(&buf, msg, 0)
if err != nil {
log.Printf("Failed to encode failure message for temporary channel failure: %v", err)
return FAILURE_TEMPORARY_CHANNEL_FAILURE
}

return buf.Bytes()
}

func FailureIncorrectCltvExpiry(cltvExpiry uint32, update lnwire.ChannelUpdate) []byte {
var buf bytes.Buffer
msg := lnwire.NewIncorrectCltvExpiry(cltvExpiry, update)
err := lnwire.EncodeFailureMessage(&buf, msg, 0)
if err != nil {
log.Printf("Failed to encode failure message for incorrect cltv expiry: %v", err)
return FAILURE_INCORRECT_CLTV_EXPIRY
}

return buf.Bytes()
}

type InterceptRequest struct {
// Identifier that uniquely identifies this htlc.
// For cln, that's hash of the next onion or the shared secret.
Expand All @@ -49,7 +76,7 @@ func (r *InterceptRequest) HtlcId() string {

type InterceptResult struct {
Action InterceptAction
FailureCode InterceptFailureCode
FailureMessage []byte
Destination []byte
AmountMsat uint64
FeeMsat *uint64
Expand Down
3 changes: 3 additions & 0 deletions common/nodes_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ import (
"github.com/breez/lspd/config"
"github.com/breez/lspd/lightning"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/chaincfg/chainhash"
ecies "github.com/ecies/go/v2"
"golang.org/x/sync/singleflight"
)

type Node struct {
NodeId []byte
ChainHash chainhash.Hash
Client lightning.Client
NodeConfig *config.NodeConfig
PrivateKey *btcec.PrivateKey
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ require (
github.com/docker/docker v20.10.24+incompatible
github.com/docker/go-connections v0.4.0
github.com/elementsproject/glightning v0.0.0-20230525134205-ef34d849f564
github.com/golang/protobuf v1.5.3
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
github.com/jackc/pgtype v1.14.0
github.com/jackc/pgx/v5 v5.4.3
Expand All @@ -38,6 +37,7 @@ require (
github.com/docker/go-units v0.5.0 // indirect
github.com/ethereum/go-ethereum v1.13.5 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgconn v1.14.0 // indirect
Expand Down Expand Up @@ -194,7 +194,7 @@ require (
sigs.k8s.io/yaml v1.2.0 // indirect
)

replace github.com/lightningnetwork/lnd v0.17.2-beta => github.com/breez/lnd v0.15.0-beta.rc6.0.20231122093500-0c939786ced7
replace github.com/lightningnetwork/lnd v0.17.2-beta => github.com/breez/lnd v0.15.0-beta.rc6.0.20240105103917-ec16df3d9d48

replace google.golang.org/protobuf => github.com/lightninglabs/protobuf-go-hex-display v1.30.0-hex-display

Expand Down
Loading
Loading