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

unencrypted failures #101

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
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
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ require (
github.com/lightningnetwork/lnd/kvdb v1.3.1 // indirect
github.com/lightningnetwork/lnd/ticker v1.1.0 // indirect
github.com/lightningnetwork/lnd/tlv v1.0.3 // indirect
github.com/lightningnetwork/lnd/tor v1.0.1 // indirect
github.com/lightningnetwork/lnd/tor v1.1.0 // indirect
github.com/ltcsuite/ltcd v0.20.1-beta // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
Expand Down Expand Up @@ -182,3 +182,5 @@ require (
)

replace github.com/bottlepay/lnmux/lnmuxrpc => ./lnmuxrpc

replace github.com/lightningnetwork/lnd => /users/Joost.Jager/lightninglabs/lnd
6 changes: 2 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -507,8 +507,6 @@ github.com/lightninglabs/neutrino v0.14.2 h1:yrnZUCYMZ5ECtXhgDrzqPq2oX8awoAN2D/c
github.com/lightninglabs/neutrino v0.14.2/go.mod h1:OICUeTCn+4Tu27YRJIpWvvqySxx4oH4vgdP33Sw9RDc=
github.com/lightningnetwork/lightning-onion v1.0.2-0.20220211021909-bb84a1ccb0c5 h1:TkKwqFcQTGYoI+VEqyxA8rxpCin8qDaYX0AfVRinT3k=
github.com/lightningnetwork/lightning-onion v1.0.2-0.20220211021909-bb84a1ccb0c5/go.mod h1:7dDx73ApjEZA0kcknI799m2O5kkpfg4/gr7N092ojNo=
github.com/lightningnetwork/lnd v0.15.4-beta h1:vO+UZjuA8RqJdDlfwQeS0h2PCocYwwqv5HkX2IXf5/M=
github.com/lightningnetwork/lnd v0.15.4-beta/go.mod h1:6aoOkifcI9tuk8UV5l2rVZSq0681obuP4zvfK+2ZrT0=
github.com/lightningnetwork/lnd/clock v1.0.1/go.mod h1:KnQudQ6w0IAMZi1SgvecLZQZ43ra2vpDNj7H/aasemg=
github.com/lightningnetwork/lnd/clock v1.1.0 h1:/yfVAwtPmdx45aQBoXQImeY7sOIEr7IXlImRMBOZ7GQ=
github.com/lightningnetwork/lnd/clock v1.1.0/go.mod h1:KnQudQ6w0IAMZi1SgvecLZQZ43ra2vpDNj7H/aasemg=
Expand All @@ -527,8 +525,8 @@ github.com/lightningnetwork/lnd/tlv v1.0.2/go.mod h1:fICAfsqk1IOsC1J7G9IdsWX1EqW
github.com/lightningnetwork/lnd/tlv v1.0.3 h1:0xBZcPuXagP6f7TY/RnLNR4igE21ov6qUdTr5NyvhhI=
github.com/lightningnetwork/lnd/tlv v1.0.3/go.mod h1:dzR/aZetBri+ZY/fHbwV06fNn/3UID6htQzbHfREFdo=
github.com/lightningnetwork/lnd/tor v1.0.0/go.mod h1:RDtaAdwfAm+ONuPYwUhNIH1RAvKPv+75lHPOegUcz64=
github.com/lightningnetwork/lnd/tor v1.0.1 h1:A11FrpU0Y//g+fA827W4VnjOeoIvExONdchlLX8wYkA=
github.com/lightningnetwork/lnd/tor v1.0.1/go.mod h1:RDtaAdwfAm+ONuPYwUhNIH1RAvKPv+75lHPOegUcz64=
github.com/lightningnetwork/lnd/tor v1.1.0 h1:iXO7fSzjxTI+p88KmtpbuyuRJeNfgtpl9QeaAliILXE=
github.com/lightningnetwork/lnd/tor v1.1.0/go.mod h1:RDtaAdwfAm+ONuPYwUhNIH1RAvKPv+75lHPOegUcz64=
github.com/ltcsuite/ltcd v0.20.1-beta h1:ka9ZwUG7oUPppl+7ptuh5VDxGD7TWEJXu/IOOOz1yfY=
github.com/ltcsuite/ltcd v0.20.1-beta/go.mod h1:ZFQaYdYULIuTQiWqs7AUiHD2XhDFeeHW1IH+UYMdABU=
github.com/ltcsuite/ltcutil v0.0.0-20191227053721-6bec450ea6ad/go.mod h1:8Vg/LTOO0KYa/vlHWJ6XZAevPQThGH5sufO0Hrou/lA=
Expand Down
10 changes: 5 additions & 5 deletions interceptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,11 @@ func (i *interceptor) start(ctx context.Context) error {
ChanId: item.incomingKey.ChanID,
HtlcId: item.incomingKey.HtlcID,
},
Action: item.resp.action,
Preimage: item.resp.preimage[:],
FailureMessage: item.resp.failureMessage,
FailureCode: item.resp.failureCode,
Action: item.resp.action,
Preimage: item.resp.preimage[:],
FailureMessage: item.resp.failureMessage,
FailureCode: item.resp.failureCode,
FailureMessageUnencrypted: item.resp.failureMessageUnencrypted,
}

