2017-03-09 00:32:11 +01:00
|
|
|
package lnwire
|
|
|
|
|
|
|
|
import (
|
2021-06-17 08:17:30 +02:00
|
|
|
"bytes"
|
2017-03-09 00:32:11 +01:00
|
|
|
"io"
|
|
|
|
|
2022-02-23 14:48:00 +01:00
|
|
|
"github.com/btcsuite/btcd/btcutil"
|
2023-01-17 04:43:25 +01:00
|
|
|
"github.com/lightningnetwork/lnd/tlv"
|
2017-03-09 00:32:11 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
// ClosingSigned is sent by both parties to a channel once the channel is clear
|
|
|
|
// of HTLCs, and is primarily concerned with negotiating fees for the close
|
|
|
|
// transaction. Each party provides a signature for a transaction with a fee
|
|
|
|
// that they believe is fair. The process terminates when both sides agree on
|
|
|
|
// the same fee, or when one side force closes the channel.
|
|
|
|
//
|
|
|
|
// NOTE: The responder is able to send a signature without any additional
|
|
|
|
// messages as all transactions are assembled observing BIP 69 which defines a
|
2017-12-18 03:40:05 +01:00
|
|
|
// canonical ordering for input/outputs. Therefore, both sides are able to
|
2017-03-09 00:32:11 +01:00
|
|
|
// arrive at an identical closure transaction as they know the order of the
|
|
|
|
// inputs/outputs.
|
|
|
|
type ClosingSigned struct {
|
|
|
|
// ChannelID serves to identify which channel is to be closed.
|
|
|
|
ChannelID ChannelID
|
|
|
|
|
2017-11-23 07:27:26 +01:00
|
|
|
// FeeSatoshis is the total fee in satoshis that the party to the
|
|
|
|
// channel would like to propose for the close transaction.
|
|
|
|
FeeSatoshis btcutil.Amount
|
2017-03-09 00:32:11 +01:00
|
|
|
|
|
|
|
// Signature is for the proposed channel close transaction.
|
2018-01-31 04:41:52 +01:00
|
|
|
Signature Sig
|
2020-01-28 02:25:36 +01:00
|
|
|
|
2023-01-17 04:43:25 +01:00
|
|
|
// PartialSig is used to transmit a musig2 extended partial signature
|
|
|
|
// that signs the latest fee offer. The nonce isn't sent along side, as
|
|
|
|
// that has already been sent in the initial shutdown message.
|
|
|
|
//
|
|
|
|
// NOTE: This field is only populated if a musig2 taproot channel is
|
|
|
|
// being signed for. In this case, the above Sig type MUST be blank.
|
|
|
|
PartialSig *PartialSig
|
|
|
|
|
2020-01-28 02:25:36 +01:00
|
|
|
// ExtraData is the set of data that was appended to this message to
|
|
|
|
// fill out the full maximum transport message size. These fields can
|
|
|
|
// be used to specify optional data such as custom TLV fields.
|
|
|
|
ExtraData ExtraOpaqueData
|
2017-03-09 00:32:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewClosingSigned creates a new empty ClosingSigned message.
|
2017-11-23 07:27:26 +01:00
|
|
|
func NewClosingSigned(cid ChannelID, fs btcutil.Amount,
|
2018-01-31 04:41:52 +01:00
|
|
|
sig Sig) *ClosingSigned {
|
2017-03-09 00:32:11 +01:00
|
|
|
|
|
|
|
return &ClosingSigned{
|
|
|
|
ChannelID: cid,
|
|
|
|
FeeSatoshis: fs,
|
|
|
|
Signature: sig,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// A compile time check to ensure ClosingSigned implements the lnwire.Message
|
|
|
|
// interface.
|
|
|
|
var _ Message = (*ClosingSigned)(nil)
|
|
|
|
|
|
|
|
// Decode deserializes a serialized ClosingSigned message stored in the passed
|
|
|
|
// io.Reader observing the specified protocol version.
|
|
|
|
//
|
|
|
|
// This is part of the lnwire.Message interface.
|
|
|
|
func (c *ClosingSigned) Decode(r io.Reader, pver uint32) error {
|
2023-01-17 04:43:25 +01:00
|
|
|
err := ReadElements(
|
|
|
|
r, &c.ChannelID, &c.FeeSatoshis, &c.Signature,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
var tlvRecords ExtraOpaqueData
|
|
|
|
if err := ReadElements(r, &tlvRecords); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
|
|
|
partialSig PartialSig
|
2020-01-28 02:25:36 +01:00
|
|
|
)
|
2023-01-17 04:43:25 +01:00
|
|
|
typeMap, err := tlvRecords.ExtractRecords(&partialSig)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the corresponding TLV types if they were included in the stream.
|
|
|
|
if val, ok := typeMap[PartialSigRecordType]; ok && val == nil {
|
|
|
|
c.PartialSig = &partialSig
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(tlvRecords) != 0 {
|
|
|
|
c.ExtraData = tlvRecords
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
2017-03-09 00:32:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Encode serializes the target ClosingSigned into the passed io.Writer
|
|
|
|
// observing the protocol version specified.
|
|
|
|
//
|
|
|
|
// This is part of the lnwire.Message interface.
|
2021-06-17 08:17:30 +02:00
|
|
|
func (c *ClosingSigned) Encode(w *bytes.Buffer, pver uint32) error {
|
2023-01-17 04:43:25 +01:00
|
|
|
recordProducers := make([]tlv.RecordProducer, 0, 1)
|
|
|
|
if c.PartialSig != nil {
|
|
|
|
recordProducers = append(recordProducers, c.PartialSig)
|
|
|
|
}
|
|
|
|
err := EncodeMessageExtraData(&c.ExtraData, recordProducers...)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-06-18 09:03:43 +02:00
|
|
|
if err := WriteChannelID(w, c.ChannelID); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := WriteSatoshi(w, c.FeeSatoshis); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := WriteSig(w, c.Signature); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return WriteBytes(w, c.ExtraData)
|
2017-03-09 00:32:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// MsgType returns the integer uniquely identifying this message type on the
|
|
|
|
// wire.
|
|
|
|
//
|
|
|
|
// This is part of the lnwire.Message interface.
|
|
|
|
func (c *ClosingSigned) MsgType() MessageType {
|
|
|
|
return MsgClosingSigned
|
|
|
|
}
|