From 6bbb7cbfc373c58efca878d1bad284e9309b4550 Mon Sep 17 00:00:00 2001 From: Andrey Samokhvalov Date: Thu, 29 Jun 2017 16:52:55 +0300 Subject: [PATCH] lnd: hook up encrypted onion error scaffolding In this commit daemon have been changed to set the proper hooks in the channel link and switch subsystems so that they could send and receive encrypted onion errors. --- peer.go | 55 +++++++++++++++++++++++++++++++++++++++++++++++++------ server.go | 17 +++++++++++++---- 2 files changed, 62 insertions(+), 10 deletions(-) diff --git a/peer.go b/peer.go index bcf2a1ac..1b527bfc 100644 --- a/peer.go +++ b/peer.go @@ -20,6 +20,7 @@ import ( "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/routing" "github.com/roasbeef/btcd/btcec" "github.com/roasbeef/btcd/chaincfg/chainhash" "github.com/roasbeef/btcd/connmgr" @@ -306,11 +307,13 @@ func (p *peer) loadActiveChannels(chans []*channeldb.OpenChannel) error { // Register this new channel link with the HTLC Switch. This is // necessary to properly route multi-hop payments, and forward // new payments triggered by RPC clients. - sphinxDecoder := htlcswitch.NewSphinxDecoder(p.server.sphinx) link := htlcswitch.NewChannelLink( htlcswitch.ChannelLinkConfig{ - Peer: p, - DecodeOnion: sphinxDecoder.Decode, + Peer: p, + DecodeHopIterator: p.server.sphinx.DecodeHopIterator, + DecodeOnionObfuscator: p.server.sphinx.DecodeOnionObfuscator, + GetLastChannelUpdate: createGetLastUpdate(p.server.chanRouter, + p.PubKey(), lnChan.ShortChanID()), SettledContracts: p.server.breachArbiter.settledContracts, DebugHTLC: cfg.DebugHTLC, Registry: p.server.invoices, @@ -786,11 +789,13 @@ out: peerLog.Infof("New channel active ChannelPoint(%v) "+ "with peerId(%v)", chanPoint, p.id) - decoder := htlcswitch.NewSphinxDecoder(p.server.sphinx) link := htlcswitch.NewChannelLink( htlcswitch.ChannelLinkConfig{ - Peer: p, - DecodeOnion: decoder.Decode, + Peer: p, + DecodeHopIterator: p.server.sphinx.DecodeHopIterator, + DecodeOnionObfuscator: p.server.sphinx.DecodeOnionObfuscator, + GetLastChannelUpdate: createGetLastUpdate(p.server.chanRouter, + p.PubKey(), newChanReq.channel.ShortChanID()), SettledContracts: p.server.breachArbiter.settledContracts, DebugHTLC: cfg.DebugHTLC, Registry: p.server.invoices, @@ -1365,3 +1370,41 @@ func (p *peer) PubKey() [33]byte { } // TODO(roasbeef): make all start/stop mutexes a CAS + +// createGetLastUpdate returns the handler which serve as a source of the last +// update of the channel in a form of lnwire update message. +func createGetLastUpdate(router *routing.ChannelRouter, + pubKey [33]byte, chanID lnwire.ShortChannelID) func() (*lnwire.ChannelUpdate, + error) { + + return func() (*lnwire.ChannelUpdate, error) { + _, edge1, edge2, err := router.GetChannelByID(chanID) + if err != nil { + return nil, err + } + + if edge1 == nil || edge2 == nil { + return nil, errors.Errorf("unable to find "+ + "channel by ShortChannelID(%v)", chanID) + } + + var local *channeldb.ChannelEdgePolicy + if bytes.Compare(edge1.Node.PubKey.SerializeCompressed(), + pubKey[:]) == 0 { + local = edge2 + } else { + local = edge1 + } + + return &lnwire.ChannelUpdate{ + Signature: local.Signature, + ShortChannelID: lnwire.NewShortChanIDFromInt(local.ChannelID), + Timestamp: uint32(time.Now().Unix()), + Flags: local.Flags, + TimeLockDelta: local.TimeLockDelta, + HtlcMinimumMsat: uint64(local.MinHTLC), + BaseFee: uint32(local.FeeBaseMSat), + FeeRate: uint32(local.FeeProportionalMillionths), + }, nil + } +} diff --git a/server.go b/server.go index 2588b097..81b5fa49 100644 --- a/server.go +++ b/server.go @@ -71,7 +71,7 @@ type server struct { utxoNursery *utxoNursery - sphinx *sphinx.Router + sphinx *htlcswitch.OnionProcessor connMgr *connmgr.ConnManager @@ -126,7 +126,8 @@ func newServer(listenAddrs []string, chanDB *channeldb.DB, cc *chainControl, // TODO(roasbeef): derive proper onion key based on rotation // schedule - sphinx: sphinx.NewRouter(privKey, activeNetParams.Params), + sphinx: htlcswitch.NewOnionProcessor( + sphinx.NewRouter(privKey, activeNetParams.Params)), lightningID: sha256.Sum256(serializedPubKey), persistentPeers: make(map[string]struct{}), @@ -236,11 +237,19 @@ func newServer(listenAddrs []string, chanDB *channeldb.DB, cc *chainControl, Chain: cc.chainIO, ChainView: cc.chainView, SendToSwitch: func(firstHop *btcec.PublicKey, - htlcAdd *lnwire.UpdateAddHTLC) ([32]byte, error) { + htlcAdd *lnwire.UpdateAddHTLC, + circuit *sphinx.Circuit) ([32]byte, error) { + + // Initialize the data obfuscator in order to be able to decode the + // onion failure and wrap it so that we could process lnwire onion + // failures. + failureDeobfuscator := &htlcswitch.FailureDeobfuscator{ + OnionDeobfuscator: sphinx.NewOnionDeobfuscator(circuit), + } var firstHopPub [33]byte copy(firstHopPub[:], firstHop.SerializeCompressed()) - return s.htlcSwitch.SendHTLC(firstHopPub, htlcAdd) + return s.htlcSwitch.SendHTLC(firstHopPub, htlcAdd, failureDeobfuscator) }, }) if err != nil {