if err := send(rpcResp); err != nil {
Expand Down Expand Up @@ -226,7 +227,6 @@ func (i *interceptor) htlcReceiveLoop(ctx context.Context,

select {
case i.htlcChan <- &interceptedHtlc{
source: i.pubKey,
circuitKey: circuitKey,
hash: hash,
onionBlob: htlc.OnionBlob,
Expand Down
76 changes: 62 additions & 14 deletions mux.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"context"
"fmt"
"sync"
"time"

"github.com/bottlepay/lnmux/common"
"github.com/bottlepay/lnmux/lnd"
Expand All @@ -29,6 +30,10 @@ type Mux struct {

settledHandler *SettledHandler
routingPolicy RoutingPolicy

virtualChannel uint64
muxKey common.PubKey
nodeKey common.PubKey
}

type MuxConfig struct {
Expand All @@ -51,9 +56,7 @@ type RoutingPolicy struct {
FeeRatePpm int64
}

func New(cfg *MuxConfig) (*Mux,
error) {

func New(cfg *MuxConfig) (*Mux, error) {
idKeyDesc, err := cfg.KeyRing.DeriveKey(
keychain.KeyLocator{
Family: keychain.KeyFamilyNodeKey,
Expand All @@ -66,6 +69,17 @@ func New(cfg *MuxConfig) (*Mux,

nodeKeyECDH := keychain.NewPubKeyECDH(idKeyDesc, cfg.KeyRing)

muxKubKey, err := cfg.KeyRing.DeriveKey(keychain.KeyLocator{})
if err != nil {
return nil, err
}
muxKey, err := common.NewPubKeyFromBytes(
muxKubKey.PubKey.SerializeCompressed(),
)
if err != nil {
return nil, err
}

replayLog := &replayLog{}

sphinxRouter := sphinx.NewRouter(
Expand All @@ -74,18 +88,25 @@ func New(cfg *MuxConfig) (*Mux,

sphinx := hop.NewOnionProcessor(sphinxRouter)

connectedNode := cfg.Lnd.PubKey()
logger := cfg.Logger.With("node", connectedNode)

virtualChannel := virtualChannelFromNode(connectedNode)

return &Mux{
registry: cfg.Registry,
sphinx: sphinx,
lnd: cfg.Lnd,
logger: cfg.Logger,
logger: logger,
settledHandler: cfg.SettledHandler,
routingPolicy: cfg.RoutingPolicy,
virtualChannel: virtualChannel,
muxKey: muxKey,
nodeKey: cfg.Lnd.PubKey(),
}, nil
}

type interceptedHtlc struct {
source common.PubKey
circuitKey types.CircuitKey
hash lntypes.Hash
onionBlob []byte
Expand All @@ -99,10 +120,11 @@ type interceptedHtlc struct {
}

type interceptedHtlcResponse struct {
action routerrpc.ResolveHoldForwardAction
preimage lntypes.Preimage
failureMessage []byte
failureCode lnrpc.Failure_FailureCode
action routerrpc.ResolveHoldForwardAction
preimage lntypes.Preimage
failureMessage []byte
failureCode lnrpc.Failure_FailureCode
failureMessageUnencrypted bool
}

func (p *Mux) Run(mainCtx context.Context) error {
Expand Down Expand Up @@ -153,10 +175,8 @@ func (p *Mux) Run(mainCtx context.Context) error {
}

case htlc := <-htlcChan:
virtualChannel := virtualChannelFromNode(htlc.source)

// Only intercept htlcs for the virtual channel.
if htlc.outgoingChanID != virtualChannel {
if htlc.outgoingChanID != p.virtualChannel {
err := htlc.reply(&interceptedHtlcResponse{
action: routerrpc.ResolveHoldForwardAction_RESUME,
})
Expand Down Expand Up @@ -209,7 +229,6 @@ func (p *Mux) ProcessHtlc(

logger := p.logger.With(
"hash", htlc.hash,
"source", htlc.source,
"circuitKey", htlc.circuitKey,
)

Expand All @@ -218,6 +237,35 @@ func (p *Mux) ProcessHtlc(
fail := func(code lnwire.FailCode) error {
logger.Debugw("Failing htlc", "code", code)

if code == lnwire.CodeFeeInsufficient {
var channelFlags lnwire.ChanUpdateChanFlags

if bytes.Compare(p.muxKey[:], p.nodeKey[:]) == 1 {
channelFlags |= lnwire.ChanUpdateDirection
}

wireMsg := lnwire.NewFeeInsufficient(0, lnwire.ChannelUpdate{
ChainHash: *p.lnd.Network().GenesisHash,
ShortChannelID: lnwire.NewShortChanIDFromInt(p.virtualChannel),
Timestamp: uint32(time.Now().Unix()),
ChannelFlags: channelFlags,
TimeLockDelta: uint16(p.routingPolicy.CltvDelta),
BaseFee: uint32(p.routingPolicy.FeeBaseMsat),
FeeRate: uint32(p.routingPolicy.FeeRatePpm),
})
var w bytes.Buffer
err := lnwire.EncodeFailureMessage(&w, wireMsg, 0)
if err != nil {
return err
}

return htlc.reply(&interceptedHtlcResponse{
action: routerrpc.ResolveHoldForwardAction_FAIL,
failureMessage: w.Bytes(),
failureMessageUnencrypted: true,
})
}

rpcCode, err := marshallFailureCode(code)
if err != nil {
return err
Expand Down Expand Up @@ -354,7 +402,7 @@ func (p *Mux) ProcessHtlc(
htlcKey := types.HtlcKey{
ChanID: htlc.circuitKey.ChanID,
HtlcID: htlc.circuitKey.HtlcID,
Node: htlc.source,
Node: p.lnd.PubKey(),
}

p.registry.NotifyExitHopHtlc(
Expand Down