• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 13586005509

28 Feb 2025 10:14AM UTC coverage: 68.629% (+9.9%) from 58.77%
13586005509

Pull #9521

github

web-flow
Merge 37d3a70a5 into 8532955b3
Pull Request #9521: unit: remove GOACC, use Go 1.20 native coverage functionality

129950 of 189351 relevant lines covered (68.63%)

23726.46 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

79.38
/watchtower/wtwire/message.go
1
package wtwire
2

3
import (
4
        "bytes"
5
        "encoding/binary"
6
        "fmt"
7
        "io"
8
)
9

10
// MaxMessagePayload is the maximum bytes a message can be regardless of other
11
// individual limits imposed by messages themselves.
12
const MaxMessagePayload = 65535 // 65KB
13

14
// MessageType is the unique 2 byte big-endian integer that indicates the type
15
// of message on the wire. All messages have a very simple header which
16
// consists simply of 2-byte message type. We omit a length field, and checksum
17
// as the Watchtower Protocol is intended to be encapsulated within a
18
// confidential+authenticated cryptographic messaging protocol.
19
type MessageType uint16
20

21
// The currently defined message types within this current version of the
22
// Watchtower protocol.
23
const (
24
        // MsgInit identifies an encoded Init message.
25
        MsgInit MessageType = 600
26

27
        // MsgError identifies an encoded Error message.
28
        MsgError MessageType = 601
29

30
        // MsgCreateSession identifies an encoded CreateSession message.
31
        MsgCreateSession MessageType = 602
32

33
        // MsgCreateSessionReply identifies an encoded CreateSessionReply message.
34
        MsgCreateSessionReply MessageType = 603
35

36
        // MsgStateUpdate identifies an encoded StateUpdate message.
37
        MsgStateUpdate MessageType = 604
38

39
        // MsgStateUpdateReply identifies an encoded StateUpdateReply message.
40
        MsgStateUpdateReply MessageType = 605
41

42
        // MsgDeleteSession identifies an encoded DeleteSession message.
43
        MsgDeleteSession MessageType = 606
44

45
        // MsgDeleteSessionReply identifies an encoded DeleteSessionReply
46
        // message.
47
        MsgDeleteSessionReply MessageType = 607
48
)
49

50
// String returns a human readable description of the message type.
51
func (m MessageType) String() string {
14✔
52
        switch m {
14✔
53
        case MsgInit:
4✔
54
                return "Init"
4✔
55
        case MsgCreateSession:
4✔
56
                return "MsgCreateSession"
4✔
57
        case MsgCreateSessionReply:
5✔
58
                return "MsgCreateSessionReply"
5✔
59
        case MsgStateUpdate:
4✔
60
                return "MsgStateUpdate"
4✔
61
        case MsgStateUpdateReply:
4✔
62
                return "MsgStateUpdateReply"
4✔
63
        case MsgDeleteSession:
4✔
64
                return "MsgDeleteSession"
4✔
65
        case MsgDeleteSessionReply:
6✔
66
                return "MsgDeleteSessionReply"
6✔
67
        case MsgError:
1✔
68
                return "Error"
1✔
69
        default:
×
70
                return "<unknown>"
×
71
        }
72
}
73

74
// Serializable is an interface which defines a lightning wire serializable
75
// object.
76
type Serializable interface {
77
        // Decode reads the bytes stream and converts it to the object.
78
        Decode(io.Reader, uint32) error
79

80
        // Encode converts object to the bytes stream and write it into the
81
        // write buffer.
82
        Encode(io.Writer, uint32) error
83
}
84

85
// Message is an interface that defines a lightning wire protocol message. The
86
// interface is general in order to allow implementing types full control over
87
// the representation of its data.
88
type Message interface {
89
        Serializable
90

91
        // MsgType returns a MessageType that uniquely identifies the message to
92
        // be encoded.
93
        MsgType() MessageType
94

95
        // MaxPayloadLength is the maximum serialized length that a particular
96
        // message type can take.
97
        MaxPayloadLength(uint32) uint32
98
}
99

