lnd: add support for pushing funds as part of channel funding
This commit adds daemon level support for pushing funds as part of the single funder channel workflow. This new feature allows the user to open a channel and simultaneously make a channel at the same time which can improve the UX when setting up a channel for the first time.
This commit is contained in:
3 files changed
+43
-21
No files matched your search
+9
-6
@@ -348,8 +348,9 @@ func (f *fundingManager) handleFundingRequest(fmsg *fundingRequestMsg) {
|
|||||||
delay := msg.CsvDelay
|
delay := msg.CsvDelay
|
||||||
|
|
||||||
// TODO(roasbeef): error if funding flow already ongoing
|
// TODO(roasbeef): error if funding flow already ongoing
|
||||||
fndgLog.Infof("Recv'd fundingRequest(amt=%v, delay=%v, pendingId=%v) "+
|
fndgLog.Infof("Recv'd fundingRequest(amt=%v, push=%v, delay=%v, pendingId=%v) "+
|
||||||
"from peerID(%v)", amt, delay, msg.ChannelID, fmsg.peer.id)
|
"from peerID(%v)", amt, msg.PushSatoshis, delay, msg.ChannelID,
|
||||||
|
fmsg.peer.id)
|
||||||
|
|
||||||
ourDustLimit := lnwallet.DefaultDustLimit()
|
ourDustLimit := lnwallet.DefaultDustLimit()
|
||||||
theirDustlimit := msg.DustLimit
|
theirDustlimit := msg.DustLimit
|
||||||
@@ -364,7 +365,7 @@ func (f *fundingManager) handleFundingRequest(fmsg *fundingRequestMsg) {
|
|||||||
// port with default advertised port
|
// port with default advertised port
|
||||||
reservation, err := f.wallet.InitChannelReservation(amt, 0,
|
reservation, err := f.wallet.InitChannelReservation(amt, 0,
|
||||||
fmsg.peer.addr.IdentityKey, fmsg.peer.addr.Address, 1, delay,
|
fmsg.peer.addr.IdentityKey, fmsg.peer.addr.Address, 1, delay,
|
||||||
ourDustLimit)
|
ourDustLimit, msg.PushSatoshis)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO(roasbeef): push ErrorGeneric message
|
// TODO(roasbeef): push ErrorGeneric message
|
||||||
fndgLog.Errorf("Unable to initialize reservation: %v", err)
|
fndgLog.Errorf("Unable to initialize reservation: %v", err)
|
||||||
@@ -890,14 +891,15 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
|
|||||||
|
|
||||||
fndgLog.Infof("Initiating fundingRequest(localAmt=%v, remoteAmt=%v, "+
|
fndgLog.Infof("Initiating fundingRequest(localAmt=%v, remoteAmt=%v, "+
|
||||||
"capacity=%v, numConfs=%v, addr=%v, dustLimit=%v)", localAmt,
|
"capacity=%v, numConfs=%v, addr=%v, dustLimit=%v)", localAmt,
|
||||||
remoteAmt, ourDustLimit, capacity, numConfs,
|
msg.pushAmt, capacity, numConfs, msg.peer.addr.Address,
|
||||||
msg.peer.addr.Address)
|
ourDustLimit)
|
||||||
|
|
||||||
// Initialize a funding reservation with the local wallet. If the
|
// Initialize a funding reservation with the local wallet. If the
|
||||||
// wallet doesn't have enough funds to commit to this channel, then
|
// wallet doesn't have enough funds to commit to this channel, then
|
||||||
// the request will fail, and be aborted.
|
// the request will fail, and be aborted.
|
||||||
reservation, err := f.wallet.InitChannelReservation(capacity, localAmt,
|
reservation, err := f.wallet.InitChannelReservation(capacity, localAmt,
|
||||||
nodeID, msg.peer.addr.Address, uint16(numConfs), 4, ourDustLimit)
|
nodeID, msg.peer.addr.Address, uint16(numConfs), 4,
|
||||||
|
ourDustLimit, msg.pushAmt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg.err <- err
|
msg.err <- err
|
||||||
return
|
return
|
||||||
@@ -951,6 +953,7 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
|
|||||||
contribution.MultiSigKey,
|
contribution.MultiSigKey,
|
||||||
deliveryScript,
|
deliveryScript,
|
||||||
ourDustLimit,
|
ourDustLimit,
|
||||||
|
msg.pushAmt,
|
||||||
)
|
)
|
||||||
msg.peer.queueMsg(fundingReq, nil)
|
msg.peer.queueMsg(fundingReq, nil)
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-7
@@ -233,10 +233,18 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest,
|
|||||||
|
|
||||||
rpcsLog.Tracef("[openchannel] request to peerid(%v) "+
|
rpcsLog.Tracef("[openchannel] request to peerid(%v) "+
|
||||||
"allocation(us=%v, them=%v) numconfs=%v", in.TargetPeerId,
|
"allocation(us=%v, them=%v) numconfs=%v", in.TargetPeerId,
|
||||||
in.LocalFundingAmount, in.RemoteFundingAmount, in.NumConfs)
|
in.LocalFundingAmount, in.PushSat, in.NumConfs)
|
||||||
|
|
||||||
localFundingAmt := btcutil.Amount(in.LocalFundingAmount)
|
localFundingAmt := btcutil.Amount(in.LocalFundingAmount)
|
||||||
remoteFundingAmt := btcutil.Amount(in.RemoteFundingAmount)
|
remoteInitialBalance := btcutil.Amount(in.PushSat)
|
||||||
|
|
||||||
|
// Ensure that the initial balance of the remote party (if pushing
|
||||||
|
// satoshis) does not execeed the amount the local party has requested
|
||||||
|
// for funding.
|
||||||
|
if remoteInitialBalance >= localFundingAmt {
|
||||||
|
return fmt.Errorf("amount pushed to remote peer for initial " +
|
||||||
|
"state must be below the local funding amount")
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(roasbeef): make it optional
|
// TODO(roasbeef): make it optional
|
||||||
nodepubKey, err := btcec.ParsePubKey(in.NodePubkey, btcec.S256())
|
nodepubKey, err := btcec.ParsePubKey(in.NodePubkey, btcec.S256())
|
||||||
@@ -248,7 +256,7 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest,
|
|||||||
// open a new channel. A stream is returned in place, this stream will
|
// open a new channel. A stream is returned in place, this stream will
|
||||||
// be used to consume updates of the state of the pending channel.
|
// be used to consume updates of the state of the pending channel.
|
||||||
updateChan, errChan := r.server.OpenChannel(in.TargetPeerId,
|
updateChan, errChan := r.server.OpenChannel(in.TargetPeerId,
|
||||||
nodepubKey, localFundingAmt, remoteFundingAmt, in.NumConfs)
|
nodepubKey, localFundingAmt, remoteInitialBalance, in.NumConfs)
|
||||||
|
|
||||||
var outpoint wire.OutPoint
|
var outpoint wire.OutPoint
|
||||||
out:
|
out:
|
||||||
@@ -257,7 +265,8 @@ out:
|
|||||||
case err := <-errChan:
|
case err := <-errChan:
|
||||||
rpcsLog.Errorf("unable to open channel to "+
|
rpcsLog.Errorf("unable to open channel to "+
|
||||||
"identityPub(%x) nor peerID(%v): %v",
|
"identityPub(%x) nor peerID(%v): %v",
|
||||||
nodepubKey, in.TargetPeerId, err)
|
nodepubKey.SerializeCompressed(),
|
||||||
|
in.TargetPeerId, err)
|
||||||
return err
|
return err
|
||||||
case fundingUpdate := <-updateChan:
|
case fundingUpdate := <-updateChan:
|
||||||
rpcsLog.Tracef("[openchannel] sending update: %v",
|
rpcsLog.Tracef("[openchannel] sending update: %v",
|
||||||
@@ -299,7 +308,7 @@ func (r *rpcServer) OpenChannelSync(ctx context.Context,
|
|||||||
|
|
||||||
rpcsLog.Tracef("[openchannel] request to peerid(%v) "+
|
rpcsLog.Tracef("[openchannel] request to peerid(%v) "+
|
||||||
"allocation(us=%v, them=%v) numconfs=%v", in.TargetPeerId,
|
"allocation(us=%v, them=%v) numconfs=%v", in.TargetPeerId,
|
||||||
in.LocalFundingAmount, in.RemoteFundingAmount, in.NumConfs)
|
in.LocalFundingAmount, in.PushSat, in.NumConfs)
|
||||||
|
|
||||||
// Decode the provided target node's public key, parsing it into a pub
|
// Decode the provided target node's public key, parsing it into a pub
|
||||||
// key object. For all sync call, byte slices are expected to be
|
// key object. For all sync call, byte slices are expected to be
|
||||||
@@ -314,10 +323,18 @@ func (r *rpcServer) OpenChannelSync(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
localFundingAmt := btcutil.Amount(in.LocalFundingAmount)
|
localFundingAmt := btcutil.Amount(in.LocalFundingAmount)
|
||||||
remoteFundingAmt := btcutil.Amount(in.RemoteFundingAmount)
|
remoteInitialBalance := btcutil.Amount(in.PushSat)
|
||||||
|
|
||||||
|
// Ensure that the initial balance of the remote party (if pushing
|
||||||
|
// satoshis) does not execeed the amount the local party has requested
|
||||||
|
// for funding.
|
||||||
|
if remoteInitialBalance >= localFundingAmt {
|
||||||
|
return nil, fmt.Errorf("amount pushed to remote peer for " +
|
||||||
|
"initial state must be below the local funding amount")
|
||||||
|
}
|
||||||
|
|
||||||
updateChan, errChan := r.server.OpenChannel(in.TargetPeerId,
|
updateChan, errChan := r.server.OpenChannel(in.TargetPeerId,
|
||||||
nodepubKey, localFundingAmt, remoteFundingAmt, in.NumConfs)
|
nodepubKey, localFundingAmt, remoteInitialBalance, in.NumConfs)
|
||||||
|
|
||||||
select {
|
select {
|
||||||
// If an error occurs them immediately return the error to the client.
|
// If an error occurs them immediately return the error to the client.
|
||||||
|
|||||||
@@ -566,6 +566,8 @@ type openChanReq struct {
|
|||||||
localFundingAmt btcutil.Amount
|
localFundingAmt btcutil.Amount
|
||||||
remoteFundingAmt btcutil.Amount
|
remoteFundingAmt btcutil.Amount
|
||||||
|
|
||||||
|
pushAmt btcutil.Amount
|
||||||
|
|
||||||
numConfs uint32
|
numConfs uint32
|
||||||
|
|
||||||
updates chan *lnrpc.OpenStatusUpdate
|
updates chan *lnrpc.OpenStatusUpdate
|
||||||
@@ -777,20 +779,20 @@ func (s *server) ConnectToPeer(addr *lnwire.NetAddress) (int32, error) {
|
|||||||
// OpenChannel sends a request to the server to open a channel to the specified
|
// OpenChannel sends a request to the server to open a channel to the specified
|
||||||
// peer identified by ID with the passed channel funding paramters.
|
// peer identified by ID with the passed channel funding paramters.
|
||||||
func (s *server) OpenChannel(peerID int32, nodeKey *btcec.PublicKey,
|
func (s *server) OpenChannel(peerID int32, nodeKey *btcec.PublicKey,
|
||||||
localAmt, remoteAmt btcutil.Amount,
|
localAmt, pushAmt btcutil.Amount,
|
||||||
numConfs uint32) (chan *lnrpc.OpenStatusUpdate, chan error) {
|
numConfs uint32) (chan *lnrpc.OpenStatusUpdate, chan error) {
|
||||||
|
|
||||||
errChan := make(chan error, 1)
|
errChan := make(chan error, 1)
|
||||||
updateChan := make(chan *lnrpc.OpenStatusUpdate, 1)
|
updateChan := make(chan *lnrpc.OpenStatusUpdate, 1)
|
||||||
|
|
||||||
req := &openChanReq{
|
req := &openChanReq{
|
||||||
targetPeerID: peerID,
|
targetPeerID: peerID,
|
||||||
targetPubkey: nodeKey,
|
targetPubkey: nodeKey,
|
||||||
localFundingAmt: localAmt,
|
localFundingAmt: localAmt,
|
||||||
remoteFundingAmt: remoteAmt,
|
pushAmt: pushAmt,
|
||||||
numConfs: numConfs,
|
numConfs: numConfs,
|
||||||
updates: updateChan,
|
updates: updateChan,
|
||||||
err: errChan,
|
err: errChan,
|
||||||
}
|
}
|
||||||
|
|
||||||
s.queries <- req
|
s.queries <- req
|
||||||
|
|||||||
Reference in new issue
Block a user