fundingmanager+lnwallet: add HTLC dust limit logic
This commit is contained in:
parent
c731156ac8
commit
d01f1b5ff4
@ -335,6 +335,8 @@ func (f *fundingManager) handleFundingRequest(fmsg *fundingRequestMsg) {
|
||||
fndgLog.Infof("Recv'd fundingRequest(amt=%v, delay=%v, pendingId=%v) "+
|
||||
"from peerID(%v)", amt, delay, msg.ChannelID, fmsg.peer.id)
|
||||
|
||||
ourDustLimit := lnwallet.DefaultDustLimit()
|
||||
theirDustlimit := msg.DustLimit
|
||||
// Attempt to initialize a reservation within the wallet. If the wallet
|
||||
// has insufficient resources to create the channel, then the reservation
|
||||
// attempt may be rejected. Note that since we're on the responding
|
||||
@ -342,7 +344,8 @@ func (f *fundingManager) handleFundingRequest(fmsg *fundingRequestMsg) {
|
||||
// channel ourselves.
|
||||
// TODO(roasbeef): passing num confs 1 is irrelevant here, make signed?
|
||||
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)
|
||||
if err != nil {
|
||||
// TODO(roasbeef): push ErrorGeneric message
|
||||
fndgLog.Errorf("Unable to initialize reservation: %v", err)
|
||||
@ -350,6 +353,8 @@ func (f *fundingManager) handleFundingRequest(fmsg *fundingRequestMsg) {
|
||||
return
|
||||
}
|
||||
|
||||
reservation.SetTheirDustLimit(theirDustlimit)
|
||||
|
||||
// Once the reservation has been created successfully, we add it to this
|
||||
// peers map of pending reservations to track this particular reservation
|
||||
// until either abort or completion.
|
||||
@ -396,7 +401,7 @@ func (f *fundingManager) handleFundingRequest(fmsg *fundingRequestMsg) {
|
||||
fundingResp := lnwire.NewSingleFundingResponse(msg.ChannelID,
|
||||
ourContribution.RevocationKey, ourContribution.CommitKey,
|
||||
ourContribution.MultiSigKey, ourContribution.CsvDelay,
|
||||
deliveryScript)
|
||||
deliveryScript, ourDustLimit)
|
||||
|
||||
fmsg.peer.queueMsg(fundingResp, nil)
|
||||
}
|
||||
@ -425,6 +430,8 @@ func (f *fundingManager) handleFundingResponse(fmsg *fundingResponseMsg) {
|
||||
|
||||
fndgLog.Infof("Recv'd fundingResponse for pendingID(%v)", msg.ChannelID)
|
||||
|
||||
resCtx.reservation.SetTheirDustLimit(msg.DustLimit)
|
||||
|
||||
// The remote node has responded with their portion of the channel
|
||||
// contribution. At this point, we can process their contribution which
|
||||
// allows us to construct and sign both the commitment transaction, and
|
||||
@ -747,22 +754,24 @@ func (f *fundingManager) initFundingWorkflow(targetPeer *peer, req *openChanReq)
|
||||
func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
|
||||
var (
|
||||
// TODO(roasbeef): add delay
|
||||
nodeID = msg.peer.addr.IdentityKey
|
||||
localAmt = msg.localFundingAmt
|
||||
remoteAmt = msg.remoteFundingAmt
|
||||
capacity = localAmt + remoteAmt
|
||||
numConfs = msg.numConfs
|
||||
nodeID = msg.peer.addr.IdentityKey
|
||||
localAmt = msg.localFundingAmt
|
||||
remoteAmt = msg.remoteFundingAmt
|
||||
capacity = localAmt + remoteAmt
|
||||
numConfs = msg.numConfs
|
||||
ourDustLimit = lnwallet.DefaultDustLimit()
|
||||
)
|
||||
|
||||
fndgLog.Infof("Initiating fundingRequest(localAmt=%v, remoteAmt=%v, "+
|
||||
"capacity=%v, numConfs=%v, addr=%v)", localAmt, remoteAmt,
|
||||
capacity, numConfs, msg.peer.addr.Address)
|
||||
"capacity=%v, numConfs=%v, addr=%v, dustLimit=%v)", localAmt,
|
||||
remoteAmt, ourDustLimit, capacity, numConfs,
|
||||
msg.peer.addr.Address)
|
||||
|
||||
// Initialize a funding reservation with the local wallet. If the
|
||||
// wallet doesn't have enough funds to commit to this channel, then
|
||||
// the request will fail, and be aborted.
|
||||
reservation, err := f.wallet.InitChannelReservation(capacity, localAmt,
|
||||
nodeID, msg.peer.addr.Address, uint16(numConfs), 4)
|
||||
nodeID, msg.peer.addr.Address, uint16(numConfs), 4, ourDustLimit)
|
||||
if err != nil {
|
||||
msg.err <- err
|
||||
return
|
||||
@ -815,6 +824,7 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
|
||||
contribution.CommitKey,
|
||||
contribution.MultiSigKey,
|
||||
deliveryScript,
|
||||
ourDustLimit,
|
||||
)
|
||||
msg.peer.queueMsg(fundingReq, nil)
|
||||
}
|
||||
|
@ -881,19 +881,21 @@ func (lc *LightningChannel) fetchCommitmentView(remoteChain bool,
|
||||
var selfKey *btcec.PublicKey
|
||||
var remoteKey *btcec.PublicKey
|
||||
var delay uint32
|
||||
var delayBalance, p2wkhBalance btcutil.Amount
|
||||
var delayBalance, p2wkhBalance, dustLimit btcutil.Amount
|
||||
if remoteChain {
|
||||
selfKey = lc.channelState.TheirCommitKey
|
||||
remoteKey = lc.channelState.OurCommitKey
|
||||
delay = lc.channelState.RemoteCsvDelay
|
||||
delayBalance = theirBalance
|
||||
p2wkhBalance = ourBalance
|
||||
dustLimit = lc.channelState.TheirDustLimit
|
||||
} else {
|
||||
selfKey = lc.channelState.OurCommitKey
|
||||
remoteKey = lc.channelState.TheirCommitKey
|
||||
delay = lc.channelState.LocalCsvDelay
|
||||
delayBalance = ourBalance
|
||||
p2wkhBalance = theirBalance
|
||||
dustLimit = lc.channelState.OurDustLimit
|
||||
}
|
||||
|
||||
// Generate a new commitment transaction with all the latest
|
||||
@ -905,6 +907,10 @@ func (lc *LightningChannel) fetchCommitmentView(remoteChain bool,
|
||||
return nil, err
|
||||
}
|
||||
for _, htlc := range filteredHTLCView.ourUpdates {
|
||||
if htlc.Amount < dustLimit {
|
||||
continue
|
||||
}
|
||||
|
||||
err := lc.addHTLC(commitTx, ourCommitTx, htlc,
|
||||
revocationHash, delay, false)
|
||||
if err != nil {
|
||||
@ -912,6 +918,10 @@ func (lc *LightningChannel) fetchCommitmentView(remoteChain bool,
|
||||
}
|
||||
}
|
||||
for _, htlc := range filteredHTLCView.theirUpdates {
|
||||
if htlc.Amount < dustLimit {
|
||||
continue
|
||||
}
|
||||
|
||||
err := lc.addHTLC(commitTx, ourCommitTx, htlc,
|
||||
revocationHash, delay, true)
|
||||
if err != nil {
|
||||
|
@ -188,6 +188,8 @@ func createTestChannels(revocationWindow int) (*LightningChannel, *LightningChan
|
||||
|
||||
channelCapacity := btcutil.Amount(10 * 1e8)
|
||||
channelBal := channelCapacity / 2
|
||||
aliceDustLimit := btcutil.Amount(200)
|
||||
bobDustLimit := btcutil.Amount(800)
|
||||
csvTimeoutAlice := uint32(5)
|
||||
csvTimeoutBob := uint32(4)
|
||||
|
||||
@ -265,6 +267,8 @@ func createTestChannels(revocationWindow int) (*LightningChannel, *LightningChan
|
||||
TheirCurrentRevocation: bobRevokeKey,
|
||||
LocalElkrem: aliceElkrem,
|
||||
RemoteElkrem: &elkrem.ElkremReceiver{},
|
||||
TheirDustLimit: bobDustLimit,
|
||||
OurDustLimit: aliceDustLimit,
|
||||
Db: dbAlice,
|
||||
}
|
||||
bobChannelState := &channeldb.OpenChannel{
|
||||
@ -289,6 +293,8 @@ func createTestChannels(revocationWindow int) (*LightningChannel, *LightningChan
|
||||
TheirCurrentRevocation: aliceRevokeKey,
|
||||
LocalElkrem: bobElkrem,
|
||||
RemoteElkrem: &elkrem.ElkremReceiver{},
|
||||
TheirDustLimit: aliceDustLimit,
|
||||
OurDustLimit: bobDustLimit,
|
||||
Db: dbBob,
|
||||
}
|
||||
|
||||
@ -833,6 +839,122 @@ func TestCheckHTLCNumberConstraint(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
// TestCheckDustLimit checks that unsettled HTLC with dust limit not included in
|
||||
// commitment transaction as output, but sender balance is decreased (thereby all
|
||||
// unsettled dust HTLCs will go to miners fee).
|
||||
func TestCheckDustLimit(t *testing.T) {
|
||||
createHTLC := func(data, amount btcutil.Amount) (*lnwire.HTLCAddRequest,
|
||||
[32]byte) {
|
||||
preimage := bytes.Repeat([]byte{byte(data)}, 32)
|
||||
paymentHash := fastsha256.Sum256(preimage)
|
||||
|
||||
var returnPreimage [32]byte
|
||||
copy(returnPreimage[:], preimage)
|
||||
|
||||
return &lnwire.HTLCAddRequest{
|
||||
RedemptionHashes: [][32]byte{paymentHash},
|
||||
Amount: amount,
|
||||
Expiry: uint32(5),
|
||||
}, returnPreimage
|
||||
}
|
||||
|
||||
// Create a test channel which will be used for the duration of this
|
||||
// unittest. The channel will be funded evenly with Alice having 5 BTC,
|
||||
// and Bob having 5 BTC.
|
||||
aliceChannel, bobChannel, cleanUp, err := createTestChannels(3)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create test channels: %v", err)
|
||||
}
|
||||
defer cleanUp()
|
||||
|
||||
aliceDustLimit := aliceChannel.channelState.OurDustLimit
|
||||
bobDustLimit := bobChannel.channelState.OurDustLimit
|
||||
htlcAmount := btcutil.Amount(500)
|
||||
|
||||
if !((htlcAmount > aliceDustLimit) && (bobDustLimit > htlcAmount)) {
|
||||
t.Fatal("htlc amount needs to be above Alice's dust limit, but " +
|
||||
"below Bob's dust limit .")
|
||||
}
|
||||
|
||||
aliceAmount := aliceChannel.channelState.OurBalance
|
||||
bobAmount := bobChannel.channelState.OurBalance
|
||||
|
||||
htlc, preimage := createHTLC(0, htlcAmount)
|
||||
if _, err := aliceChannel.AddHTLC(htlc); err != nil {
|
||||
t.Fatalf("alice unable to add htlc: %v", err)
|
||||
}
|
||||
if _, err := bobChannel.ReceiveHTLC(htlc); err != nil {
|
||||
t.Fatalf("bob unable to receive htlc: %v", err)
|
||||
}
|
||||
if err := forceStateTransition(aliceChannel, bobChannel); err != nil {
|
||||
t.Fatalf("Can't update the channel state: %v", err)
|
||||
}
|
||||
|
||||
// First two outputs are payment to them and to us. If we encounter
|
||||
// third output it means that dust HTLC was included. Their channel
|
||||
// balance shouldn't change because, it will be changed only after
|
||||
// HTLC will be settled.
|
||||
|
||||
// From Alice point of view HTLC's amount is bigger then dust limit.
|
||||
commitment := aliceChannel.localCommitChain.tip()
|
||||
if len(commitment.txn.TxOut) != 3 {
|
||||
t.Fatal("htlc wasn't added")
|
||||
}
|
||||
if commitment.ourBalance != aliceAmount-htlcAmount {
|
||||
t.Fatal("our balance wasn't updated")
|
||||
}
|
||||
if commitment.theirBalance != bobAmount {
|
||||
t.Fatal("their balance was updated")
|
||||
}
|
||||
|
||||
// From Bob point of view HTLC's amount is lower then dust limit.
|
||||
commitment = bobChannel.localCommitChain.tip()
|
||||
if len(commitment.txn.TxOut) != 2 {
|
||||
t.Fatal("HTLC with dust amount was added")
|
||||
}
|
||||
if commitment.theirBalance != aliceAmount-htlcAmount {
|
||||
t.Fatal("their balance wasn't updated")
|
||||
}
|
||||
if commitment.ourBalance != bobAmount {
|
||||
t.Fatal("our balance was updated")
|
||||
}
|
||||
|
||||
// Settle HTLC and sign new commitment.
|
||||
settleIndex, err := bobChannel.SettleHTLC(preimage)
|
||||
if err != nil {
|
||||
t.Fatalf("bob unable to settle inbound htlc: %v", err)
|
||||
}
|
||||
err = aliceChannel.ReceiveHTLCSettle(preimage, settleIndex)
|
||||
if err != nil {
|
||||
t.Fatalf("alice unable to accept settle of outbound htlc: %v", err)
|
||||
}
|
||||
if err := forceStateTransition(aliceChannel, bobChannel); err != nil {
|
||||
t.Fatalf("Can't update the channel state: %v", err)
|
||||
}
|
||||
|
||||
commitment = aliceChannel.localCommitChain.tip()
|
||||
if len(commitment.txn.TxOut) != 2 {
|
||||
t.Fatal("HTLC wasn't settled")
|
||||
}
|
||||
if commitment.ourBalance != aliceAmount-htlcAmount {
|
||||
t.Fatal("our balance wasn't updated")
|
||||
}
|
||||
if commitment.theirBalance != bobAmount+htlcAmount {
|
||||
t.Fatal("their balance wasn't updated")
|
||||
}
|
||||
|
||||
commitment = bobChannel.localCommitChain.tip()
|
||||
if len(commitment.txn.TxOut) != 2 {
|
||||
t.Fatal("HTLC with dust amount wasn't settled")
|
||||
}
|
||||
if commitment.ourBalance != bobAmount+htlcAmount {
|
||||
t.Fatal("our balance wasn't updated")
|
||||
}
|
||||
if commitment.theirBalance != aliceAmount-htlcAmount {
|
||||
t.Fatal("their balance wasn't updated")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStateUpdatePersistence(t *testing.T) {
|
||||
// Create a test channel which will be used for the duration of this
|
||||
// unittest. The channel will be funded evenly with Alice having 5 BTC,
|
||||
|
@ -363,7 +363,7 @@ func testDualFundingReservationWorkflow(miner *rpctest.Harness, wallet *lnwallet
|
||||
// Bob initiates a channel funded with 5 BTC for each side, so 10
|
||||
// BTC total. He also generates 2 BTC in change.
|
||||
chanReservation, err := wallet.InitChannelReservation(fundingAmount*2,
|
||||
fundingAmount, bobNode.id, bobAddr, numReqConfs, 4)
|
||||
fundingAmount, bobNode.id, bobAddr, numReqConfs, 4, 540)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to initialize funding reservation: %v", err)
|
||||
}
|
||||
@ -522,7 +522,7 @@ func testFundingTransactionLockedOutputs(miner *rpctest.Harness,
|
||||
// Create a single channel asking for 16 BTC total.
|
||||
fundingAmount := btcutil.Amount(8 * 1e8)
|
||||
_, err := wallet.InitChannelReservation(fundingAmount, fundingAmount,
|
||||
testPub, bobAddr, numReqConfs, 4)
|
||||
testPub, bobAddr, numReqConfs, 4, 540)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to initialize funding reservation 1: %v", err)
|
||||
}
|
||||
@ -532,7 +532,7 @@ func testFundingTransactionLockedOutputs(miner *rpctest.Harness,
|
||||
// that aren't locked, so this should fail.
|
||||
amt := btcutil.Amount(900 * 1e8)
|
||||
failedReservation, err := wallet.InitChannelReservation(amt, amt,
|
||||
testPub, bobAddr, numReqConfs, 4)
|
||||
testPub, bobAddr, numReqConfs, 4, 540)
|
||||
if err == nil {
|
||||
t.Fatalf("not error returned, should fail on coin selection")
|
||||
}
|
||||
@ -552,14 +552,14 @@ func testFundingCancellationNotEnoughFunds(miner *rpctest.Harness,
|
||||
// Create a reservation for 44 BTC.
|
||||
fundingAmount := btcutil.Amount(44 * 1e8)
|
||||
chanReservation, err := wallet.InitChannelReservation(fundingAmount,
|
||||
fundingAmount, testPub, bobAddr, numReqConfs, 4)
|
||||
fundingAmount, testPub, bobAddr, numReqConfs, 4, 540)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to initialize funding reservation: %v", err)
|
||||
}
|
||||
|
||||
// Attempt to create another channel with 44 BTC, this should fail.
|
||||
_, err = wallet.InitChannelReservation(fundingAmount,
|
||||
fundingAmount, testPub, bobAddr, numReqConfs, 4)
|
||||
fundingAmount, testPub, bobAddr, numReqConfs, 4, 540)
|
||||
if _, ok := err.(*lnwallet.ErrInsufficientFunds); !ok {
|
||||
t.Fatalf("coin selection succeded should have insufficient funds: %v",
|
||||
err)
|
||||
@ -589,7 +589,7 @@ func testFundingCancellationNotEnoughFunds(miner *rpctest.Harness,
|
||||
|
||||
// Request to fund a new channel should now succeed.
|
||||
_, err = wallet.InitChannelReservation(fundingAmount, fundingAmount,
|
||||
testPub, bobAddr, numReqConfs, 4)
|
||||
testPub, bobAddr, numReqConfs, 4, 540)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to initialize funding reservation: %v", err)
|
||||
}
|
||||
@ -628,7 +628,7 @@ func testSingleFunderReservationWorkflowInitiator(miner *rpctest.Harness,
|
||||
// Initialize a reservation for a channel with 4 BTC funded solely by us.
|
||||
fundingAmt := btcutil.Amount(4 * 1e8)
|
||||
chanReservation, err := lnwallet.InitChannelReservation(fundingAmt,
|
||||
fundingAmt, bobNode.id, bobAddr, numReqConfs, 4)
|
||||
fundingAmt, bobNode.id, bobAddr, numReqConfs, 4, 540)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to init channel reservation: %v", err)
|
||||
}
|
||||
@ -769,7 +769,7 @@ func testSingleFunderReservationWorkflowResponder(miner *rpctest.Harness,
|
||||
// contribution and the necessary resources.
|
||||
fundingAmt := btcutil.Amount(0)
|
||||
chanReservation, err := wallet.InitChannelReservation(capacity,
|
||||
fundingAmt, bobNode.id, bobAddr, numReqConfs, 4)
|
||||
fundingAmt, bobNode.id, bobAddr, numReqConfs, 4, 540)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to init channel reservation: %v", err)
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
package lnwallet
|
||||
|
||||
import (
|
||||
"github.com/roasbeef/btcwallet/wallet/txrules"
|
||||
"github.com/roasbeef/btcutil"
|
||||
"github.com/roasbeef/btcwallet/wallet/txrules"
|
||||
)
|
||||
|
||||
// DefaultDustLimit is used to calculate the dust HTLC amount which will be
|
||||
// proposed to other node during channel creation.
|
||||
// send to other node during funding process.
|
||||
func DefaultDustLimit() btcutil.Amount {
|
||||
return txrules.GetDustThreshold(P2WSHSize, txrules.DefaultRelayFeePerKb)
|
||||
}
|
||||
|
@ -382,6 +382,14 @@ func (r *ChannelReservation) LocalCommitTx() *wire.MsgTx {
|
||||
return r.partialState.OurCommitTx
|
||||
}
|
||||
|
||||
// SetDustLimit set dust limit of the remote party.
|
||||
func (r *ChannelReservation) SetTheirDustLimit(dustLimit btcutil.Amount) {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
r.partialState.TheirDustLimit = dustLimit
|
||||
}
|
||||
|
||||
// FundingOutpoint returns the outpoint of the funding transaction.
|
||||
//
|
||||
// NOTE: The pointer returned will only be set once the .ProcesContribution()
|
||||
|
@ -100,6 +100,11 @@ type initFundingReserveMsg struct {
|
||||
// TODO(roasbeef): integrate fee estimation project...
|
||||
minFeeRate btcutil.Amount
|
||||
|
||||
// ourDustLimit is the threshold below which no HTLC output should be
|
||||
// generated for our commitment transaction; ie. HTLCs below
|
||||
// this amount are not enforceable onchain from our point of view.
|
||||
ourDustLimit btcutil.Amount
|
||||
|
||||
// The delay on the "pay-to-self" output(s) of the commitment transaction.
|
||||
csvDelay uint32
|
||||
|
||||
@ -484,7 +489,7 @@ out:
|
||||
func (l *LightningWallet) InitChannelReservation(capacity,
|
||||
ourFundAmt btcutil.Amount, theirID *btcec.PublicKey,
|
||||
theirAddr *net.TCPAddr, numConfs uint16,
|
||||
csvDelay uint32) (*ChannelReservation, error) {
|
||||
csvDelay uint32, ourDustLimit btcutil.Amount) (*ChannelReservation, error) {
|
||||
|
||||
errChan := make(chan error, 1)
|
||||
respChan := make(chan *ChannelReservation, 1)
|
||||
@ -494,6 +499,7 @@ func (l *LightningWallet) InitChannelReservation(capacity,
|
||||
numConfs: numConfs,
|
||||
fundingAmount: ourFundAmt,
|
||||
csvDelay: csvDelay,
|
||||
ourDustLimit: ourDustLimit,
|
||||
nodeID: theirID,
|
||||
err: errChan,
|
||||
resp: respChan,
|
||||
@ -522,11 +528,14 @@ func (l *LightningWallet) handleFundingReserveRequest(req *initFundingReserveMsg
|
||||
reservation.Lock()
|
||||
defer reservation.Unlock()
|
||||
|
||||
reservation.partialState.IdentityPub = req.nodeID
|
||||
reservation.nodeAddr = req.nodeAddr
|
||||
ourContribution := reservation.ourContribution
|
||||
ourContribution.CsvDelay = req.csvDelay
|
||||
reservation.ourContribution.CsvDelay = req.csvDelay
|
||||
|
||||
reservation.partialState.IdentityPub = req.nodeID
|
||||
reservation.partialState.LocalCsvDelay = req.csvDelay
|
||||
reservation.partialState.OurDustLimit = req.ourDustLimit
|
||||
|
||||
ourContribution := reservation.ourContribution
|
||||
|
||||
// If we're on the receiving end of a single funder channel then we
|
||||
// don't need to perform any coin selection. Otherwise, attempt to
|
||||
|
8
peer.go
8
peer.go
@ -390,13 +390,7 @@ out:
|
||||
// * .(CommitmentUpdater)
|
||||
|
||||
case *lnwire.ErrorGeneric:
|
||||
switch msg.Code {
|
||||
case lnwire.ErrorMaxPendingChannels:
|
||||
p.server.fundingMgr.processErrorGeneric(msg, p)
|
||||
default:
|
||||
peerLog.Warnf("ErrorGeneric(%v) handling isn't"+
|
||||
" implemented.", msg.Code)
|
||||
}
|
||||
p.server.fundingMgr.processErrorGeneric(msg, p)
|
||||
case *lnwire.HTLCAddRequest:
|
||||
isChanUpdate = true
|
||||
targetChan = msg.ChannelPoint
|
||||
|
@ -455,9 +455,9 @@ func (s *server) handleOpenChanReq(req *openChanReq) {
|
||||
}
|
||||
|
||||
// Spawn a goroutine to send the funding workflow request to the funding
|
||||
// manager. This allows the server to continue handling queries instead of
|
||||
// blocking on this request which is exporeted as a synchronous request to
|
||||
// the outside world.
|
||||
// manager. This allows the server to continue handling queries instead
|
||||
// of blocking on this request which is exported as a synchronous
|
||||
// request to the outside world.
|
||||
// TODO(roasbeef): server semaphore to restrict num goroutines
|
||||
go s.fundingMgr.initFundingWorkflow(targetPeer, req)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user