routing+rpcserver: move route querying+sending to SendPayment
This commit moves much of the logic for querying for a potential route, constructing the HTLC including the Sphinx packet, and sending the ultimate payment from the rpcServer to the ChannelRouter. This movement paves the way for muilt-path path finding as well as adding automatic retry logic to the ChannelRouter. Additionally, by having the ChannelRouter construct the Sphinx packet, we’ll be able to also include the proper time-lock and general per-hop-payload information properly in the future.
This commit is contained in:
parent
4eebc7c994
commit
08f0d0fbea
@ -15,6 +15,8 @@ import (
|
|||||||
"github.com/roasbeef/btcd/btcec"
|
"github.com/roasbeef/btcd/btcec"
|
||||||
"github.com/roasbeef/btcd/wire"
|
"github.com/roasbeef/btcd/wire"
|
||||||
"github.com/roasbeef/btcutil"
|
"github.com/roasbeef/btcutil"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lightning-onion"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FeeSchema is the set fee configuration for a Lighting Node on the network.
|
// FeeSchema is the set fee configuration for a Lighting Node on the network.
|
||||||
@ -74,9 +76,12 @@ type Config struct {
|
|||||||
// key.
|
// key.
|
||||||
SendMessages func(target *btcec.PublicKey, msg ...lnwire.Message) error
|
SendMessages func(target *btcec.PublicKey, msg ...lnwire.Message) error
|
||||||
|
|
||||||
// TODO(roasbeef): need a SendToSwitch func
|
// SendToSwitch is a function that directs a link-layer switch to
|
||||||
// * possibly lift switch into package?
|
// forward a fully encoded payment to the first hop in the route
|
||||||
// *
|
// denoted by its public key. A non-nil error is to be returned if the
|
||||||
|
// payment was unsuccessful.
|
||||||
|
SendToSwitch func(firstHop *btcec.PublicKey,
|
||||||
|
htlcAdd *lnwire.HTLCAddRequest) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChannelRouter is the layer 3 router within the Lightning stack. Below the
|
// ChannelRouter is the layer 3 router within the Lightning stack. Below the
|
||||||
@ -540,6 +545,11 @@ func (r *ChannelRouter) processNetworkAnnouncement(msg lnwire.Message) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(roasbeef): check if height > then our known height and
|
||||||
|
// wait for next epoch based on that?
|
||||||
|
// * or add to "premature" announcement bucket
|
||||||
|
// * bucket gets checked on each new incoming block
|
||||||
|
|
||||||
// Before we can add the channel to the channel graph, we need
|
// Before we can add the channel to the channel graph, we need
|
||||||
// to obtain the full funding outpoint that's encoded within
|
// to obtain the full funding outpoint that's encoded within
|
||||||
// the channel ID.
|
// the channel ID.
|
||||||
@ -911,13 +921,130 @@ func (r *ChannelRouter) FindRoute(target *btcec.PublicKey, amt btcutil.Amount) (
|
|||||||
return route, nil
|
return route, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendPayment...
|
// generateSphinxPacket generates then encodes a sphinx packet which encodes
|
||||||
|
// the onion route specified by the passed layer 3 route. The blob returned
|
||||||
|
// from this function can immediately be included within an HTLC add packet to
|
||||||
|
// be sent to the first hop within the route.
|
||||||
//
|
//
|
||||||
// TODO(roasbeef): pipe through the htlcSwitch, move the payment storage info
|
// TODO(roasbeef): add params for the per-hop payloads
|
||||||
// to the router, add interface for payment storage
|
func generateSphinxPacket(route *Route, paymentHash []byte) ([]byte, error) {
|
||||||
// TODO(roasbeef): add version that takes a route object
|
// First obtain all the public keys along the route which are contained
|
||||||
func (r *ChannelRouter) SendPayment() error {
|
// in each hop.
|
||||||
return nil
|
nodes := make([]*btcec.PublicKey, len(route.Hops))
|
||||||
|
for i, hop := range route.Hops {
|
||||||
|
// We create a new instance of the public key to avoid possibly
|
||||||
|
// mutating the curve parameters, which are unset in a higher
|
||||||
|
// level in order to avoid spamming the logs.
|
||||||
|
pub := btcec.PublicKey{
|
||||||
|
btcec.S256(),
|
||||||
|
hop.Channel.Node.PubKey.X,
|
||||||
|
hop.Channel.Node.PubKey.Y,
|
||||||
|
}
|
||||||
|
nodes[i] = &pub
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next we generate the per-hop payload which gives each node within
|
||||||
|
// the route the necessary information (fees, CLTV value, etc) to
|
||||||
|
// properly forward the payment.
|
||||||
|
// TODO(roasbeef): properly set CLTV value, payment amount, and chain
|
||||||
|
// within hop payloads.
|
||||||
|
var hopPayloads [][]byte
|
||||||
|
for i := 0; i < len(route.Hops); i++ {
|
||||||
|
payload := bytes.Repeat([]byte{byte('A' + i)},
|
||||||
|
sphinx.HopPayloadSize)
|
||||||
|
hopPayloads = append(hopPayloads, payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionKey, err := btcec.NewPrivateKey(btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next generate the onion routing packet which allows us to perform
|
||||||
|
// privacy preserving source routing across the network.
|
||||||
|
sphinxPacket, err := sphinx.NewOnionPacket(nodes, sessionKey,
|
||||||
|
hopPayloads, paymentHash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, encode Sphinx packet using it's wire representation to be
|
||||||
|
// included within the HTLC add packet.
|
||||||
|
var onionBlob bytes.Buffer
|
||||||
|
if err := sphinxPacket.Encode(&onionBlob); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Tracef("Generated sphinx packet: %v",
|
||||||
|
newLogClosure(func() string {
|
||||||
|
// We unset the internal curve here in order to keep
|
||||||
|
// the logs from getting noisy.
|
||||||
|
sphinxPacket.Header.EphemeralKey.Curve = nil
|
||||||
|
return spew.Sdump(sphinxPacket)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
return onionBlob.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LightningPayment describes a payment to be sent through the network to the
|
||||||
|
// final destination.
|
||||||
|
type LightningPayment struct {
|
||||||
|
// Target is the node in which the payment should be routed towards.
|
||||||
|
Target *btcec.PublicKey
|
||||||
|
|
||||||
|
// Amount is the value of the payment to send throuhg the network in
|
||||||
|
// satoshis.
|
||||||
|
// TODO(roasbeef): this should be milli satoshis
|
||||||
|
Amount btcutil.Amount
|
||||||
|
|
||||||
|
// PaymentHash is the r-hash value to use within the HTLC extended to
|
||||||
|
// the first hop.
|
||||||
|
PaymentHash [32]byte
|
||||||
|
|
||||||
|
// TODO(roasbeef): add message?
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendPayment attempts to send a payment as described within the passed
|
||||||
|
// LightningPayment. This function is blocking and will return either: when the
|
||||||
|
// payment is successful, or all candidates routes have been attempted and
|
||||||
|
// resulted in a failed payment. If the payment succeeds, then a non-nil Route
|
||||||
|
// will be returned which describes the path the successful payment traversed
|
||||||
|
// within the network to reach the destination.
|
||||||
|
func (r *ChannelRouter) SendPayment(payment *LightningPayment) (*Route, error) {
|
||||||
|
// Query the graph for a potential path to the destination node that
|
||||||
|
// can support our payment amount. If a path is ultimately unavailable,
|
||||||
|
// then an error will be returned.
|
||||||
|
route, err := r.FindRoute(payment.Target, payment.Amount)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
log.Tracef("Selected route for payment: %#v", route)
|
||||||
|
|
||||||
|
// Generate the raw encoded sphinx packet to be included along with the
|
||||||
|
// htlcAdd message that we send directly to the switch.
|
||||||
|
sphinxPacket, err := generateSphinxPacket(route, payment.PaymentHash[:])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Craft an HTLC packet to send to the layer 2 switch. The metadata
|
||||||
|
// within this packet will be used to route the payment through the
|
||||||
|
// network, starting with the first-hop.
|
||||||
|
htlcAdd := &lnwire.HTLCAddRequest{
|
||||||
|
Amount: route.TotalAmount,
|
||||||
|
RedemptionHashes: [][32]byte{payment.PaymentHash},
|
||||||
|
OnionBlob: sphinxPacket,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to send this payment through the network to complete the
|
||||||
|
// payment. If this attempt fails, then we'll bail our early.
|
||||||
|
firstHop := route.Hops[0].Channel.Node.PubKey
|
||||||
|
if err := r.cfg.SendToSwitch(firstHop, htlcAdd); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return route, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TopologyClient...
|
// TopologyClient...
|
||||||
|
179
rpcserver.go
179
rpcserver.go
@ -1,7 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
@ -17,7 +16,6 @@ import (
|
|||||||
|
|
||||||
"github.com/btcsuite/fastsha256"
|
"github.com/btcsuite/fastsha256"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/lightningnetwork/lightning-onion"
|
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
@ -916,10 +914,10 @@ func (r *rpcServer) SendPayment(paymentStream lnrpc.Lightning_SendPaymentServer)
|
|||||||
return err
|
return err
|
||||||
|
|
||||||
}
|
}
|
||||||
// If we're in debug HTLC mode, then all outgoing
|
|
||||||
// HTLCs will pay to the same debug rHash. Otherwise,
|
// If we're in debug HTLC mode, then all outgoing HTLCs
|
||||||
// we pay to the rHash specified within the RPC
|
// will pay to the same debug rHash. Otherwise, we pay
|
||||||
// request.
|
// to the rHash specified within the RPC request.
|
||||||
var rHash [32]byte
|
var rHash [32]byte
|
||||||
if cfg.DebugHTLC && len(nextPayment.PaymentHash) == 0 {
|
if cfg.DebugHTLC && len(nextPayment.PaymentHash) == 0 {
|
||||||
rHash = debugHash
|
rHash = debugHash
|
||||||
@ -927,15 +925,6 @@ func (r *rpcServer) SendPayment(paymentStream lnrpc.Lightning_SendPaymentServer)
|
|||||||
copy(rHash[:], nextPayment.PaymentHash)
|
copy(rHash[:], nextPayment.PaymentHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct and HTLC packet which a payment route (if
|
|
||||||
// one is found) to the destination using a Sphinx
|
|
||||||
// onion packet to encode the route.
|
|
||||||
htlcPkt, route, err := r.constructPaymentRoute(destNode, amt,
|
|
||||||
rHash)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// We launch a new goroutine to execute the current
|
// We launch a new goroutine to execute the current
|
||||||
// payment so we can continue to serve requests while
|
// payment so we can continue to serve requests while
|
||||||
// this payment is being dispatched.
|
// this payment is being dispatched.
|
||||||
@ -943,10 +932,18 @@ func (r *rpcServer) SendPayment(paymentStream lnrpc.Lightning_SendPaymentServer)
|
|||||||
// TODO(roasbeef): semaphore to limit num outstanding
|
// TODO(roasbeef): semaphore to limit num outstanding
|
||||||
// goroutines.
|
// goroutines.
|
||||||
go func() {
|
go func() {
|
||||||
// Finally, send this next packet to the
|
// Construct a payment request to send to the
|
||||||
// routing layer in order to complete the next
|
// channel router. If the payment is
|
||||||
// payment.
|
// successful, the the route chosen will be
|
||||||
if err := r.server.htlcSwitch.SendHTLC(htlcPkt); err != nil {
|
// returned. Otherwise, we'll get a non-nil
|
||||||
|
// error.
|
||||||
|
payment := &routing.LightningPayment{
|
||||||
|
Target: destNode,
|
||||||
|
Amount: amt,
|
||||||
|
PaymentHash: rHash,
|
||||||
|
}
|
||||||
|
route, err := r.server.chanRouter.SendPayment(payment)
|
||||||
|
if err != nil {
|
||||||
errChan <- err
|
errChan <- err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -958,11 +955,11 @@ func (r *rpcServer) SendPayment(paymentStream lnrpc.Lightning_SendPaymentServer)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(roasbeef): proper responses
|
// TODO(roasbeef): tack on payment hash also?
|
||||||
resp := &lnrpc.SendResponse{
|
err = paymentStream.Send(&lnrpc.SendResponse{
|
||||||
PaymentRoute: marshalRoute(route),
|
PaymentRoute: marshalRoute(route),
|
||||||
}
|
})
|
||||||
if err := paymentStream.Send(resp); err != nil {
|
if err != nil {
|
||||||
errChan <- err
|
errChan <- err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -997,12 +994,12 @@ func (r *rpcServer) SendPaymentSync(ctx context.Context,
|
|||||||
amt = payReq.Amount
|
amt = payReq.Amount
|
||||||
rHash = payReq.PaymentHash
|
rHash = payReq.PaymentHash
|
||||||
|
|
||||||
// Otherwise, the payment conditions have been manually specified in
|
// Otherwise, the payment conditions have been manually
|
||||||
// the proto.
|
// specified in the proto.
|
||||||
} else {
|
} else {
|
||||||
// If we're in debug HTLC mode, then all outgoing HTLCs will pay to
|
// If we're in debug HTLC mode, then all outgoing HTLCs will
|
||||||
// the same debug rHash. Otherwise, we pay to the rHash specified
|
// pay to the same debug rHash. Otherwise, we pay to the rHash
|
||||||
// within the RPC request.
|
// specified within the RPC request.
|
||||||
if cfg.DebugHTLC && nextPayment.PaymentHashString == "" {
|
if cfg.DebugHTLC && nextPayment.PaymentHashString == "" {
|
||||||
rHash = debugHash
|
rHash = debugHash
|
||||||
} else {
|
} else {
|
||||||
@ -1026,20 +1023,18 @@ func (r *rpcServer) SendPaymentSync(ctx context.Context,
|
|||||||
amt = btcutil.Amount(nextPayment.Amt)
|
amt = btcutil.Amount(nextPayment.Amt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct and HTLC packet which a payment route (if
|
// Finally, send a payment request to the channel router. If the
|
||||||
// one is found) to the destination using a Sphinx
|
// payment succeeds, then the returned route will be that was used
|
||||||
// onoin packet to encode the route.
|
// successfully within the payment.
|
||||||
htlcPkt, route, err := r.constructPaymentRoute(destPub, amt, rHash)
|
route, err := r.server.chanRouter.SendPayment(&routing.LightningPayment{
|
||||||
|
Target: destPub,
|
||||||
|
Amount: amt,
|
||||||
|
PaymentHash: rHash,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next, send this next packet to the routing layer in order to
|
|
||||||
// complete the next payment.
|
|
||||||
if err := r.server.htlcSwitch.SendHTLC(htlcPkt); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// With the payment completed successfully, we now ave the details of
|
// With the payment completed successfully, we now ave the details of
|
||||||
// the completed payment to the databse for historical record keeping.
|
// the completed payment to the databse for historical record keeping.
|
||||||
if err := r.savePayment(route, amt, rHash[:]); err != nil {
|
if err := r.savePayment(route, amt, rHash[:]); err != nil {
|
||||||
@ -1049,114 +1044,6 @@ func (r *rpcServer) SendPaymentSync(ctx context.Context,
|
|||||||
return &lnrpc.SendResponse{}, nil
|
return &lnrpc.SendResponse{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// constructPaymentRoute attempts to construct a complete HTLC packet which
|
|
||||||
// encapsulates a Sphinx onion packet that encodes the end-to-end route any
|
|
||||||
// payment instructions necessary to complete an HTLC. If a route is unable to
|
|
||||||
// be located, then an error is returned indicating as much.
|
|
||||||
func (r *rpcServer) constructPaymentRoute(destNode *btcec.PublicKey,
|
|
||||||
amt btcutil.Amount, rHash [32]byte) (*htlcPacket, *routing.Route, error) {
|
|
||||||
|
|
||||||
const queryTimeout = time.Duration(time.Second * 10)
|
|
||||||
|
|
||||||
// Query the channel router for a potential path to the destination
|
|
||||||
// node that can support our payment amount. If a path is ultimately
|
|
||||||
// unavailable, then an error will be returned.
|
|
||||||
route, err := r.server.chanRouter.FindRoute(destNode, amt)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
rpcsLog.Tracef("[sendpayment] selected route: %#v", route)
|
|
||||||
|
|
||||||
// Generate the raw encoded sphinx packet to be included along with the
|
|
||||||
// HTLC add message. We snip off the first hop from the path as within
|
|
||||||
// the routing table's star graph, we're always the first hop.
|
|
||||||
sphinxPacket, err := generateSphinxPacket(route, rHash[:])
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Craft an HTLC packet to send to the routing subsystem. The
|
|
||||||
// metadata within this packet will be used to route the payment
|
|
||||||
// through the network.
|
|
||||||
htlcAdd := &lnwire.HTLCAddRequest{
|
|
||||||
Amount: route.TotalAmount,
|
|
||||||
RedemptionHashes: [][32]byte{rHash},
|
|
||||||
OnionBlob: sphinxPacket,
|
|
||||||
}
|
|
||||||
|
|
||||||
firstHopPub := route.Hops[0].Channel.Node.PubKey.SerializeCompressed()
|
|
||||||
destInterface := chainhash.Hash(fastsha256.Sum256(firstHopPub))
|
|
||||||
|
|
||||||
return &htlcPacket{
|
|
||||||
dest: destInterface,
|
|
||||||
msg: htlcAdd,
|
|
||||||
}, route, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// generateSphinxPacket generates then encodes a sphinx packet which encodes
|
|
||||||
// the onion route specified by the passed layer 3 route. The blob returned
|
|
||||||
// from this function can immediately be included within an HTLC add packet to
|
|
||||||
// be sent to the first hop within the route.
|
|
||||||
func generateSphinxPacket(route *routing.Route, paymentHash []byte) ([]byte, error) {
|
|
||||||
// First obtain all the public keys along the route which are contained
|
|
||||||
// in each hop.
|
|
||||||
nodes := make([]*btcec.PublicKey, len(route.Hops))
|
|
||||||
for i, hop := range route.Hops {
|
|
||||||
// We create a new instance of the public key to avoid possibly
|
|
||||||
// mutating the curve parameters, which are unset in a higher
|
|
||||||
// level in order to avoid spamming the logs.
|
|
||||||
pub := btcec.PublicKey{
|
|
||||||
btcec.S256(),
|
|
||||||
hop.Channel.Node.PubKey.X,
|
|
||||||
hop.Channel.Node.PubKey.Y,
|
|
||||||
}
|
|
||||||
nodes[i] = &pub
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next we generate the per-hop payload which gives each node within
|
|
||||||
// the route the necessary information (fees, CLTV value, etc) to
|
|
||||||
// properly forward the payment.
|
|
||||||
// TODO(roasbeef): properly set CLTV value, payment amount, and chain
|
|
||||||
// within hop paylods.
|
|
||||||
var hopPayloads [][]byte
|
|
||||||
for i := 0; i < len(route.Hops); i++ {
|
|
||||||
payload := bytes.Repeat([]byte{byte('A' + i)},
|
|
||||||
sphinx.HopPayloadSize)
|
|
||||||
hopPayloads = append(hopPayloads, payload)
|
|
||||||
}
|
|
||||||
|
|
||||||
sessionKey, err := btcec.NewPrivateKey(btcec.S256())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next generate the onion routing packet which allows
|
|
||||||
// us to perform privacy preserving source routing
|
|
||||||
// across the network.
|
|
||||||
sphinxPacket, err := sphinx.NewOnionPacket(nodes, sessionKey,
|
|
||||||
hopPayloads, paymentHash)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, encode Sphinx packet using it's wire representation to be
|
|
||||||
// included within the HTLC add packet.
|
|
||||||
var onionBlob bytes.Buffer
|
|
||||||
if err := sphinxPacket.Encode(&onionBlob); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
rpcsLog.Tracef("[sendpayment] generated sphinx packet: %v",
|
|
||||||
newLogClosure(func() string {
|
|
||||||
// We unset the internal curve here in order to keep
|
|
||||||
// the logs from getting noisy.
|
|
||||||
sphinxPacket.Header.EphemeralKey.Curve = nil
|
|
||||||
return spew.Sdump(sphinxPacket)
|
|
||||||
}))
|
|
||||||
|
|
||||||
return onionBlob.Bytes(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddInvoice attempts to add a new invoice to the invoice database. Any
|
// AddInvoice attempts to add a new invoice to the invoice database. Any
|
||||||
// duplicated invoices are rejected, therefore all invoices *must* have a
|
// duplicated invoices are rejected, therefore all invoices *must* have a
|
||||||
// unique payment preimage.
|
// unique payment preimage.
|
||||||
|
16
server.go
16
server.go
@ -17,11 +17,11 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
"github.com/lightningnetwork/lnd/routing"
|
||||||
"github.com/roasbeef/btcd/btcec"
|
"github.com/roasbeef/btcd/btcec"
|
||||||
|
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
||||||
"github.com/roasbeef/btcd/connmgr"
|
"github.com/roasbeef/btcd/connmgr"
|
||||||
"github.com/roasbeef/btcutil"
|
"github.com/roasbeef/btcutil"
|
||||||
|
|
||||||
"github.com/lightningnetwork/lnd/routing"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// server is the main server of the Lightning Network Daemon. The server houses
|
// server is the main server of the Lightning Network Daemon. The server houses
|
||||||
@ -167,6 +167,17 @@ func newServer(listenAddrs []string, notifier chainntnfs.ChainNotifier,
|
|||||||
Notifier: notifier,
|
Notifier: notifier,
|
||||||
Broadcast: s.broadcastMessage,
|
Broadcast: s.broadcastMessage,
|
||||||
SendMessages: s.sendToPeer,
|
SendMessages: s.sendToPeer,
|
||||||
|
SendToSwitch: func(firstHop *btcec.PublicKey,
|
||||||
|
htlcAdd *lnwire.HTLCAddRequest) error {
|
||||||
|
|
||||||
|
firstHopPub := firstHop.SerializeCompressed()
|
||||||
|
destInterface := chainhash.Hash(fastsha256.Sum256(firstHopPub))
|
||||||
|
|
||||||
|
return s.htlcSwitch.SendHTLC(&htlcPacket{
|
||||||
|
dest: destInterface,
|
||||||
|
msg: htlcAdd,
|
||||||
|
})
|
||||||
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -217,6 +228,7 @@ func newServer(listenAddrs []string, notifier chainntnfs.ChainNotifier,
|
|||||||
// Send the persistent connection request to the connection
|
// Send the persistent connection request to the connection
|
||||||
// manager, saving the request itself so we can cancel/restart
|
// manager, saving the request itself so we can cancel/restart
|
||||||
// the process as needed.
|
// the process as needed.
|
||||||
|
// TODO(roasbeef): use default addr
|
||||||
connReq := &connmgr.ConnReq{
|
connReq := &connmgr.ConnReq{
|
||||||
Addr: lnAddr,
|
Addr: lnAddr,
|
||||||
Permanent: true,
|
Permanent: true,
|
||||||
|
Loading…
Reference in New Issue
Block a user