github.com/decred/dcrlnd@v0.7.6/lnwallet/chancloser/chancloser.go (about)

     1  package chancloser
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  
     7  	"github.com/davecgh/go-spew/spew"
     8  	"github.com/decred/dcrd/chaincfg/v3"
     9  	"github.com/decred/dcrd/dcrutil/v4"
    10  	"github.com/decred/dcrd/txscript/v4/stdaddr"
    11  	"github.com/decred/dcrd/wire"
    12  	"github.com/decred/dcrlnd/htlcswitch"
    13  	"github.com/decred/dcrlnd/input"
    14  	"github.com/decred/dcrlnd/labels"
    15  	"github.com/decred/dcrlnd/lnwallet"
    16  	"github.com/decred/dcrlnd/lnwallet/chainfee"
    17  	"github.com/decred/dcrlnd/lnwire"
    18  )
    19  
    20  var (
    21  	// ErrChanAlreadyClosing is returned when a channel shutdown is attempted
    22  	// more than once.
    23  	ErrChanAlreadyClosing = fmt.Errorf("channel shutdown already initiated")
    24  
    25  	// ErrChanCloseNotFinished is returned when a caller attempts to access
    26  	// a field or function that is contingent on the channel closure negotiation
    27  	// already being completed.
    28  	ErrChanCloseNotFinished = fmt.Errorf("close negotiation not finished")
    29  
    30  	// ErrInvalidState is returned when the closing state machine receives a
    31  	// message while it is in an unknown state.
    32  	ErrInvalidState = fmt.Errorf("invalid state")
    33  
    34  	// ErrUpfrontShutdownScriptMismatch is returned when a peer or end user
    35  	// provides a cooperative close script which does not match the upfront
    36  	// shutdown script previously set for that party.
    37  	ErrUpfrontShutdownScriptMismatch = fmt.Errorf("shutdown script does not " +
    38  		"match upfront shutdown script")
    39  )
    40  
    41  // closeState represents all the possible states the channel closer state
    42  // machine can be in. Each message will either advance to the next state, or
    43  // remain at the current state. Once the state machine reaches a state of
    44  // closeFinished, then negotiation is over.
    45  type closeState uint8
    46  
    47  const (
    48  	// closeIdle is the initial starting state. In this state, the state
    49  	// machine has been instantiated, but no state transitions have been
    50  	// attempted. If a state machine receives a message while in this state,
    51  	// then it is the responder to an initiated cooperative channel closure.
    52  	closeIdle closeState = iota
    53  
    54  	// closeShutdownInitiated is the state that's transitioned to once the
    55  	// initiator of a closing workflow sends the shutdown message. At this
    56  	// point, they're waiting for the remote party to respond with their own
    57  	// shutdown message. After which, they'll both enter the fee negotiation
    58  	// phase.
    59  	closeShutdownInitiated
    60  
    61  	// closeFeeNegotiation is the third, and most persistent state. Both
    62  	// parties enter this state after they've sent and received a shutdown
    63  	// message. During this phase, both sides will send monotonically
    64  	// increasing fee requests until one side accepts the last fee rate offered
    65  	// by the other party. In this case, the party will broadcast the closing
    66  	// transaction, and send the accepted fee to the remote party. This then
    67  	// causes a shift into the closeFinished state.
    68  	closeFeeNegotiation
    69  
    70  	// closeFinished is the final state of the state machine. In this state, a
    71  	// side has accepted a fee offer and has broadcast the valid closing
    72  	// transaction to the network. During this phase, the closing transaction
    73  	// becomes available for examination.
    74  	closeFinished
    75  )
    76  
    77  // ChanCloseCfg holds all the items that a ChanCloser requires to carry out its
    78  // duties.
    79  type ChanCloseCfg struct {
    80  	// Channel is the channel that should be closed.
    81  	Channel *lnwallet.LightningChannel
    82  
    83  	// BroadcastTx broadcasts the passed transaction to the network.
    84  	BroadcastTx func(*wire.MsgTx, string) error
    85  
    86  	// DisableChannel disables a channel, resulting in it not being able to
    87  	// forward payments.
    88  	DisableChannel func(wire.OutPoint) error
    89  
    90  	// Disconnect will disconnect from the remote peer in this close.
    91  	Disconnect func() error
    92  
    93  	// Quit is a channel that should be sent upon in the occasion the state
    94  	// machine should cease all progress and shutdown.
    95  	Quit chan struct{}
    96  }
    97  
    98  // ChanCloser is a state machine that handles the cooperative channel closure
    99  // procedure. This includes shutting down a channel, marking it ineligible for
   100  // routing HTLC's, negotiating fees with the remote party, and finally
   101  // broadcasting the fully signed closure transaction to the network.
   102  type ChanCloser struct {
   103  	// state is the current state of the state machine.
   104  	state closeState
   105  
   106  	// cfg holds the configuration for this ChanCloser instance.
   107  	cfg ChanCloseCfg
   108  
   109  	// chanPoint is the full channel point of the target channel.
   110  	chanPoint wire.OutPoint
   111  
   112  	// cid is the full channel ID of the target channel.
   113  	cid lnwire.ChannelID
   114  
   115  	// negotiationHeight is the height that the fee negotiation begun at.
   116  	negotiationHeight uint32
   117  
   118  	// closingTx is the final, fully signed closing transaction. This will only
   119  	// be populated once the state machine shifts to the closeFinished state.
   120  	closingTx *wire.MsgTx
   121  
   122  	// idealFeeSat is the ideal fee that the state machine should initially
   123  	// offer when starting negotiation. This will be used as a baseline.
   124  	idealFeeSat dcrutil.Amount
   125  
   126  	// lastFeeProposal is the last fee that we proposed to the remote
   127  	// party.  We'll use this as a pivot point to ratchet our next offer
   128  	// up, down, or simply accept the remote party's prior offer.
   129  	lastFeeProposal dcrutil.Amount
   130  
   131  	// priorFeeOffers is a map that keeps track of all the proposed fees that
   132  	// we've offered during the fee negotiation. We use this map to cut the
   133  	// negotiation early if the remote party ever sends an offer that we've
   134  	// sent in the past. Once negotiation terminates, we can extract the prior
   135  	// signature of our accepted offer from this map.
   136  	//
   137  	// TODO(roasbeef): need to ensure if they broadcast w/ any of our prior
   138  	// sigs, we are aware of
   139  	priorFeeOffers map[dcrutil.Amount]*lnwire.ClosingSigned
   140  
   141  	// closeReq is the initial closing request. This will only be populated if
   142  	// we're the initiator of this closing negotiation.
   143  	//
   144  	// TODO(roasbeef): abstract away
   145  	closeReq *htlcswitch.ChanClose
   146  
   147  	// localDeliveryScript is the script that we'll send our settled channel
   148  	// funds to.
   149  	localDeliveryScript []byte
   150  
   151  	// remoteDeliveryScript is the script that we'll send the remote party's
   152  	// settled channel funds to.
   153  	remoteDeliveryScript []byte
   154  
   155  	// locallyInitiated is true if we initiated the channel close.
   156  	locallyInitiated bool
   157  }
   158  
   159  // NewChanCloser creates a new instance of the channel closure given the passed
   160  // configuration, and delivery+fee preference. The final argument should only
   161  // be populated iff, we're the initiator of this closing request.
   162  func NewChanCloser(cfg ChanCloseCfg, deliveryScript []byte,
   163  	idealFeePerKB chainfee.AtomPerKByte, negotiationHeight uint32,
   164  	closeReq *htlcswitch.ChanClose, locallyInitiated bool) *ChanCloser {
   165  
   166  	// Given the target fee-per-kw, we'll compute what our ideal _total_ fee
   167  	// will be starting at for this fee negotiation.
   168  	//
   169  	// TODO(roasbeef): should factor in minimal commit
   170  	idealFeeSat := cfg.Channel.CalcFee(idealFeePerKB)
   171  
   172  	// If this fee is greater than the fee currently present within the
   173  	// commitment transaction, then we'll clamp it down to be within the proper
   174  	// range.
   175  	//
   176  	// TODO(roasbeef): clamp fee func?
   177  	channelCommitFee := cfg.Channel.StateSnapshot().CommitFee
   178  	if idealFeeSat > channelCommitFee {
   179  		chancloserLog.Infof("Ideal starting fee of %v is greater than commit "+
   180  			"fee of %v, clamping", int64(idealFeeSat), int64(channelCommitFee))
   181  
   182  		idealFeeSat = channelCommitFee
   183  	}
   184  
   185  	chancloserLog.Infof("Ideal fee for closure of ChannelPoint(%v) is: %v sat",
   186  		cfg.Channel.ChannelPoint(), int64(idealFeeSat))
   187  
   188  	cid := lnwire.NewChanIDFromOutPoint(cfg.Channel.ChannelPoint())
   189  	return &ChanCloser{
   190  		closeReq:            closeReq,
   191  		state:               closeIdle,
   192  		chanPoint:           *cfg.Channel.ChannelPoint(),
   193  		cid:                 cid,
   194  		cfg:                 cfg,
   195  		negotiationHeight:   negotiationHeight,
   196  		idealFeeSat:         idealFeeSat,
   197  		localDeliveryScript: deliveryScript,
   198  		priorFeeOffers:      make(map[dcrutil.Amount]*lnwire.ClosingSigned),
   199  		locallyInitiated:    locallyInitiated,
   200  	}
   201  }
   202  
   203  // initChanShutdown begins the shutdown process by un-registering the channel,
   204  // and creating a valid shutdown message to our target delivery address.
   205  func (c *ChanCloser) initChanShutdown() (*lnwire.Shutdown, error) {
   206  	// With both items constructed we'll now send the shutdown message for this
   207  	// particular channel, advertising a shutdown request to our desired
   208  	// closing script.
   209  	shutdown := lnwire.NewShutdown(c.cid, c.localDeliveryScript)
   210  
   211  	// Before closing, we'll attempt to send a disable update for the channel.
   212  	// We do so before closing the channel as otherwise the current edge policy
   213  	// won't be retrievable from the graph.
   214  	if err := c.cfg.DisableChannel(c.chanPoint); err != nil {
   215  		chancloserLog.Warnf("Unable to disable channel %v on close: %v",
   216  			c.chanPoint, err)
   217  	}
   218  
   219  	// Before continuing, mark the channel as cooperatively closed with a nil
   220  	// txn. Even though we haven't negotiated the final txn, this guarantees
   221  	// that our listchannels rpc will be externally consistent, and reflect
   222  	// that the channel is being shutdown by the time the closing request
   223  	// returns.
   224  	err := c.cfg.Channel.MarkCoopBroadcasted(nil, c.locallyInitiated)
   225  	if err != nil {
   226  		return nil, err
   227  	}
   228  
   229  	chancloserLog.Infof("ChannelPoint(%v): sending shutdown message",
   230  		c.chanPoint)
   231  
   232  	return shutdown, nil
   233  }
   234  
   235  // ShutdownChan is the first method that's to be called by the initiator of the
   236  // cooperative channel closure. This message returns the shutdown message to
   237  // send to the remote party. Upon completion, we enter the
   238  // closeShutdownInitiated phase as we await a response.
   239  func (c *ChanCloser) ShutdownChan() (*lnwire.Shutdown, error) {
   240  	// If we attempt to shutdown the channel for the first time, and we're not
   241  	// in the closeIdle state, then the caller made an error.
   242  	if c.state != closeIdle {
   243  		return nil, ErrChanAlreadyClosing
   244  	}
   245  
   246  	chancloserLog.Infof("ChannelPoint(%v): initiating shutdown", c.chanPoint)
   247  
   248  	shutdownMsg, err := c.initChanShutdown()
   249  	if err != nil {
   250  		return nil, err
   251  	}
   252  
   253  	// With the opening steps complete, we'll transition into the
   254  	// closeShutdownInitiated state. In this state, we'll wait until the other
   255  	// party sends their version of the shutdown message.
   256  	c.state = closeShutdownInitiated
   257  
   258  	// Finally, we'll return the shutdown message to the caller so it can send
   259  	// it to the remote peer.
   260  	return shutdownMsg, nil
   261  }
   262  
   263  // ClosingTx returns the fully signed, final closing transaction.
   264  //
   265  // NOTE: This transaction is only available if the state machine is in the
   266  // closeFinished state.
   267  func (c *ChanCloser) ClosingTx() (*wire.MsgTx, error) {
   268  	// If the state machine hasn't finished closing the channel, then we'll
   269  	// return an error as we haven't yet computed the closing tx.
   270  	if c.state != closeFinished {
   271  		return nil, ErrChanCloseNotFinished
   272  	}
   273  
   274  	return c.closingTx, nil
   275  }
   276  
   277  // CloseRequest returns the original close request that prompted the creation
   278  // of the state machine.
   279  //
   280  // NOTE: This will only return a non-nil pointer if we were the initiator of
   281  // the cooperative closure workflow.
   282  func (c *ChanCloser) CloseRequest() *htlcswitch.ChanClose {
   283  	return c.closeReq
   284  }
   285  
   286  // Channel returns the channel stored in the config.
   287  func (c *ChanCloser) Channel() *lnwallet.LightningChannel {
   288  	return c.cfg.Channel
   289  }
   290  
   291  // NegotiationHeight returns the negotiation height.
   292  func (c *ChanCloser) NegotiationHeight() uint32 {
   293  	return c.negotiationHeight
   294  }
   295  
   296  // maybeMatchScript attempts to match the script provided in our peer's
   297  // shutdown message with the upfront shutdown script we have on record. If no
   298  // upfront shutdown script was set, we do not need to enforce option upfront
   299  // shutdown, so the function returns early. If an upfront script is set, we
   300  // check whether it matches the script provided by our peer. If they do not
   301  // match, we use the disconnect function provided to disconnect from the peer.
   302  func maybeMatchScript(disconnect func() error, upfrontScript,
   303  	peerScript lnwire.DeliveryAddress) error {
   304  
   305  	// If no upfront shutdown script was set, return early because we do not
   306  	// need to enforce closure to a specific script.
   307  	if len(upfrontScript) == 0 {
   308  		return nil
   309  	}
   310  
   311  	// If an upfront shutdown script was provided, disconnect from the peer, as
   312  	// per BOLT 2, and return an error.
   313  	if !bytes.Equal(upfrontScript, peerScript) {
   314  		chancloserLog.Warnf("peer's script: %x does not match upfront "+
   315  			"shutdown script: %x", peerScript, upfrontScript)
   316  
   317  		// Disconnect from the peer because they have violated option upfront
   318  		// shutdown.
   319  		if err := disconnect(); err != nil {
   320  			return err
   321  		}
   322  
   323  		return ErrUpfrontShutdownScriptMismatch
   324  	}
   325  
   326  	return nil
   327  }
   328  
   329  // ProcessCloseMsg attempts to process the next message in the closing series.
   330  // This method will update the state accordingly and return two primary values:
   331  // the next set of messages to be sent, and a bool indicating if the fee
   332  // negotiation process has completed. If the second value is true, then this
   333  // means the ChanCloser can be garbage collected.
   334  func (c *ChanCloser) ProcessCloseMsg(msg lnwire.Message) ([]lnwire.Message,
   335  	bool, error) {
   336  
   337  	switch c.state {
   338  
   339  	// If we're in the close idle state, and we're receiving a channel closure
   340  	// related message, then this indicates that we're on the receiving side of
   341  	// an initiated channel closure.
   342  	case closeIdle:
   343  		// First, we'll assert that we have a channel shutdown message,
   344  		// as otherwise, this is an attempted invalid state transition.
   345  		shutdownMsg, ok := msg.(*lnwire.Shutdown)
   346  		if !ok {
   347  			return nil, false, fmt.Errorf("expected lnwire.Shutdown, instead "+
   348  				"have %v", spew.Sdump(msg))
   349  		}
   350  
   351  		// As we're the responder to this shutdown (the other party
   352  		// wants to close), we'll check if this is a frozen channel or
   353  		// not. If the channel is frozen and we were not also the
   354  		// initiator of the channel opening, then we'll deny their close
   355  		// attempt.
   356  		chanInitiator := c.cfg.Channel.IsInitiator()
   357  		chanState := c.cfg.Channel.State()
   358  		if !chanInitiator {
   359  			absoluteThawHeight, err := chanState.AbsoluteThawHeight()
   360  			if err != nil {
   361  				return nil, false, err
   362  			}
   363  			if c.negotiationHeight < absoluteThawHeight {
   364  				return nil, false, fmt.Errorf("initiator "+
   365  					"attempting to co-op close frozen "+
   366  					"ChannelPoint(%v) (current_height=%v, "+
   367  					"thaw_height=%v)", c.chanPoint,
   368  					c.negotiationHeight, absoluteThawHeight)
   369  			}
   370  		}
   371  
   372  		// If the remote node opened the channel with option upfront shutdown
   373  		// script, check that the script they provided matches.
   374  		if err := maybeMatchScript(
   375  			c.cfg.Disconnect, c.cfg.Channel.RemoteUpfrontShutdownScript(),
   376  			shutdownMsg.Address,
   377  		); err != nil {
   378  			return nil, false, err
   379  		}
   380  
   381  		// Once we have checked that the other party has not violated option
   382  		// upfront shutdown we set their preference for delivery address. We'll
   383  		// use this when we craft the closure transaction.
   384  		c.remoteDeliveryScript = shutdownMsg.Address
   385  
   386  		// We'll generate a shutdown message of our own to send across the
   387  		// wire.
   388  		localShutdown, err := c.initChanShutdown()
   389  		if err != nil {
   390  			return nil, false, err
   391  		}
   392  
   393  		chancloserLog.Infof("ChannelPoint(%v): responding to shutdown",
   394  			c.chanPoint)
   395  
   396  		msgsToSend := make([]lnwire.Message, 0, 2)
   397  		msgsToSend = append(msgsToSend, localShutdown)
   398  
   399  		// After the other party receives this message, we'll actually start
   400  		// the final stage of the closure process: fee negotiation. So we'll
   401  		// update our internal state to reflect this, so we can handle the next
   402  		// message sent.
   403  		c.state = closeFeeNegotiation
   404  
   405  		// We'll also craft our initial close proposal in order to keep the
   406  		// negotiation moving, but only if we're the negotiator.
   407  		if chanInitiator {
   408  			closeSigned, err := c.proposeCloseSigned(c.idealFeeSat)
   409  			if err != nil {
   410  				return nil, false, err
   411  			}
   412  			msgsToSend = append(msgsToSend, closeSigned)
   413  		}
   414  
   415  		// We'll return both sets of messages to send to the remote party to
   416  		// kick off the fee negotiation process.
   417  		return msgsToSend, false, nil
   418  
   419  	// If we just initiated a channel shutdown, and we receive a new message,
   420  	// then this indicates the other party is ready to shutdown as well. In
   421  	// this state we'll send our first signature.
   422  	case closeShutdownInitiated:
   423  		// First, we'll assert that we have a channel shutdown message.
   424  		// Otherwise, this is an attempted invalid state transition.
   425  		shutdownMsg, ok := msg.(*lnwire.Shutdown)
   426  		if !ok {
   427  			return nil, false, fmt.Errorf("expected lnwire.Shutdown, instead "+
   428  				"have %v", spew.Sdump(msg))
   429  		}
   430  
   431  		// If the remote node opened the channel with option upfront shutdown
   432  		// script, check that the script they provided matches.
   433  		if err := maybeMatchScript(c.cfg.Disconnect,
   434  			c.cfg.Channel.RemoteUpfrontShutdownScript(), shutdownMsg.Address,
   435  		); err != nil {
   436  			return nil, false, err
   437  		}
   438  
   439  		// Now that we know this is a valid shutdown message and address, we'll
   440  		// record their preferred delivery closing script.
   441  		c.remoteDeliveryScript = shutdownMsg.Address
   442  
   443  		// At this point, we can now start the fee negotiation state, by
   444  		// constructing and sending our initial signature for what we think the
   445  		// closing transaction should look like.
   446  		c.state = closeFeeNegotiation
   447  
   448  		chancloserLog.Infof("ChannelPoint(%v): shutdown response received, "+
   449  			"entering fee negotiation", c.chanPoint)
   450  
   451  		// Starting with our ideal fee rate, we'll create an initial closing
   452  		// proposal, but only if we're the initiator, as otherwise, the other
   453  		// party will send their initial proposal first.
   454  		if c.cfg.Channel.IsInitiator() {
   455  			closeSigned, err := c.proposeCloseSigned(c.idealFeeSat)
   456  			if err != nil {
   457  				return nil, false, err
   458  			}
   459  
   460  			return []lnwire.Message{closeSigned}, false, nil
   461  		}
   462  
   463  		return nil, false, nil
   464  
   465  	// If we're receiving a message while we're in the fee negotiation phase,
   466  	// then this indicates the remote party is responding to a close signed
   467  	// message we sent, or kicking off the process with their own.
   468  	case closeFeeNegotiation:
   469  		// First, we'll assert that we're actually getting a ClosingSigned
   470  		// message, otherwise an invalid state transition was attempted.
   471  		closeSignedMsg, ok := msg.(*lnwire.ClosingSigned)
   472  		if !ok {
   473  			return nil, false, fmt.Errorf("expected lnwire.ClosingSigned, "+
   474  				"instead have %v", spew.Sdump(msg))
   475  		}
   476  		// We'll compare the proposed total fee, to what we've proposed
   477  		// during the negotiations. If it doesn't match any of our
   478  		// prior offers, then we'll attempt to ratchet the fee closer
   479  		// to
   480  		remoteProposedFee := closeSignedMsg.FeeAtoms
   481  		if _, ok := c.priorFeeOffers[remoteProposedFee]; !ok {
   482  			// We'll now attempt to ratchet towards a fee deemed acceptable by
   483  			// both parties, factoring in our ideal fee rate, and the last
   484  			// proposed fee by both sides.
   485  			feeProposal := calcCompromiseFee(c.chanPoint, c.idealFeeSat,
   486  				c.lastFeeProposal, remoteProposedFee,
   487  			)
   488  
   489  			// With our new fee proposal calculated, we'll craft a new close
   490  			// signed signature to send to the other party so we can continue
   491  			// the fee negotiation process.
   492  			closeSigned, err := c.proposeCloseSigned(feeProposal)
   493  			if err != nil {
   494  				return nil, false, err
   495  			}
   496  
   497  			// If the compromise fee doesn't match what the peer proposed, then
   498  			// we'll return this latest close signed message so we can continue
   499  			// negotiation.
   500  			if feeProposal != remoteProposedFee {
   501  				chancloserLog.Debugf("ChannelPoint(%v): close tx fee "+
   502  					"disagreement, continuing negotiation", c.chanPoint)
   503  				return []lnwire.Message{closeSigned}, false, nil
   504  			}
   505  		}
   506  
   507  		chancloserLog.Infof("ChannelPoint(%v) fee of %v accepted, ending "+
   508  			"negotiation", c.chanPoint, remoteProposedFee)
   509  
   510  		// Otherwise, we've agreed on a fee for the closing transaction! We'll
   511  		// craft the final closing transaction so we can broadcast it to the
   512  		// network.
   513  		matchingSig := c.priorFeeOffers[remoteProposedFee].Signature
   514  		localSig, err := matchingSig.ToSignature()
   515  		if err != nil {
   516  			return nil, false, err
   517  		}
   518  
   519  		remoteSig, err := closeSignedMsg.Signature.ToSignature()
   520  		if err != nil {
   521  			return nil, false, err
   522  		}
   523  
   524  		closeTx, _, err := c.cfg.Channel.CompleteCooperativeClose(
   525  			localSig, remoteSig, c.localDeliveryScript, c.remoteDeliveryScript,
   526  			remoteProposedFee,
   527  		)
   528  		if err != nil {
   529  			return nil, false, err
   530  		}
   531  		c.closingTx = closeTx
   532  
   533  		// Before publishing the closing tx, we persist it to the database,
   534  		// such that it can be republished if something goes wrong.
   535  		err = c.cfg.Channel.MarkCoopBroadcasted(closeTx, c.locallyInitiated)
   536  		if err != nil {
   537  			return nil, false, err
   538  		}
   539  
   540  		// With the closing transaction crafted, we'll now broadcast it to the
   541  		// network.
   542  		chancloserLog.Infof("Broadcasting cooperative close tx: %v",
   543  			newLogClosure(func() string {
   544  				return spew.Sdump(closeTx)
   545  			}),
   546  		)
   547  
   548  		// Create a close channel label.
   549  		chanID := c.cfg.Channel.ShortChanID()
   550  		closeLabel := labels.MakeLabel(
   551  			labels.LabelTypeChannelClose, &chanID,
   552  		)
   553  
   554  		if err := c.cfg.BroadcastTx(closeTx, closeLabel); err != nil {
   555  			return nil, false, err
   556  		}
   557  
   558  		// Finally, we'll transition to the closeFinished state, and also
   559  		// return the final close signed message we sent. Additionally, we
   560  		// return true for the second argument to indicate we're finished with
   561  		// the channel closing negotiation.
   562  		c.state = closeFinished
   563  		matchingOffer := c.priorFeeOffers[remoteProposedFee]
   564  		return []lnwire.Message{matchingOffer}, true, nil
   565  
   566  	// If we received a message while in the closeFinished state, then this
   567  	// should only be the remote party echoing the last ClosingSigned message
   568  	// that we agreed on.
   569  	case closeFinished:
   570  		if _, ok := msg.(*lnwire.ClosingSigned); !ok {
   571  			return nil, false, fmt.Errorf("expected lnwire.ClosingSigned, "+
   572  				"instead have %v", spew.Sdump(msg))
   573  		}
   574  
   575  		// There's no more to do as both sides should have already broadcast
   576  		// the closing transaction at this state.
   577  		return nil, true, nil
   578  
   579  	// Otherwise, we're in an unknown state, and can't proceed.
   580  	default:
   581  		return nil, false, ErrInvalidState
   582  	}
   583  }
   584  
   585  // proposeCloseSigned attempts to propose a new signature for the closing
   586  // transaction for a channel based on the prior fee negotiations and our
   587  // current compromise fee.
   588  func (c *ChanCloser) proposeCloseSigned(fee dcrutil.Amount) (*lnwire.ClosingSigned, error) {
   589  	rawSig, _, _, err := c.cfg.Channel.CreateCloseProposal(
   590  		fee, c.localDeliveryScript, c.remoteDeliveryScript,
   591  	)
   592  	if err != nil {
   593  		return nil, err
   594  	}
   595  
   596  	// We'll note our last signature and proposed fee so when the remote party
   597  	// responds we'll be able to decide if we've agreed on fees or not.
   598  	c.lastFeeProposal = fee
   599  	parsedSig, err := lnwire.NewSigFromSignature(rawSig)
   600  	if err != nil {
   601  		return nil, err
   602  	}
   603  
   604  	chancloserLog.Infof("ChannelPoint(%v): proposing fee of %v atoms to close "+
   605  		"chan", c.chanPoint, int64(fee))
   606  
   607  	// We'll assemble a ClosingSigned message using this information and return
   608  	// it to the caller so we can kick off the final stage of the channel
   609  	// closure process.
   610  	closeSignedMsg := lnwire.NewClosingSigned(c.cid, fee, parsedSig)
   611  
   612  	// We'll also save this close signed, in the case that the remote party
   613  	// accepts our offer. This way, we don't have to re-sign.
   614  	c.priorFeeOffers[fee] = closeSignedMsg
   615  
   616  	return closeSignedMsg, nil
   617  }
   618  
   619  // feeInAcceptableRange returns true if the passed remote fee is deemed to be
   620  // in an "acceptable" range to our local fee. This is an attempt at a
   621  // compromise and to ensure that the fee negotiation has a stopping point. We
   622  // consider their fee acceptable if it's within 30% of our fee.
   623  func feeInAcceptableRange(localFee, remoteFee dcrutil.Amount) bool {
   624  	// If our offer is lower than theirs, then we'll accept their offer if it's
   625  	// no more than 30% *greater* than our current offer.
   626  	if localFee < remoteFee {
   627  		acceptableRange := localFee + ((localFee * 3) / 10)
   628  		return remoteFee <= acceptableRange
   629  	}
   630  
   631  	// If our offer is greater than theirs, then we'll accept their offer if
   632  	// it's no more than 30% *less* than our current offer.
   633  	acceptableRange := localFee - ((localFee * 3) / 10)
   634  	return remoteFee >= acceptableRange
   635  }
   636  
   637  // ratchetFee is our step function used to inch our fee closer to something
   638  // that both sides can agree on. If up is true, then we'll attempt to increase
   639  // our offered fee. Otherwise, if up is false, then we'll attempt to decrease
   640  // our offered fee.
   641  func ratchetFee(fee dcrutil.Amount, up bool) dcrutil.Amount {
   642  	// If we need to ratchet up, then we'll increase our fee by 10%.
   643  	if up {
   644  		return fee + ((fee * 1) / 10)
   645  	}
   646  
   647  	// Otherwise, we'll *decrease* our fee by 10%.
   648  	return fee - ((fee * 1) / 10)
   649  }
   650  
   651  // calcCompromiseFee performs the current fee negotiation algorithm, taking
   652  // into consideration our ideal fee based on current fee environment, the fee
   653  // we last proposed (if any), and the fee proposed by the peer.
   654  func calcCompromiseFee(chanPoint wire.OutPoint, ourIdealFee, lastSentFee,
   655  	remoteFee dcrutil.Amount) dcrutil.Amount {
   656  
   657  	// TODO(roasbeef): take in number of rounds as well?
   658  
   659  	chancloserLog.Infof("ChannelPoint(%v): computing fee compromise, ideal="+
   660  		"%v, last_sent=%v, remote_offer=%v", chanPoint, int64(ourIdealFee),
   661  		int64(lastSentFee), int64(remoteFee))
   662  
   663  	// Otherwise, we'll need to attempt to make a fee compromise if this is the
   664  	// second round, and neither side has agreed on fees.
   665  	switch {
   666  
   667  	// If their proposed fee is identical to our ideal fee, then we'll go with
   668  	// that as we can short circuit the fee negotiation. Similarly, if we
   669  	// haven't sent an offer yet, we'll default to our ideal fee.
   670  	case ourIdealFee == remoteFee || lastSentFee == 0:
   671  		return ourIdealFee
   672  
   673  	// If the last fee we sent, is equal to the fee the remote party is
   674  	// offering, then we can simply return this fee as the negotiation is over.
   675  	case remoteFee == lastSentFee:
   676  		return lastSentFee
   677  
   678  	// If the fee the remote party is offering is less than the last one we
   679  	// sent, then we'll need to ratchet down in order to move our offer closer
   680  	// to theirs.
   681  	case remoteFee < lastSentFee:
   682  		// If the fee is lower, but still acceptable, then we'll just return
   683  		// this fee and end the negotiation.
   684  		if feeInAcceptableRange(lastSentFee, remoteFee) {
   685  			chancloserLog.Infof("ChannelPoint(%v): proposed remote fee is "+
   686  				"close enough, capitulating", chanPoint)
   687  			return remoteFee
   688  		}
   689  
   690  		// Otherwise, we'll ratchet the fee *down* using our current algorithm.
   691  		return ratchetFee(lastSentFee, false)
   692  
   693  	// If the fee the remote party is offering is greater than the last one we
   694  	// sent, then we'll ratchet up in order to ensure we terminate eventually.
   695  	case remoteFee > lastSentFee:
   696  		// If the fee is greater, but still acceptable, then we'll just return
   697  		// this fee in order to put an end to the negotiation.
   698  		if feeInAcceptableRange(lastSentFee, remoteFee) {
   699  			chancloserLog.Infof("ChannelPoint(%v): proposed remote fee is "+
   700  				"close enough, capitulating", chanPoint)
   701  			return remoteFee
   702  		}
   703  
   704  		// Otherwise, we'll ratchet the fee up using our current algorithm.
   705  		return ratchetFee(lastSentFee, true)
   706  
   707  	default:
   708  		// TODO(roasbeef): fail if their fee isn't in expected range
   709  		return remoteFee
   710  	}
   711  }
   712  
   713  // ParseUpfrontShutdownAddress attempts to parse an upfront shutdown address.
   714  // If the address is empty, it returns nil. If it successfully decoded the
   715  // address, it returns a script that pays out to the address.
   716  func ParseUpfrontShutdownAddress(address string,
   717  	params *chaincfg.Params) (lnwire.DeliveryAddress, error) {
   718  
   719  	if len(address) == 0 {
   720  		return nil, nil
   721  	}
   722  
   723  	addr, err := stdaddr.DecodeAddress(
   724  		address, params,
   725  	)
   726  	if err != nil {
   727  		return nil, fmt.Errorf("invalid address: %v", err)
   728  	}
   729  
   730  	return input.PayToAddrScript(addr)
   731  }