Also freeze the lnwire and record packages used by the migration. Copy the minimal subset of lnwire files (16) into payments/db/migration1/lnwire/ and all record files (6) into payments/db/migration1/record/. Three lnwire files are trimmed to avoid pulling in the full message-type dispatch tree — all changes are purely subtractive and can be verified with: diff lnwire/message.go payments/db/migration1/lnwire/message.go diff lnwire/writer.go payments/db/migration1/lnwire/writer.go diff lnwire/lnwire.go payments/db/migration1/lnwire/lnwire.go All migration1 files now import only the frozen packages, removing the live dependency on lnwire and record so future changes to those packages cannot affect migration correctness.
324 lines
10 KiB
Go
324 lines
10 KiB
Go
// Copyright (c) 2013-2017 The btcsuite developers
|
|
// Copyright (c) 2015-2016 The Decred developers
|
|
// code derived from https://github .com/btcsuite/btcd/blob/master/wire/message.go
|
|
// Copyright (C) 2015-2022 The Lightning Network Developers
|
|
|
|
package lnwire
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"io"
|
|
)
|
|
|
|
// MessageTypeSize is the size in bytes of the message type field in the header
|
|
// of all messages.
|
|
const MessageTypeSize = 2
|
|
|
|
// MessageType is the unique 2 byte big-endian integer that indicates the type
|
|
// of message on the wire. All messages have a very simple header which
|
|
// consists simply of 2-byte message type. We omit a length field, and checksum
|
|
// as the Lightning Protocol is intended to be encapsulated within a
|
|
// confidential+authenticated cryptographic messaging protocol.
|
|
type MessageType uint16
|
|
|
|
// The currently defined message types within this current version of the
|
|
// Lightning protocol.
|
|
const (
|
|
MsgWarning MessageType = 1
|
|
MsgStfu = 2
|
|
MsgInit = 16
|
|
MsgError = 17
|
|
MsgPing = 18
|
|
MsgPong = 19
|
|
MsgOpenChannel = 32
|
|
MsgAcceptChannel = 33
|
|
MsgFundingCreated = 34
|
|
MsgFundingSigned = 35
|
|
MsgChannelReady = 36
|
|
MsgShutdown = 38
|
|
MsgClosingSigned = 39
|
|
MsgClosingComplete = 40
|
|
MsgClosingSig = 41
|
|
MsgDynPropose = 111
|
|
MsgDynAck = 113
|
|
MsgDynReject = 115
|
|
MsgDynCommit = 117
|
|
MsgUpdateAddHTLC = 128
|
|
MsgUpdateFulfillHTLC = 130
|
|
MsgUpdateFailHTLC = 131
|
|
MsgCommitSig = 132
|
|
MsgRevokeAndAck = 133
|
|
MsgUpdateFee = 134
|
|
MsgUpdateFailMalformedHTLC = 135
|
|
MsgChannelReestablish = 136
|
|
MsgChannelAnnouncement = 256
|
|
MsgNodeAnnouncement = 257
|
|
MsgChannelUpdate = 258
|
|
MsgAnnounceSignatures = 259
|
|
MsgAnnounceSignatures2 = 260
|
|
MsgQueryShortChanIDs = 261
|
|
MsgReplyShortChanIDsEnd = 262
|
|
MsgQueryChannelRange = 263
|
|
MsgReplyChannelRange = 264
|
|
MsgGossipTimestampRange = 265
|
|
MsgChannelAnnouncement2 = 267
|
|
MsgNodeAnnouncement2 = 269
|
|
MsgChannelUpdate2 = 271
|
|
MsgOnionMessage = 513
|
|
MsgKickoffSig = 777
|
|
|
|
// MsgEnd defines the end of the official message range of the protocol.
|
|
// If a new message is added beyond this message, then this should be
|
|
// modified.
|
|
MsgEnd = 778
|
|
)
|
|
|
|
// IsChannelUpdate is a filter function that discerns channel update messages
|
|
// from the other messages in the Lightning Network Protocol.
|
|
func (t MessageType) IsChannelUpdate() bool {
|
|
switch t {
|
|
case MsgUpdateAddHTLC:
|
|
return true
|
|
case MsgUpdateFulfillHTLC:
|
|
return true
|
|
case MsgUpdateFailHTLC:
|
|
return true
|
|
case MsgUpdateFailMalformedHTLC:
|
|
return true
|
|
case MsgUpdateFee:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// ErrorEncodeMessage is used when failed to encode the message payload.
|
|
func ErrorEncodeMessage(err error) error {
|
|
return fmt.Errorf("failed to encode message to buffer, got %w", err)
|
|
}
|
|
|
|
// ErrorWriteMessageType is used when failed to write the message type.
|
|
func ErrorWriteMessageType(err error) error {
|
|
return fmt.Errorf("failed to write message type, got %w", err)
|
|
}
|
|
|
|
// ErrorPayloadTooLarge is used when the payload size exceeds the
|
|
// MaxMsgBody.
|
|
func ErrorPayloadTooLarge(size int) error {
|
|
return fmt.Errorf(
|
|
"message payload is too large - encoded %d bytes, "+
|
|
"but maximum message payload is %d bytes",
|
|
size, MaxMsgBody,
|
|
)
|
|
}
|
|
|
|
// String return the string representation of message type.
|
|
func (t MessageType) String() string {
|
|
switch t {
|
|
case MsgWarning:
|
|
return "Warning"
|
|
case MsgStfu:
|
|
return "Stfu"
|
|
case MsgInit:
|
|
return "Init"
|
|
case MsgOpenChannel:
|
|
return "MsgOpenChannel"
|
|
case MsgAcceptChannel:
|
|
return "MsgAcceptChannel"
|
|
case MsgFundingCreated:
|
|
return "MsgFundingCreated"
|
|
case MsgFundingSigned:
|
|
return "MsgFundingSigned"
|
|
case MsgChannelReady:
|
|
return "ChannelReady"
|
|
case MsgShutdown:
|
|
return "Shutdown"
|
|
case MsgClosingSigned:
|
|
return "ClosingSigned"
|
|
case MsgDynPropose:
|
|
return "DynPropose"
|
|
case MsgDynAck:
|
|
return "DynAck"
|
|
case MsgDynReject:
|
|
return "DynReject"
|
|
case MsgDynCommit:
|
|
return "DynCommit"
|
|
case MsgKickoffSig:
|
|
return "KickoffSig"
|
|
case MsgUpdateAddHTLC:
|
|
return "UpdateAddHTLC"
|
|
case MsgUpdateFailHTLC:
|
|
return "UpdateFailHTLC"
|
|
case MsgUpdateFulfillHTLC:
|
|
return "UpdateFulfillHTLC"
|
|
case MsgCommitSig:
|
|
return "CommitSig"
|
|
case MsgRevokeAndAck:
|
|
return "RevokeAndAck"
|
|
case MsgUpdateFailMalformedHTLC:
|
|
return "UpdateFailMalformedHTLC"
|
|
case MsgChannelReestablish:
|
|
return "ChannelReestablish"
|
|
case MsgError:
|
|
return "Error"
|
|
case MsgChannelAnnouncement:
|
|
return "ChannelAnnouncement"
|
|
case MsgChannelUpdate:
|
|
return "ChannelUpdate"
|
|
case MsgNodeAnnouncement:
|
|
return "NodeAnnouncement1"
|
|
case MsgPing:
|
|
return "Ping"
|
|
case MsgAnnounceSignatures:
|
|
return "AnnounceSignatures"
|
|
case MsgPong:
|
|
return "Pong"
|
|
case MsgUpdateFee:
|
|
return "UpdateFee"
|
|
case MsgQueryShortChanIDs:
|
|
return "QueryShortChanIDs"
|
|
case MsgReplyShortChanIDsEnd:
|
|
return "ReplyShortChanIDsEnd"
|
|
case MsgQueryChannelRange:
|
|
return "QueryChannelRange"
|
|
case MsgReplyChannelRange:
|
|
return "ReplyChannelRange"
|
|
case MsgGossipTimestampRange:
|
|
return "GossipTimestampRange"
|
|
case MsgClosingComplete:
|
|
return "ClosingComplete"
|
|
case MsgClosingSig:
|
|
return "ClosingSig"
|
|
case MsgAnnounceSignatures2:
|
|
return "MsgAnnounceSignatures2"
|
|
case MsgChannelAnnouncement2:
|
|
return "ChannelAnnouncement2"
|
|
case MsgNodeAnnouncement2:
|
|
return "NodeAnnouncement2"
|
|
case MsgChannelUpdate2:
|
|
return "ChannelUpdate2"
|
|
case MsgOnionMessage:
|
|
return "OnionMessage"
|
|
default:
|
|
return "<unknown>"
|
|
}
|
|
}
|
|
|
|
// UnknownMessage is an implementation of the error interface that allows the
|
|
// creation of an error in response to an unknown message.
|
|
type UnknownMessage struct {
|
|
messageType MessageType
|
|
}
|
|
|
|
// Error returns a human readable string describing the error.
|
|
//
|
|
// This is part of the error interface.
|
|
func (u *UnknownMessage) Error() string {
|
|
return fmt.Sprintf("unable to parse message of unknown type: %v",
|
|
u.messageType)
|
|
}
|
|
|
|
// Serializable is an interface which defines a lightning wire serializable
|
|
// object.
|
|
type Serializable interface {
|
|
// Decode reads the bytes stream and converts it to the object.
|
|
Decode(io.Reader, uint32) error
|
|
|
|
// Encode converts object to the bytes stream and write it into the
|
|
// write buffer.
|
|
Encode(*bytes.Buffer, uint32) error
|
|
}
|
|
|
|
// Message is an interface that defines a lightning wire protocol message. The
|
|
// interface is general in order to allow implementing types full control over
|
|
// the representation of its data.
|
|
type Message interface {
|
|
Serializable
|
|
MsgType() MessageType
|
|
}
|
|
|
|
// LinkUpdater is an interface implemented by most messages in BOLT 2 that are
|
|
// allowed to update the channel state.
|
|
type LinkUpdater interface {
|
|
// All LinkUpdater messages are messages and so we embed the interface
|
|
// so that we can treat it as a message if all we know about it is that
|
|
// it is a LinkUpdater message.
|
|
Message
|
|
|
|
// TargetChanID returns the channel id of the link for which this
|
|
// message is intended.
|
|
TargetChanID() ChannelID
|
|
}
|
|
|
|
// SizeableMessage is an interface that extends the base Message interface with
|
|
// a method to calculate the serialized size of a message.
|
|
type SizeableMessage interface {
|
|
Message
|
|
|
|
// SerializedSize returns the serialized size of the message in bytes.
|
|
// The returned size includes the message type header bytes.
|
|
SerializedSize() (uint32, error)
|
|
}
|
|
|
|
// MessageSerializedSize calculates the serialized size of a message in bytes.
|
|
// This is a helper function that can be used by all message types to implement
|
|
// the SerializedSize method.
|
|
func MessageSerializedSize(msg Message) (uint32, error) {
|
|
var buf bytes.Buffer
|
|
|
|
// Encode the message to the buffer.
|
|
if err := msg.Encode(&buf, 0); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
// Add the size of the message type.
|
|
return uint32(buf.Len()) + MessageTypeSize, nil
|
|
}
|
|
|
|
// WriteMessage writes a lightning Message to a buffer including the necessary
|
|
// header information and returns the number of bytes written. If any error is
|
|
// encountered, the buffer passed will be reset to its original state since we
|
|
// don't want any broken bytes left. In other words, no bytes will be written
|
|
// if there's an error. Either all or none of the message bytes will be written
|
|
// to the buffer.
|
|
//
|
|
// NOTE: this method is not concurrent safe.
|
|
func WriteMessage(buf *bytes.Buffer, msg Message, pver uint32) (int, error) {
|
|
// Record the size of the bytes already written in buffer.
|
|
oldByteSize := buf.Len()
|
|
|
|
// cleanBrokenBytes is a helper closure that helps reset the buffer to
|
|
// its original state. It truncates all the bytes written in current
|
|
// scope.
|
|
var cleanBrokenBytes = func(b *bytes.Buffer) int {
|
|
b.Truncate(oldByteSize)
|
|
return 0
|
|
}
|
|
|
|
// Write the message type.
|
|
var mType [2]byte
|
|
binary.BigEndian.PutUint16(mType[:], uint16(msg.MsgType()))
|
|
msgTypeBytes, err := buf.Write(mType[:])
|
|
if err != nil {
|
|
return cleanBrokenBytes(buf), ErrorWriteMessageType(err)
|
|
}
|
|
|
|
// Use the write buffer to encode our message.
|
|
if err := msg.Encode(buf, pver); err != nil {
|
|
return cleanBrokenBytes(buf), ErrorEncodeMessage(err)
|
|
}
|
|
|
|
// Enforce maximum overall message payload. The write buffer now has
|
|
// the size of len(originalBytes) + len(payload) + len(type). We want
|
|
// to enforce the payload here, so we subtract it by the length of the
|
|
// type and old bytes.
|
|
lenp := buf.Len() - oldByteSize - msgTypeBytes
|
|
if lenp > MaxMsgBody {
|
|
return cleanBrokenBytes(buf), ErrorPayloadTooLarge(lenp)
|
|
}
|
|
|
|
return buf.Len() - oldByteSize, nil
|
|
}
|