100
// makeEmptyMessage creates a new empty message of the proper concrete type
101
// based on the passed message type.
102
func makeEmptyMessage(msgType MessageType) (Message, error) {
3,325✔
103
        var msg Message
3,325✔
104

3,325✔
105
        switch msgType {
3,325✔
106
        case MsgInit:
1,087✔
107
                msg = &Init{}
1,087✔
108
        case MsgCreateSession:
238✔
109
                msg = &CreateSession{}
238✔
110
        case MsgCreateSessionReply:
224✔
111
                msg = &CreateSessionReply{}
224✔
112
        case MsgStateUpdate:
842✔
113
                msg = &StateUpdate{}
842✔
114
        case MsgStateUpdateReply:
603✔
115
                msg = &StateUpdateReply{}
603✔
116
        case MsgDeleteSession:
111✔
117
                msg = &DeleteSession{}
111✔
118
        case MsgDeleteSessionReply:
113✔
119
                msg = &DeleteSessionReply{}
113✔
120
        case MsgError:
125✔
121
                msg = &Error{}
125✔
122
        default:
×
123
                return nil, fmt.Errorf("unknown message type [%d]", msgType)
×
124
        }
125

126
        return msg, nil
3,325✔
127
}
128

129
// WriteMessage writes a lightning Message to w including the necessary header
130
// information and returns the number of bytes written.
131
func WriteMessage(w io.Writer, msg Message, pver uint32) (int, error) {
3,223✔
132
        totalBytes := 0
3,223✔
133

3,223✔
134
        // Encode the message payload itself into a temporary buffer.
3,223✔
135
        // TODO(roasbeef): create buffer pool
3,223✔
136
        var bw bytes.Buffer
3,223✔
137
        if err := msg.Encode(&bw, pver); err != nil {
3,223✔
138
                return totalBytes, err
×
139
        }
×
140
        payload := bw.Bytes()
3,223✔
141
        lenp := len(payload)
3,223✔
142

3,223✔
143
        // Enforce maximum overall message payload.
3,223✔
144
        if lenp > MaxMessagePayload {
3,223✔
145
                return totalBytes, fmt.Errorf("message payload is too large - "+
×
146
                        "encoded %d bytes, but maximum message payload is %d bytes",
×
147
                        lenp, MaxMessagePayload)
×
148
        }
×
149

150
        // Enforce maximum message payload on the message type.
151
        mpl := msg.MaxPayloadLength(pver)
3,223✔
152
        if uint32(lenp) > mpl {
3,223✔
153
                return totalBytes, fmt.Errorf("message payload is too large - "+
×
154
                        "encoded %d bytes, but maximum message payload of "+
×
155
                        "type %v is %d bytes", lenp, msg.MsgType(), mpl)
×
156
        }
×
157

158
        // With the initial sanity checks complete, we'll now write out the
159
        // message type itself.
160
        var mType [2]byte
3,223✔
161
        binary.BigEndian.PutUint16(mType[:], uint16(msg.MsgType()))
3,223✔
162
        n, err := w.Write(mType[:])
3,223✔
163
        totalBytes += n
3,223✔
164
        if err != nil {
3,223✔
165
                return totalBytes, err
×
166
        }
×
167

168
        // With the message type written, we'll now write out the raw payload
169
        // itself.
170
        n, err = w.Write(payload)
3,223✔
171
        totalBytes += n
3,223✔
172

3,223✔
173
        return totalBytes, err
3,223✔
174
}
175

176
// ReadMessage reads, validates, and parses the next Watchtower message from r
177
// for the provided protocol version.
178
func ReadMessage(r io.Reader, pver uint32) (Message, error) {
3,325✔
179
        // First, we'll read out the first two bytes of the message so we can
3,325✔
180
        // create the proper empty message.
3,325✔
181
        var mType [2]byte
3,325✔
182
        if _, err := io.ReadFull(r, mType[:]); err != nil {
3,325✔
183
                return nil, err
×
184
        }
×
185

186
        msgType := MessageType(binary.BigEndian.Uint16(mType[:]))
3,325✔
187

3,325✔
188
        // Now that we know the target message type, we can create the proper
3,325✔
189
        // empty message type and decode the message into it.
3,325✔
190
        msg, err := makeEmptyMessage(msgType)
3,325✔
191
        if err != nil {
3,325✔
192
                return nil, err
×
193
        }
×
194
        if err := msg.Decode(r, pver); err != nil {
3,397✔
195
                return nil, err
72✔
196
        }
72✔
197

198
        return msg, nil
3,253✔
199
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc