github.com/decred/dcrlnd@v0.7.6/lnwire/open_channel.go (about)

     1  package lnwire
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  
     7  	"github.com/decred/dcrd/chaincfg/chainhash"
     8  	"github.com/decred/dcrd/dcrec/secp256k1/v4"
     9  	"github.com/decred/dcrd/dcrutil/v4"
    10  	"github.com/decred/dcrlnd/tlv"
    11  )
    12  
    13  // FundingFlag represents the possible bit mask values for the ChannelFlags
    14  // field within the OpenChannel struct.
    15  type FundingFlag uint8
    16  
    17  const (
    18  	// FFAnnounceChannel is a FundingFlag that when set, indicates the
    19  	// initiator of a funding flow wishes to announce the channel to the
    20  	// greater network.
    21  	FFAnnounceChannel FundingFlag = 1 << iota
    22  )
    23  
    24  // OpenChannel is the message Alice sends to Bob if we should like to create a
    25  // channel with Bob where she's the sole provider of funds to the channel.
    26  // Single funder channels simplify the initial funding workflow, are supported
    27  // by nodes backed by SPV clients, and have a simpler security models than dual
    28  // funded channels.
    29  type OpenChannel struct {
    30  	// ChainHash is the target chain that the initiator wishes to open a
    31  	// channel within.
    32  	ChainHash chainhash.Hash
    33  
    34  	// PendingChannelID serves to uniquely identify the future channel
    35  	// created by the initiated single funder workflow.
    36  	PendingChannelID [32]byte
    37  
    38  	// FundingAmount is the amount of atoms that the initiator of the
    39  	// channel wishes to use as the total capacity of the channel. The
    40  	// initial balance of the funding will be this value minus the push
    41  	// amount (if set).
    42  	FundingAmount dcrutil.Amount
    43  
    44  	// PushAmount is the value that the initiating party wishes to "push"
    45  	// to the responding as part of the first commitment state. If the
    46  	// responder accepts, then this will be their initial balance.
    47  	PushAmount MilliAtom
    48  
    49  	// DustLimit is the specific dust limit the sender of this message
    50  	// would like enforced on their version of the commitment transaction.
    51  	// Any output below this value will be "trimmed" from the commitment
    52  	// transaction, with the amount of the HTLC going to dust.
    53  	DustLimit dcrutil.Amount
    54  
    55  	// MaxValueInFlight represents the maximum amount of coins that can be
    56  	// pending within the channel at any given time. If the amount of funds
    57  	// in limbo exceeds this amount, then the channel will be failed.
    58  	MaxValueInFlight MilliAtom
    59  
    60  	// ChannelReserve is the amount that the receiving party MUST
    61  	// maintain a balance above at all times. This is a safety mechanism to
    62  	// ensure that both sides always have skin in the game during the
    63  	// channel's lifetime.
    64  	ChannelReserve dcrutil.Amount
    65  
    66  	// HtlcMinimum is the smallest HTLC that the sender of this message
    67  	// will accept.
    68  	HtlcMinimum MilliAtom
    69  
    70  	// FeePerKiloByte is the initial fee rate that the initiator suggests
    71  	// for both commitment transaction. This value is expressed in atoms
    72  	// per kilobyte.
    73  	//
    74  	// TODO(halseth): make AtomsPerKWeight when fee estimation is in own
    75  	// package. Currently this will cause an import cycle.
    76  	FeePerKiloByte uint32
    77  
    78  	// CsvDelay is the number of blocks to use for the relative time lock
    79  	// in the pay-to-self output of both commitment transactions.
    80  	CsvDelay uint16
    81  
    82  	// MaxAcceptedHTLCs is the total number of incoming HTLC's that the
    83  	// sender of this channel will accept.
    84  	MaxAcceptedHTLCs uint16
    85  
    86  	// FundingKey is the key that should be used on behalf of the sender
    87  	// within the 2-of-2 multi-sig output that it contained within the
    88  	// funding transaction.
    89  	FundingKey *secp256k1.PublicKey
    90  
    91  	// RevocationPoint is the base revocation point for the sending party.
    92  	// Any commitment transaction belonging to the receiver of this message
    93  	// should use this key and their per-commitment point to derive the
    94  	// revocation key for the commitment transaction.
    95  	RevocationPoint *secp256k1.PublicKey
    96  
    97  	// PaymentPoint is the base payment point for the sending party. This
    98  	// key should be combined with the per commitment point for a
    99  	// particular commitment state in order to create the key that should
   100  	// be used in any output that pays directly to the sending party, and
   101  	// also within the HTLC covenant transactions.
   102  	PaymentPoint *secp256k1.PublicKey
   103  
   104  	// DelayedPaymentPoint is the delay point for the sending party. This
   105  	// key should be combined with the per commitment point to derive the
   106  	// keys that are used in outputs of the sender's commitment transaction
   107  	// where they claim funds.
   108  	DelayedPaymentPoint *secp256k1.PublicKey
   109  
   110  	// HtlcPoint is the base point used to derive the set of keys for this
   111  	// party that will be used within the HTLC public key scripts. This
   112  	// value is combined with the receiver's revocation base point in order
   113  	// to derive the keys that are used within HTLC scripts.
   114  	HtlcPoint *secp256k1.PublicKey
   115  
   116  	// FirstCommitmentPoint is the first commitment point for the sending
   117  	// party. This value should be combined with the receiver's revocation
   118  	// base point in order to derive the revocation keys that are placed
   119  	// within the commitment transaction of the sender.
   120  	FirstCommitmentPoint *secp256k1.PublicKey
   121  
   122  	// ChannelFlags is a bit-field which allows the initiator of the
   123  	// channel to specify further behavior surrounding the channel.
   124  	// Currently, the least significant bit of this bit field indicates the
   125  	// initiator of the channel wishes to advertise this channel publicly.
   126  	ChannelFlags FundingFlag
   127  
   128  	// UpfrontShutdownScript is the script to which the channel funds should
   129  	// be paid when mutually closing the channel. This field is optional, and
   130  	// and has a length prefix, so a zero will be written if it is not set
   131  	// and its length followed by the script will be written if it is set.
   132  	UpfrontShutdownScript DeliveryAddress
   133  
   134  	// ChannelType is the explicit channel type the initiator wishes to
   135  	// open.
   136  	ChannelType *ChannelType
   137  
   138  	// LeaseExpiry represents the absolute expiration height of a channel
   139  	// lease. This is a custom TLV record that will only apply when a leased
   140  	// channel is being opened using the script enforced lease commitment
   141  	// type.
   142  	LeaseExpiry *LeaseExpiry
   143  
   144  	// ExtraData is the set of data that was appended to this message to
   145  	// fill out the full maximum transport message size. These fields can
   146  	// be used to specify optional data such as custom TLV fields.
   147  	//
   148  	// NOTE: Since the upfront shutdown script MUST be present (though can
   149  	// be zero-length) if any TLV data is available, the script will be
   150  	// extracted and removed from this blob when decoding. ExtraData will
   151  	// contain all TLV records _except_ the DeliveryAddress record in that
   152  	// case.
   153  	ExtraData ExtraOpaqueData
   154  }
   155  
   156  // A compile time check to ensure OpenChannel implements the lnwire.Message
   157  // interface.
   158  var _ Message = (*OpenChannel)(nil)
   159  
   160  // Encode serializes the target OpenChannel into the passed io.Writer
   161  // implementation. Serialization will observe the rules defined by the passed
   162  // protocol version.
   163  func (o *OpenChannel) Encode(w *bytes.Buffer, pver uint32) error {
   164  	recordProducers := []tlv.RecordProducer{&o.UpfrontShutdownScript}
   165  	if o.ChannelType != nil {
   166  		recordProducers = append(recordProducers, o.ChannelType)
   167  	}
   168  	if o.LeaseExpiry != nil {
   169  		recordProducers = append(recordProducers, o.LeaseExpiry)
   170  	}
   171  	err := EncodeMessageExtraData(&o.ExtraData, recordProducers...)
   172  	if err != nil {
   173  		return err
   174  	}
   175  
   176  	if err := WriteBytes(w, o.ChainHash[:]); err != nil {
   177  		return err
   178  	}
   179  
   180  	if err := WriteBytes(w, o.PendingChannelID[:]); err != nil {
   181  		return err
   182  	}
   183  
   184  	if err := WriteSatoshi(w, o.FundingAmount); err != nil {
   185  		return err
   186  	}
   187  
   188  	if err := WriteMilliAtom(w, o.PushAmount); err != nil {
   189  		return err
   190  	}
   191  
   192  	if err := WriteSatoshi(w, o.DustLimit); err != nil {
   193  		return err
   194  	}
   195  
   196  	if err := WriteMilliAtom(w, o.MaxValueInFlight); err != nil {
   197  		return err
   198  	}
   199  
   200  	if err := WriteSatoshi(w, o.ChannelReserve); err != nil {
   201  		return err
   202  	}
   203  
   204  	if err := WriteMilliAtom(w, o.HtlcMinimum); err != nil {
   205  		return err
   206  	}
   207  
   208  	if err := WriteUint32(w, o.FeePerKiloByte); err != nil {
   209  		return err
   210  	}
   211  
   212  	if err := WriteUint16(w, o.CsvDelay); err != nil {
   213  		return err
   214  	}
   215  
   216  	if err := WriteUint16(w, o.MaxAcceptedHTLCs); err != nil {
   217  		return err
   218  	}
   219  
   220  	if err := WritePublicKey(w, o.FundingKey); err != nil {
   221  		return err
   222  	}
   223  
   224  	if err := WritePublicKey(w, o.RevocationPoint); err != nil {
   225  		return err
   226  	}
   227  
   228  	if err := WritePublicKey(w, o.PaymentPoint); err != nil {
   229  		return err
   230  	}
   231  
   232  	if err := WritePublicKey(w, o.DelayedPaymentPoint); err != nil {
   233  		return err
   234  	}
   235  
   236  	if err := WritePublicKey(w, o.HtlcPoint); err != nil {
   237  		return err
   238  
   239  	}
   240  
   241  	if err := WritePublicKey(w, o.FirstCommitmentPoint); err != nil {
   242  		return err
   243  	}
   244  
   245  	if err := WriteFundingFlag(w, o.ChannelFlags); err != nil {
   246  		return err
   247  	}
   248  
   249  	return WriteBytes(w, o.ExtraData)
   250  }
   251  
   252  // Decode deserializes the serialized OpenChannel stored in the passed
   253  // io.Reader into the target OpenChannel using the deserialization rules
   254  // defined by the passed protocol version.
   255  //
   256  // This is part of the lnwire.Message interface.
   257  func (o *OpenChannel) Decode(r io.Reader, pver uint32) error {
   258  	// Read all the mandatory fields in the open message.
   259  	err := ReadElements(r,
   260  		o.ChainHash[:],
   261  		o.PendingChannelID[:],
   262  		&o.FundingAmount,
   263  		&o.PushAmount,
   264  		&o.DustLimit,
   265  		&o.MaxValueInFlight,
   266  		&o.ChannelReserve,
   267  		&o.HtlcMinimum,
   268  		&o.FeePerKiloByte,
   269  		&o.CsvDelay,
   270  		&o.MaxAcceptedHTLCs,
   271  		&o.FundingKey,
   272  		&o.RevocationPoint,
   273  		&o.PaymentPoint,
   274  		&o.DelayedPaymentPoint,
   275  		&o.HtlcPoint,
   276  		&o.FirstCommitmentPoint,
   277  		&o.ChannelFlags,
   278  	)
   279  	if err != nil {
   280  		return err
   281  	}
   282  
   283  	// For backwards compatibility, the optional extra data blob for
   284  	// OpenChannel must contain an entry for the upfront shutdown script.
   285  	// We'll read it out and attempt to parse it.
   286  	var tlvRecords ExtraOpaqueData
   287  	if err := ReadElements(r, &tlvRecords); err != nil {
   288  		return err
   289  	}
   290  
   291  	// Next we'll parse out the set of known records, keeping the raw tlv
   292  	// bytes untouched to ensure we don't drop any bytes erroneously.
   293  	var (
   294  		chanType    ChannelType
   295  		leaseExpiry LeaseExpiry
   296  	)
   297  	typeMap, err := tlvRecords.ExtractRecords(
   298  		&o.UpfrontShutdownScript, &chanType, &leaseExpiry,
   299  	)
   300  	if err != nil {
   301  		return err
   302  	}
   303  
   304  	// Set the corresponding TLV types if they were included in the stream.
   305  	if val, ok := typeMap[ChannelTypeRecordType]; ok && val == nil {
   306  		o.ChannelType = &chanType
   307  	}
   308  	if val, ok := typeMap[LeaseExpiryRecordType]; ok && val == nil {
   309  		o.LeaseExpiry = &leaseExpiry
   310  	}
   311  
   312  	o.ExtraData = tlvRecords
   313  
   314  	return nil
   315  }
   316  
   317  // MsgType returns the MessageType code which uniquely identifies this message
   318  // as an OpenChannel on the wire.
   319  //
   320  // This is part of the lnwire.Message interface.
   321  func (o *OpenChannel) MsgType() MessageType {
   322  	return MsgOpenChannel
   323  }