channel_reestablish.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. package lnwire
  2. import (
  3. "bytes"
  4. "io"
  5. "github.com/btcsuite/btcd/btcec/v2"
  6. "github.com/lightningnetwork/lnd/fn"
  7. "github.com/lightningnetwork/lnd/tlv"
  8. )
  9. const (
  10. CRDynHeight tlv.Type = 20
  11. )
  12. // DynHeight is a newtype wrapper to get the proper RecordProducer instance
  13. // to smoothly integrate with the ChannelReestablish Message instance.
  14. type DynHeight uint64
  15. // Record implements the RecordProducer interface, allowing a full tlv.Record
  16. // object to be constructed from a DynHeight.
  17. func (d *DynHeight) Record() tlv.Record {
  18. return tlv.MakePrimitiveRecord(CRDynHeight, (*uint64)(d))
  19. }
  20. // ChannelReestablish is a message sent between peers that have an existing
  21. // open channel upon connection reestablishment. This message allows both sides
  22. // to report their local state, and their current knowledge of the state of the
  23. // remote commitment chain. If a deviation is detected and can be recovered
  24. // from, then the necessary messages will be retransmitted. If the level of
  25. // desynchronization is irreconcilable, then the channel will be force closed.
  26. type ChannelReestablish struct {
  27. // ChanID is the channel ID of the channel state we're attempting to
  28. // synchronize with the remote party.
  29. ChanID ChannelID
  30. // NextLocalCommitHeight is the next local commitment height of the
  31. // sending party. If the height of the sender's commitment chain from
  32. // the receiver's Pov is one less that this number, then the sender
  33. // should re-send the *exact* same proposed commitment.
  34. //
  35. // In other words, the receiver should re-send their last sent
  36. // commitment iff:
  37. //
  38. // * NextLocalCommitHeight == remoteCommitChain.Height
  39. //
  40. // This covers the case of a lost commitment which was sent by the
  41. // sender of this message, but never received by the receiver of this
  42. // message.
  43. NextLocalCommitHeight uint64
  44. // RemoteCommitTailHeight is the height of the receiving party's
  45. // unrevoked commitment from the PoV of the sender of this message. If
  46. // the height of the receiver's commitment is *one more* than this
  47. // value, then their prior RevokeAndAck message should be
  48. // retransmitted.
  49. //
  50. // In other words, the receiver should re-send their last sent
  51. // RevokeAndAck message iff:
  52. //
  53. // * localCommitChain.tail().Height == RemoteCommitTailHeight + 1
  54. //
  55. // This covers the case of a lost revocation, wherein the receiver of
  56. // the message sent a revocation for a prior state, but the sender of
  57. // the message never fully processed it.
  58. RemoteCommitTailHeight uint64
  59. // LastRemoteCommitSecret is the last commitment secret that the
  60. // receiving node has sent to the sending party. This will be the
  61. // secret of the last revoked commitment transaction. Including this
  62. // provides proof that the sending node at least knows of this state,
  63. // as they couldn't have produced it if it wasn't sent, as the value
  64. // can be authenticated by querying the shachain or the receiving
  65. // party.
  66. LastRemoteCommitSecret [32]byte
  67. // LocalUnrevokedCommitPoint is the commitment point used in the
  68. // current un-revoked commitment transaction of the sending party.
  69. LocalUnrevokedCommitPoint *btcec.PublicKey
  70. // LocalNonce is an optional field that stores a local musig2 nonce.
  71. // This will only be populated if the simple taproot channels type was
  72. // negotiated.
  73. //
  74. LocalNonce OptMusig2NonceTLV
  75. // DynHeight is an optional field that stores the dynamic commitment
  76. // negotiation height that is incremented upon successful completion of
  77. // a dynamic commitment negotiation
  78. DynHeight fn.Option[DynHeight]
  79. // ExtraData is the set of data that was appended to this message to
  80. // fill out the full maximum transport message size. These fields can
  81. // be used to specify optional data such as custom TLV fields.
  82. ExtraData ExtraOpaqueData
  83. }
  84. // A compile time check to ensure ChannelReestablish implements the
  85. // lnwire.Message interface.
  86. var _ Message = (*ChannelReestablish)(nil)
  87. // Encode serializes the target ChannelReestablish into the passed io.Writer
  88. // observing the protocol version specified.
  89. //
  90. // This is part of the lnwire.Message interface.
  91. func (a *ChannelReestablish) Encode(w *bytes.Buffer, pver uint32) error {
  92. if err := WriteChannelID(w, a.ChanID); err != nil {
  93. return err
  94. }
  95. if err := WriteUint64(w, a.NextLocalCommitHeight); err != nil {
  96. return err
  97. }
  98. if err := WriteUint64(w, a.RemoteCommitTailHeight); err != nil {
  99. return err
  100. }
  101. // If the commit point wasn't sent, then we won't write out any of the
  102. // remaining fields as they're optional.
  103. if a.LocalUnrevokedCommitPoint == nil {
  104. // However, we'll still write out the extra data if it's
  105. // present.
  106. //
  107. // NOTE: This is here primarily for the quickcheck tests, in
  108. // practice, we'll always populate this field.
  109. return WriteBytes(w, a.ExtraData)
  110. }
  111. // Otherwise, we'll write out the remaining elements.
  112. if err := WriteBytes(w, a.LastRemoteCommitSecret[:]); err != nil {
  113. return err
  114. }
  115. if err := WritePublicKey(w, a.LocalUnrevokedCommitPoint); err != nil {
  116. return err
  117. }
  118. recordProducers := make([]tlv.RecordProducer, 0, 1)
  119. a.LocalNonce.WhenSome(func(localNonce Musig2NonceTLV) {
  120. recordProducers = append(recordProducers, &localNonce)
  121. })
  122. a.DynHeight.WhenSome(func(h DynHeight) {
  123. recordProducers = append(recordProducers, &h)
  124. })
  125. err := EncodeMessageExtraData(&a.ExtraData, recordProducers...)
  126. if err != nil {
  127. return err
  128. }
  129. return WriteBytes(w, a.ExtraData)
  130. }
  131. // Decode deserializes a serialized ChannelReestablish stored in the passed
  132. // io.Reader observing the specified protocol version.
  133. //
  134. // This is part of the lnwire.Message interface.
  135. func (a *ChannelReestablish) Decode(r io.Reader, pver uint32) error {
  136. err := ReadElements(r,
  137. &a.ChanID,
  138. &a.NextLocalCommitHeight,
  139. &a.RemoteCommitTailHeight,
  140. )
  141. if err != nil {
  142. return err
  143. }
  144. // This message has currently defined optional fields. As a result,
  145. // we'll only proceed if there's still bytes remaining within the
  146. // reader.
  147. //
  148. // We'll manually parse out the optional fields in order to be able to
  149. // still utilize the io.Reader interface.
  150. // We'll first attempt to read the optional commit secret, if we're at
  151. // the EOF, then this means the field wasn't included so we can exit
  152. // early.
  153. var buf [32]byte
  154. _, err = io.ReadFull(r, buf[:32])
  155. if err == io.EOF {
  156. // If there aren't any more bytes, then we'll emplace an empty
  157. // extra data to make our quickcheck tests happy.
  158. a.ExtraData = make([]byte, 0)
  159. return nil
  160. } else if err != nil {
  161. return err
  162. }
  163. // If the field is present, then we'll copy it over and proceed.
  164. copy(a.LastRemoteCommitSecret[:], buf[:])
  165. // We'll conclude by parsing out the commitment point. We don't check
  166. // the error in this case, as it has included the commit secret, then
  167. // they MUST also include the commit point.
  168. if err = ReadElement(r, &a.LocalUnrevokedCommitPoint); err != nil {
  169. return err
  170. }
  171. var tlvRecords ExtraOpaqueData
  172. if err := ReadElements(r, &tlvRecords); err != nil {
  173. return err
  174. }
  175. var (
  176. dynHeight DynHeight
  177. localNonce = a.LocalNonce.Zero()
  178. )
  179. typeMap, err := tlvRecords.ExtractRecords(
  180. &localNonce, &dynHeight,
  181. )
  182. if err != nil {
  183. return err
  184. }
  185. if val, ok := typeMap[a.LocalNonce.TlvType()]; ok && val == nil {
  186. a.LocalNonce = tlv.SomeRecordT(localNonce)
  187. }
  188. if val, ok := typeMap[CRDynHeight]; ok && val == nil {
  189. a.DynHeight = fn.Some(dynHeight)
  190. }
  191. if len(tlvRecords) != 0 {
  192. a.ExtraData = tlvRecords
  193. }
  194. return nil
  195. }
  196. // MsgType returns the integer uniquely identifying this message type on the
  197. // wire.
  198. //
  199. // This is part of the lnwire.Message interface.
  200. func (a *ChannelReestablish) MsgType() MessageType {
  201. return MsgChannelReestablish
  202. }