peer: modify channel closing negotiation to create new delivery scripts
This commit modifies the channel close negotiation workflow to instead take not of the fat that with the new funding workflow, the delivery scripts are no longer pre-committed to at the start of the funding workflow. Instead, both sides present their delivery addresses at the start of the shutdown process, then use those to create the final cooperative closure transaction. To accommodate for this new change, we now have an intermediate staging area where we store the delivery scripts for both sides.
This commit is contained in:
parent
01fe9adff0
commit
cd7b3290a8
203
peer.go
203
peer.go
@ -750,6 +750,15 @@ func (p *peer) ChannelSnapshots() []*channeldb.ChannelSnapshot {
|
|||||||
return <-resp
|
return <-resp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// closingScripts are the set of clsoign deslivery scripts for each party. This
|
||||||
|
// intermediate state is maintained for each active close negotiation, as the
|
||||||
|
// final signatures sent must cover the specified delivery scripts for each
|
||||||
|
// party.
|
||||||
|
type closingScripts struct {
|
||||||
|
localScript []byte
|
||||||
|
remoteScript []byte
|
||||||
|
}
|
||||||
|
|
||||||
// channelManager is goroutine dedicated to handling all requests/signals
|
// channelManager is goroutine dedicated to handling all requests/signals
|
||||||
// pertaining to the opening, cooperative closing, and force closing of all
|
// pertaining to the opening, cooperative closing, and force closing of all
|
||||||
// channels maintained with the remote peer.
|
// channels maintained with the remote peer.
|
||||||
@ -762,11 +771,27 @@ func (p *peer) channelManager() {
|
|||||||
// workflow.
|
// workflow.
|
||||||
chanShutdowns := make(map[lnwire.ChannelID]*htlcswitch.ChanClose)
|
chanShutdowns := make(map[lnwire.ChannelID]*htlcswitch.ChanClose)
|
||||||
|
|
||||||
|
deliveryAddrs := make(map[lnwire.ChannelID]*closingScripts)
|
||||||
|
|
||||||
// shutdownSigs is a map of signatures maintained by the responder in a
|
// shutdownSigs is a map of signatures maintained by the responder in a
|
||||||
// cooperative channel close. This map enables us to respond to
|
// cooperative channel close. This map enables us to respond to
|
||||||
// subsequent steps in the workflow without having to recalculate our
|
// subsequent steps in the workflow without having to recalculate our
|
||||||
// signature for the channel close transaction.
|
// signature for the channel close transaction.
|
||||||
shutdownSigs := make(map[lnwire.ChannelID][]byte)
|
shutdownSigs := make(map[lnwire.ChannelID][]byte)
|
||||||
|
|
||||||
|
// TODO(roasbeef): move to cfg closure func
|
||||||
|
genDeliveryScript := func() ([]byte, error) {
|
||||||
|
deliveryAddr, err := p.server.cc.wallet.NewAddress(
|
||||||
|
lnwallet.WitnessPubKey, false,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
peerLog.Infof("Delivery addr for channel close: %v",
|
||||||
|
deliveryAddr)
|
||||||
|
|
||||||
|
return txscript.PayToAddrScript(deliveryAddr)
|
||||||
|
}
|
||||||
out:
|
out:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
@ -781,33 +806,43 @@ out:
|
|||||||
p.activeChanMtx.RUnlock()
|
p.activeChanMtx.RUnlock()
|
||||||
req.resp <- snapshots
|
req.resp <- snapshots
|
||||||
|
|
||||||
|
// A new channel has arrived which means we've just completed a
|
||||||
|
// funding workflow. We'll initialize the necessary local
|
||||||
|
// state, and notify the htlc switch of a new link.
|
||||||
case newChanReq := <-p.newChannels:
|
case newChanReq := <-p.newChannels:
|
||||||
chanPoint := newChanReq.channel.ChannelPoint()
|
chanPoint := newChanReq.channel.ChannelPoint()
|
||||||
chanID := lnwire.NewChanIDFromOutPoint(chanPoint)
|
chanID := lnwire.NewChanIDFromOutPoint(chanPoint)
|
||||||
|
newChan := newChanReq.channel
|
||||||
|
|
||||||
|
// First, we'll add this channel to the set of active
|
||||||
|
// channels, so we can look it up later easily
|
||||||
|
// according to its channel ID.
|
||||||
p.activeChanMtx.Lock()
|
p.activeChanMtx.Lock()
|
||||||
p.activeChannels[chanID] = newChanReq.channel
|
p.activeChannels[chanID] = newChan
|
||||||
p.activeChanMtx.Unlock()
|
p.activeChanMtx.Unlock()
|
||||||
|
|
||||||
peerLog.Infof("New channel active ChannelPoint(%v) "+
|
peerLog.Infof("New channel active ChannelPoint(%v) "+
|
||||||
"with peerId(%v)", chanPoint, p.id)
|
"with peerId(%v)", chanPoint, p.id)
|
||||||
|
|
||||||
link := htlcswitch.NewChannelLink(
|
// Next, we'll assemble a ChannelLink along with the
|
||||||
htlcswitch.ChannelLinkConfig{
|
// necessary items it needs to function.
|
||||||
Peer: p,
|
linkConfig := htlcswitch.ChannelLinkConfig{
|
||||||
DecodeHopIterator: p.server.sphinx.DecodeHopIterator,
|
Peer: p,
|
||||||
DecodeOnionObfuscator: p.server.sphinx.DecodeOnionObfuscator,
|
DecodeHopIterator: p.server.sphinx.DecodeHopIterator,
|
||||||
GetLastChannelUpdate: createGetLastUpdate(p.server.chanRouter,
|
DecodeOnionObfuscator: p.server.sphinx.DecodeOnionObfuscator,
|
||||||
p.PubKey(), newChanReq.channel.ShortChanID()),
|
GetLastChannelUpdate: createGetLastUpdate(p.server.chanRouter,
|
||||||
SettledContracts: p.server.breachArbiter.settledContracts,
|
p.PubKey(), newChanReq.channel.ShortChanID()),
|
||||||
DebugHTLC: cfg.DebugHTLC,
|
SettledContracts: p.server.breachArbiter.settledContracts,
|
||||||
Registry: p.server.invoices,
|
DebugHTLC: cfg.DebugHTLC,
|
||||||
Switch: p.server.htlcSwitch,
|
Registry: p.server.invoices,
|
||||||
FwrdingPolicy: p.server.cc.routingPolicy,
|
Switch: p.server.htlcSwitch,
|
||||||
},
|
FwrdingPolicy: p.server.cc.routingPolicy,
|
||||||
newChanReq.channel,
|
}
|
||||||
)
|
link := htlcswitch.NewChannelLink(linkConfig, newChan)
|
||||||
|
|
||||||
|
// With the channel link created, we'll now notify the
|
||||||
|
// htlc switch so this channel can be used to dispatch
|
||||||
|
// local payments and also passively forward payments.
|
||||||
err := p.server.htlcSwitch.AddLink(link)
|
err := p.server.htlcSwitch.AddLink(link)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
peerLog.Errorf("can't register new channel "+
|
peerLog.Errorf("can't register new channel "+
|
||||||
@ -826,58 +861,117 @@ out:
|
|||||||
// We'll only track this shutdown request if this is a
|
// We'll only track this shutdown request if this is a
|
||||||
// regular close request, and not in response to a
|
// regular close request, and not in response to a
|
||||||
// channel breach.
|
// channel breach.
|
||||||
|
var (
|
||||||
|
deliveryScript []byte
|
||||||
|
err error
|
||||||
|
)
|
||||||
if req.CloseType == htlcswitch.CloseRegular {
|
if req.CloseType == htlcswitch.CloseRegular {
|
||||||
chanShutdowns[chanID] = req
|
chanShutdowns[chanID] = req
|
||||||
|
|
||||||
|
// As we need to close out the channel and
|
||||||
|
// claim our funds on-chain, we'll request a
|
||||||
|
// new delivery address from the wallet, and
|
||||||
|
// turn that into it corresponding output
|
||||||
|
// script.
|
||||||
|
deliveryScript, err = genDeliveryScript()
|
||||||
|
if err != nil {
|
||||||
|
cErr := fmt.Errorf("Unable to generate "+
|
||||||
|
"delivery address: %v", err)
|
||||||
|
|
||||||
|
peerLog.Errorf(cErr.Error())
|
||||||
|
|
||||||
|
req.Err <- cErr
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// We'll also track this delivery script, as
|
||||||
|
// we'll need it to reconstruct the cooperative
|
||||||
|
// closure transaction during our closing fee
|
||||||
|
// negotiation ratchet.
|
||||||
|
deliveryAddrs[chanID] = &closingScripts{
|
||||||
|
localScript: deliveryScript,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// With the state marked as shutting down, we can now
|
// With the state marked as shutting down, we can now
|
||||||
// proceed with the channel close workflow. If this is
|
// proceed with the channel close workflow. If this is
|
||||||
// regular close, we'll send a shutdown. Otherwise,
|
// regular close, we'll send a shutdown. Otherwise,
|
||||||
// we'll simply be clearing our indexes.
|
// we'll simply be clearing our indexes.
|
||||||
p.handleLocalClose(req)
|
p.handleLocalClose(req, deliveryScript)
|
||||||
|
|
||||||
// A receipt of a message over this channel indicates that
|
// A receipt of a message over this channel indicates that
|
||||||
// either a shutdown proposal has been initiated, or a prior
|
// either a shutdown proposal has been initiated, or a prior
|
||||||
// one has been completed, advancing to the next state of
|
// one has been completed, advancing to the next state of
|
||||||
// channel closure.
|
// channel closure.
|
||||||
case req := <-p.shutdownChanReqs:
|
case req := <-p.shutdownChanReqs:
|
||||||
// We've just received a shutdown request. First, we'll
|
// If we don't have a channel that matches this channel
|
||||||
// check in the shutdown map to see if we're the
|
// ID, then we'll ignore this message.
|
||||||
// initiator or not. If we don't have an entry for
|
chanID := req.ChannelID
|
||||||
// this channel, then this means that we're the
|
p.activeChanMtx.Lock()
|
||||||
// responder to the workflow.
|
_, ok := p.activeChannels[chanID]
|
||||||
|
p.activeChanMtx.Unlock()
|
||||||
|
if !ok {
|
||||||
|
peerLog.Warnf("Received unsolicited shutdown msg: %v",
|
||||||
|
spew.Sdump(req))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// First, we'll track their delivery script for when we
|
||||||
|
// ultimately create the cooperative closure
|
||||||
|
// transaction.
|
||||||
|
deliveryScripts, ok := deliveryAddrs[chanID]
|
||||||
|
if !ok {
|
||||||
|
deliveryAddrs[chanID] = &closingScripts{}
|
||||||
|
deliveryScripts = deliveryAddrs[chanID]
|
||||||
|
}
|
||||||
|
deliveryScripts.remoteScript = req.Address
|
||||||
|
|
||||||
|
// Next, we'll check in the shutdown map to see if
|
||||||
|
// we're the initiator or not. If we don't have an
|
||||||
|
// entry for this channel, then this means that we're
|
||||||
|
// the responder to the workflow.
|
||||||
if _, ok := chanShutdowns[req.ChannelID]; !ok {
|
if _, ok := chanShutdowns[req.ChannelID]; !ok {
|
||||||
|
// As we're the responder, we'll need to
|
||||||
|
// generate a delivery script of our own.
|
||||||
|
deliveryScript, err := genDeliveryScript()
|
||||||
|
if err != nil {
|
||||||
|
peerLog.Errorf("Unable to generate "+
|
||||||
|
"delivery address: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
deliveryScripts.localScript = deliveryScript
|
||||||
|
|
||||||
// In this case, we'll send a shutdown message,
|
// In this case, we'll send a shutdown message,
|
||||||
// and also prep our closing signature for the
|
// and also prep our closing signature for the
|
||||||
// case they fees are immediately agreed upon.
|
// case they fees are immediately agreed upon.
|
||||||
closeSig := p.handleShutdownResponse(req)
|
closeSig := p.handleShutdownResponse(req,
|
||||||
|
deliveryScript)
|
||||||
if closeSig != nil {
|
if closeSig != nil {
|
||||||
shutdownSigs[req.ChannelID] = closeSig
|
shutdownSigs[chanID] = closeSig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(roasbeef): should also save their delivery
|
|
||||||
// address within close request after funding change.
|
|
||||||
// * modify complete to include delivery address
|
|
||||||
|
|
||||||
// A receipt of a message over this channel indicates that the
|
// A receipt of a message over this channel indicates that the
|
||||||
// final stage of a channel shutdown workflow has been
|
// final stage of a channel shutdown workflow has been
|
||||||
// completed.
|
// completed.
|
||||||
case req := <-p.closingSignedChanReqs:
|
case req := <-p.closingSignedChanReqs:
|
||||||
// First we'll check if this has an entry in the local
|
// First we'll check if this has an entry in the local
|
||||||
// shutdown map.
|
// shutdown map.
|
||||||
localCloseReq, ok := chanShutdowns[req.ChannelID]
|
chanID := req.ChannelID
|
||||||
|
localCloseReq, ok := chanShutdowns[chanID]
|
||||||
|
|
||||||
// If it does, then this means we were the initiator of
|
// If it does, then this means we were the initiator of
|
||||||
// the channel shutdown procedure.
|
// the channel shutdown procedure.
|
||||||
if ok {
|
if ok {
|
||||||
// To finalize this shtudown, we'll now send a
|
// To finalize this shutdown, we'll now send a
|
||||||
// matching close signed message to the other
|
// matching close signed message to the other
|
||||||
// party, and broadcast the closing transaction
|
// party, and broadcast the closing transaction
|
||||||
// to the network.
|
// to the network.
|
||||||
p.handleInitClosingSigned(localCloseReq, req)
|
p.handleInitClosingSigned(localCloseReq, req,
|
||||||
|
deliveryAddrs[chanID])
|
||||||
|
|
||||||
delete(chanShutdowns, req.ChannelID)
|
delete(chanShutdowns, req.ChannelID)
|
||||||
|
delete(deliveryAddrs, req.ChannelID)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -886,10 +980,13 @@ out:
|
|||||||
// channel as pending close, and watch the network for
|
// channel as pending close, and watch the network for
|
||||||
// the ultimate confirmation of the closing
|
// the ultimate confirmation of the closing
|
||||||
// transaction.
|
// transaction.
|
||||||
responderSig := append(shutdownSigs[req.ChannelID],
|
responderSig := append(shutdownSigs[chanID],
|
||||||
byte(txscript.SigHashAll))
|
byte(txscript.SigHashAll))
|
||||||
p.handleResponseClosingSigned(req, responderSig)
|
p.handleResponseClosingSigned(req, responderSig,
|
||||||
delete(shutdownSigs, req.ChannelID)
|
deliveryAddrs[chanID])
|
||||||
|
|
||||||
|
delete(shutdownSigs, chanID)
|
||||||
|
delete(deliveryAddrs, chanID)
|
||||||
|
|
||||||
case <-p.quit:
|
case <-p.quit:
|
||||||
break out
|
break out
|
||||||
@ -904,7 +1001,7 @@ out:
|
|||||||
//
|
//
|
||||||
// TODO(roasbeef): if no more active channels with peer call Remove on connMgr
|
// TODO(roasbeef): if no more active channels with peer call Remove on connMgr
|
||||||
// with peerID
|
// with peerID
|
||||||
func (p *peer) handleLocalClose(req *htlcswitch.ChanClose) {
|
func (p *peer) handleLocalClose(req *htlcswitch.ChanClose, deliveryScript []byte) {
|
||||||
chanID := lnwire.NewChanIDFromOutPoint(req.ChanPoint)
|
chanID := lnwire.NewChanIDFromOutPoint(req.ChanPoint)
|
||||||
|
|
||||||
p.activeChanMtx.RLock()
|
p.activeChanMtx.RLock()
|
||||||
@ -919,11 +1016,12 @@ func (p *peer) handleLocalClose(req *htlcswitch.ChanClose) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch req.CloseType {
|
switch req.CloseType {
|
||||||
|
|
||||||
// A type of CloseRegular indicates that the user has opted to close
|
// A type of CloseRegular indicates that the user has opted to close
|
||||||
// out this channel on-chain, so we execute the cooperative channel
|
// out this channel on-chain, so we execute the cooperative channel
|
||||||
// closure workflow.
|
// closure workflow.
|
||||||
case htlcswitch.CloseRegular:
|
case htlcswitch.CloseRegular:
|
||||||
err := p.sendShutdown(channel)
|
err := p.sendShutdown(channel, deliveryScript)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
req.Err <- err
|
req.Err <- err
|
||||||
return
|
return
|
||||||
@ -932,6 +1030,7 @@ func (p *peer) handleLocalClose(req *htlcswitch.ChanClose) {
|
|||||||
// A type of CloseBreach indicates that the counterparty has breached
|
// A type of CloseBreach indicates that the counterparty has breached
|
||||||
// the channel therefore we need to clean up our local state.
|
// the channel therefore we need to clean up our local state.
|
||||||
case htlcswitch.CloseBreach:
|
case htlcswitch.CloseBreach:
|
||||||
|
// TODO(roasbeef): no longer need with newer beach logic?
|
||||||
peerLog.Infof("ChannelPoint(%v) has been breached, wiping "+
|
peerLog.Infof("ChannelPoint(%v) has been breached, wiping "+
|
||||||
"channel", req.ChanPoint)
|
"channel", req.ChanPoint)
|
||||||
if err := p.WipeChannel(channel); err != nil {
|
if err := p.WipeChannel(channel); err != nil {
|
||||||
@ -948,7 +1047,9 @@ func (p *peer) handleLocalClose(req *htlcswitch.ChanClose) {
|
|||||||
// close workflow receives a Shutdown message. This is the second step in the
|
// close workflow receives a Shutdown message. This is the second step in the
|
||||||
// cooperative close workflow. This function generates a close transaction with
|
// cooperative close workflow. This function generates a close transaction with
|
||||||
// a proposed fee amount and sends the signed transaction to the initiator.
|
// a proposed fee amount and sends the signed transaction to the initiator.
|
||||||
func (p *peer) handleShutdownResponse(msg *lnwire.Shutdown) []byte {
|
func (p *peer) handleShutdownResponse(msg *lnwire.Shutdown,
|
||||||
|
localDeliveryScript []byte) []byte {
|
||||||
|
|
||||||
p.activeChanMtx.RLock()
|
p.activeChanMtx.RLock()
|
||||||
channel, ok := p.activeChannels[msg.ChannelID]
|
channel, ok := p.activeChannels[msg.ChannelID]
|
||||||
p.activeChanMtx.RUnlock()
|
p.activeChanMtx.RUnlock()
|
||||||
@ -960,7 +1061,8 @@ func (p *peer) handleShutdownResponse(msg *lnwire.Shutdown) []byte {
|
|||||||
|
|
||||||
// As we just received a shutdown message, we'll also send a shutdown
|
// As we just received a shutdown message, we'll also send a shutdown
|
||||||
// message with our desired fee so we can start the negotiation.
|
// message with our desired fee so we can start the negotiation.
|
||||||
if err := p.sendShutdown(channel); err != nil {
|
err := p.sendShutdown(channel, localDeliveryScript)
|
||||||
|
if err != nil {
|
||||||
peerLog.Errorf("error while sending shutdown message: %v", err)
|
peerLog.Errorf("error while sending shutdown message: %v", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -973,8 +1075,9 @@ func (p *peer) handleShutdownResponse(msg *lnwire.Shutdown) []byte {
|
|||||||
|
|
||||||
// Once both sides agree on a fee, we'll create a signature that closes
|
// Once both sides agree on a fee, we'll create a signature that closes
|
||||||
// the channel using the agree upon fee rate.
|
// the channel using the agree upon fee rate.
|
||||||
// TODO(roasbeef): remove encoding redundancy
|
closeSig, proposedFee, err := channel.CreateCloseProposal(
|
||||||
closeSig, proposedFee, err := channel.CreateCloseProposal(feeRate)
|
feeRate, localDeliveryScript, msg.Address,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
peerLog.Errorf("unable to create close proposal: %v", err)
|
peerLog.Errorf("unable to create close proposal: %v", err)
|
||||||
return nil
|
return nil
|
||||||
@ -1008,7 +1111,9 @@ func (p *peer) handleShutdownResponse(msg *lnwire.Shutdown) []byte {
|
|||||||
// of an unresponsive remote party, the initiator can either choose to execute
|
// of an unresponsive remote party, the initiator can either choose to execute
|
||||||
// a force closure, or backoff for a period of time, and retry the cooperative
|
// a force closure, or backoff for a period of time, and retry the cooperative
|
||||||
// closure.
|
// closure.
|
||||||
func (p *peer) handleInitClosingSigned(req *htlcswitch.ChanClose, msg *lnwire.ClosingSigned) {
|
func (p *peer) handleInitClosingSigned(req *htlcswitch.ChanClose,
|
||||||
|
msg *lnwire.ClosingSigned, deliveryScripts *closingScripts) {
|
||||||
|
|
||||||
chanID := lnwire.NewChanIDFromOutPoint(req.ChanPoint)
|
chanID := lnwire.NewChanIDFromOutPoint(req.ChanPoint)
|
||||||
p.activeChanMtx.RLock()
|
p.activeChanMtx.RLock()
|
||||||
channel, ok := p.activeChannels[chanID]
|
channel, ok := p.activeChannels[chanID]
|
||||||
@ -1030,7 +1135,9 @@ func (p *peer) handleInitClosingSigned(req *htlcswitch.ChanClose, msg *lnwire.Cl
|
|||||||
|
|
||||||
// We agree with the proposed channel close transaction and fee rate,
|
// We agree with the proposed channel close transaction and fee rate,
|
||||||
// so generate our signature.
|
// so generate our signature.
|
||||||
initiatorSig, proposedFee, err := channel.CreateCloseProposal(feeRate)
|
initiatorSig, proposedFee, err := channel.CreateCloseProposal(
|
||||||
|
feeRate, deliveryScripts.localScript, deliveryScripts.remoteScript,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
req.Err <- err
|
req.Err <- err
|
||||||
return
|
return
|
||||||
@ -1042,6 +1149,7 @@ func (p *peer) handleInitClosingSigned(req *htlcswitch.ChanClose, msg *lnwire.Cl
|
|||||||
responderSig := msg.Signature
|
responderSig := msg.Signature
|
||||||
respSig := append(responderSig.Serialize(), byte(txscript.SigHashAll))
|
respSig := append(responderSig.Serialize(), byte(txscript.SigHashAll))
|
||||||
closeTx, err := channel.CompleteCooperativeClose(initSig, respSig,
|
closeTx, err := channel.CompleteCooperativeClose(initSig, respSig,
|
||||||
|
deliveryScripts.localScript, deliveryScripts.remoteScript,
|
||||||
feeRate)
|
feeRate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
req.Err <- err
|
req.Err <- err
|
||||||
@ -1150,7 +1258,8 @@ func (p *peer) handleInitClosingSigned(req *htlcswitch.ChanClose, msg *lnwire.Cl
|
|||||||
// close workflow receives a ClosingSigned message. This function handles the
|
// close workflow receives a ClosingSigned message. This function handles the
|
||||||
// finalization of the cooperative close from the perspective of the responder.
|
// finalization of the cooperative close from the perspective of the responder.
|
||||||
func (p *peer) handleResponseClosingSigned(msg *lnwire.ClosingSigned,
|
func (p *peer) handleResponseClosingSigned(msg *lnwire.ClosingSigned,
|
||||||
respSig []byte) {
|
respSig []byte, deliveryScripts *closingScripts) {
|
||||||
|
|
||||||
p.activeChanMtx.RLock()
|
p.activeChanMtx.RLock()
|
||||||
channel, ok := p.activeChannels[msg.ChannelID]
|
channel, ok := p.activeChannels[msg.ChannelID]
|
||||||
p.activeChanMtx.RUnlock()
|
p.activeChanMtx.RUnlock()
|
||||||
@ -1171,6 +1280,7 @@ func (p *peer) handleResponseClosingSigned(msg *lnwire.ClosingSigned,
|
|||||||
// TODO(roasbeef): should instead use the fee within the message
|
// TODO(roasbeef): should instead use the fee within the message
|
||||||
feeRate := p.server.cc.feeEstimator.EstimateFeePerWeight(1) * 1000
|
feeRate := p.server.cc.feeEstimator.EstimateFeePerWeight(1) * 1000
|
||||||
closeTx, err := channel.CompleteCooperativeClose(respSig, initSig,
|
closeTx, err := channel.CompleteCooperativeClose(respSig, initSig,
|
||||||
|
deliveryScripts.localScript, deliveryScripts.remoteScript,
|
||||||
feeRate)
|
feeRate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
peerLog.Errorf("unable to complete cooperative "+
|
peerLog.Errorf("unable to complete cooperative "+
|
||||||
@ -1279,17 +1389,18 @@ func waitForChanToClose(bestHeight uint32, notifier chainntnfs.ChainNotifier,
|
|||||||
// between peers to initiate the cooperative channel close workflow. In
|
// between peers to initiate the cooperative channel close workflow. In
|
||||||
// addition, sendShutdown also signals to the HTLC switch to stop accepting
|
// addition, sendShutdown also signals to the HTLC switch to stop accepting
|
||||||
// HTLCs for the specified channel.
|
// HTLCs for the specified channel.
|
||||||
func (p *peer) sendShutdown(channel *lnwallet.LightningChannel) error {
|
func (p *peer) sendShutdown(channel *lnwallet.LightningChannel,
|
||||||
|
deliveryScript []byte) error {
|
||||||
|
|
||||||
// In order to construct the shutdown message, we'll need to
|
// In order to construct the shutdown message, we'll need to
|
||||||
// reconstruct the channelID, and the current set delivery script for
|
// reconstruct the channelID, and the current set delivery script for
|
||||||
// the channel closure.
|
// the channel closure.
|
||||||
chanID := lnwire.NewChanIDFromOutPoint(channel.ChannelPoint())
|
chanID := lnwire.NewChanIDFromOutPoint(channel.ChannelPoint())
|
||||||
addr := lnwire.DeliveryAddress(channel.LocalDeliveryScript)
|
|
||||||
|
|
||||||
// With both items constructed we'll now send the shutdown message for
|
// With both items constructed we'll now send the shutdown message for
|
||||||
// this particular channel, advertising a shutdown request to our
|
// this particular channel, advertising a shutdown request to our
|
||||||
// desired closing script.
|
// desired closing script.
|
||||||
shutdown := lnwire.NewShutdown(chanID, addr)
|
shutdown := lnwire.NewShutdown(chanID, deliveryScript)
|
||||||
p.queueMsg(shutdown, nil)
|
p.queueMsg(shutdown, nil)
|
||||||
|
|
||||||
// Finally, we'll unregister the link from the switch in order to
|
// Finally, we'll unregister the link from the switch in order to
|
||||||
|
Loading…
Reference in New Issue
Block a user