Merge pull request #9263 from morehouse/simplify_fuzz_lnwire

lnwire: simplify fuzz targets
This commit is contained in:
Oliver Gugger
2024-11-13 18:32:15 +01:00
committed by GitHub

View File

@ -4,7 +4,6 @@ import (
"bytes" "bytes"
"compress/zlib" "compress/zlib"
"encoding/binary" "encoding/binary"
"reflect"
"testing" "testing"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -20,12 +19,18 @@ func prefixWithMsgType(data []byte, prefix MessageType) []byte {
return data return data
} }
// harness performs the actual fuzz testing of the appropriate wire message. // assertEqualFunc is a function used to assert that two deserialized messages
// This function will check that the passed-in message passes wire length // are equivalent.
// checks, is a valid message once deserialized, and passes a sequence of type assertEqualFunc func(t *testing.T, x, y any)
// wireMsgHarnessCustom performs the actual fuzz testing of the appropriate wire
// message. This function will check that the passed-in message passes wire
// length checks, is a valid message once deserialized, and passes a sequence of
// serialization and deserialization checks. // serialization and deserialization checks.
func harness(t *testing.T, data []byte) { func wireMsgHarnessCustom(t *testing.T, data []byte, msgType MessageType,
t.Helper() assertEqual assertEqualFunc) {
data = prefixWithMsgType(data, msgType)
// Create a reader with the byte array. // Create a reader with the byte array.
r := bytes.NewReader(data) r := bytes.NewReader(data)
@ -51,423 +56,235 @@ func harness(t *testing.T, data []byte) {
// message. // message.
newMsg, err := ReadMessage(&b, 0) newMsg, err := ReadMessage(&b, 0)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, msg, newMsg)
assertEqual(t, msg, newMsg)
}
func wireMsgHarness(t *testing.T, data []byte, msgType MessageType) {
t.Helper()
assertEq := func(t *testing.T, x, y any) {
require.Equal(t, x, y)
}
wireMsgHarnessCustom(t, data, msgType, assertEq)
} }
func FuzzAcceptChannel(f *testing.F) { func FuzzAcceptChannel(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
data = prefixWithMsgType(data, MsgAcceptChannel)
// Create a reader with the byte array.
r := bytes.NewReader(data)
// Make sure byte array length (excluding 2 bytes for message
// type) is less than max payload size for the wire message.
payloadLen := uint32(len(data)) - 2
if payloadLen > MaxMsgBody {
return
}
msg, err := ReadMessage(r, 0)
if err != nil {
return
}
// We will serialize the message into a new bytes buffer.
var b bytes.Buffer
_, err = WriteMessage(&b, msg, 0)
require.NoError(t, err)
// Deserialize the message from the serialized bytes buffer, and
// then assert that the original message is equal to the newly
// deserialized message.
newMsg, err := ReadMessage(&b, 0)
require.NoError(t, err)
require.IsType(t, &AcceptChannel{}, msg)
first, _ := msg.(*AcceptChannel)
require.IsType(t, &AcceptChannel{}, newMsg)
second, _ := newMsg.(*AcceptChannel)
// We can't use require.Equal for UpfrontShutdownScript, since // We can't use require.Equal for UpfrontShutdownScript, since
// we consider the empty slice and nil to be equivalent. // we consider the empty slice and nil to be equivalent.
require.True( assertEq := func(t *testing.T, x, y any) {
t, bytes.Equal( require.IsType(t, &AcceptChannel{}, x)
first.UpfrontShutdownScript, first, _ := x.(*AcceptChannel)
second.UpfrontShutdownScript, require.IsType(t, &AcceptChannel{}, y)
), second, _ := y.(*AcceptChannel)
)
first.UpfrontShutdownScript = nil
second.UpfrontShutdownScript = nil
require.Equal(t, first, second) require.True(
t, bytes.Equal(
first.UpfrontShutdownScript,
second.UpfrontShutdownScript,
),
)
first.UpfrontShutdownScript = nil
second.UpfrontShutdownScript = nil
require.Equal(t, first, second)
}
wireMsgHarnessCustom(t, data, MsgAcceptChannel, assertEq)
}) })
} }
func FuzzAnnounceSignatures(f *testing.F) { func FuzzAnnounceSignatures(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgAnnounceSignatures. wireMsgHarness(t, data, MsgAnnounceSignatures)
data = prefixWithMsgType(data, MsgAnnounceSignatures)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzAnnounceSignatures2(f *testing.F) { func FuzzAnnounceSignatures2(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgAnnounceSignatures2. wireMsgHarness(t, data, MsgAnnounceSignatures2)
data = prefixWithMsgType(data, MsgAnnounceSignatures2)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzChannelAnnouncement(f *testing.F) { func FuzzChannelAnnouncement(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgChannelAnnouncement. wireMsgHarness(t, data, MsgChannelAnnouncement)
data = prefixWithMsgType(data, MsgChannelAnnouncement)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzChannelAnnouncement2(f *testing.F) { func FuzzChannelAnnouncement2(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgChannelAnnouncement2.
data = prefixWithMsgType(data, MsgChannelAnnouncement2)
// Because require.Equal considers nil maps and empty maps
// to be non-equal, we must manually compare Features field
// rather than using the harness.
if len(data) > MaxSliceLength {
return
}
r := bytes.NewReader(data)
msg, err := ReadMessage(r, 0)
if err != nil {
return
}
// We will serialize the message into a new bytes buffer.
var b bytes.Buffer
_, err = WriteMessage(&b, msg, 0)
require.NoError(t, err)
// Deserialize the message from the serialized bytes buffer, and
// then assert that the original message is equal to the newly
// deserialized message.
newMsg, err := ReadMessage(&b, 0)
require.NoError(t, err)
require.IsType(t, &ChannelAnnouncement2{}, msg)
first, _ := msg.(*ChannelAnnouncement2)
require.IsType(t, &ChannelAnnouncement2{}, newMsg)
second, _ := newMsg.(*ChannelAnnouncement2)
// We can't use require.Equal for Features, since we consider // We can't use require.Equal for Features, since we consider
// the empty map and nil to be equivalent. // the empty map and nil to be equivalent.
require.True(t, first.Features.Val.Equals(&second.Features.Val)) assertEq := func(t *testing.T, x, y any) {
first.Features.Val = *NewRawFeatureVector() require.IsType(t, &ChannelAnnouncement2{}, x)
second.Features.Val = *NewRawFeatureVector() first, _ := x.(*ChannelAnnouncement2)
require.IsType(t, &ChannelAnnouncement2{}, y)
second, _ := y.(*ChannelAnnouncement2)
require.Equal(t, first, second) require.True(
t,
first.Features.Val.Equals(&second.Features.Val),
)
first.Features.Val = *NewRawFeatureVector()
second.Features.Val = *NewRawFeatureVector()
require.Equal(t, first, second)
}
wireMsgHarnessCustom(t, data, MsgChannelAnnouncement2, assertEq)
}) })
} }
func FuzzChannelReestablish(f *testing.F) { func FuzzChannelReestablish(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgChannelReestablish. wireMsgHarness(t, data, MsgChannelReestablish)
data = prefixWithMsgType(data, MsgChannelReestablish)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzChannelUpdate(f *testing.F) { func FuzzChannelUpdate(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgChannelUpdate. wireMsgHarness(t, data, MsgChannelUpdate)
data = prefixWithMsgType(data, MsgChannelUpdate)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzChannelUpdate2(f *testing.F) { func FuzzChannelUpdate2(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgChannelUpdate2. wireMsgHarness(t, data, MsgChannelUpdate2)
data = prefixWithMsgType(data, MsgChannelUpdate2)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzClosingSigned(f *testing.F) { func FuzzClosingSigned(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgClosingSigned. wireMsgHarness(t, data, MsgClosingSigned)
data = prefixWithMsgType(data, MsgClosingSigned)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzCommitSig(f *testing.F) { func FuzzCommitSig(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgCommitSig. wireMsgHarness(t, data, MsgCommitSig)
data = prefixWithMsgType(data, MsgCommitSig)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzError(f *testing.F) { func FuzzError(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgError. wireMsgHarness(t, data, MsgError)
data = prefixWithMsgType(data, MsgError)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzWarning(f *testing.F) { func FuzzWarning(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgWarning. wireMsgHarness(t, data, MsgWarning)
data = prefixWithMsgType(data, MsgWarning)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzStfu(f *testing.F) { func FuzzStfu(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgStfu. wireMsgHarness(t, data, MsgStfu)
data = prefixWithMsgType(data, MsgStfu)
// Pass the message into our general fuzz harness for wire
// messages.
harness(t, data)
}) })
} }
func FuzzFundingCreated(f *testing.F) { func FuzzFundingCreated(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgFundingCreated. wireMsgHarness(t, data, MsgFundingCreated)
data = prefixWithMsgType(data, MsgFundingCreated)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzChannelReady(f *testing.F) { func FuzzChannelReady(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgChannelReady. wireMsgHarness(t, data, MsgChannelReady)
data = prefixWithMsgType(data, MsgChannelReady)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzFundingSigned(f *testing.F) { func FuzzFundingSigned(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgFundingSigned. wireMsgHarness(t, data, MsgFundingSigned)
data = prefixWithMsgType(data, MsgFundingSigned)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzGossipTimestampRange(f *testing.F) { func FuzzGossipTimestampRange(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgGossipTimestampRange. wireMsgHarness(t, data, MsgGossipTimestampRange)
data = prefixWithMsgType(data, MsgGossipTimestampRange)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzInit(f *testing.F) { func FuzzInit(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgInit. wireMsgHarness(t, data, MsgInit)
data = prefixWithMsgType(data, MsgInit)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzNodeAnnouncement(f *testing.F) { func FuzzNodeAnnouncement(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgNodeAnnouncement.
data = prefixWithMsgType(data, MsgNodeAnnouncement)
// We have to do this here instead of in harness so that
// reflect.DeepEqual isn't called. Address (de)serialization
// messes up the fuzzing assertions.
// Create a reader with the byte array.
r := bytes.NewReader(data)
// Make sure byte array length (excluding 2 bytes for message
// type) is less than max payload size for the wire message.
payloadLen := uint32(len(data)) - 2
if payloadLen > MaxMsgBody {
return
}
msg, err := ReadMessage(r, 0)
if err != nil {
return
}
// We will serialize the message into a new bytes buffer.
var b bytes.Buffer
_, err = WriteMessage(&b, msg, 0)
require.NoError(t, err)
// Deserialize the message from the serialized bytes buffer, and
// then assert that the original message is equal to the newly
// deserialized message.
newMsg, err := ReadMessage(&b, 0)
require.NoError(t, err)
require.IsType(t, &NodeAnnouncement{}, msg)
first, _ := msg.(*NodeAnnouncement)
require.IsType(t, &NodeAnnouncement{}, newMsg)
second, _ := newMsg.(*NodeAnnouncement)
// We can't use require.Equal for Addresses, since the same IP // We can't use require.Equal for Addresses, since the same IP
// can be represented by different underlying bytes. Instead, we // can be represented by different underlying bytes. Instead, we
// compare the normalized string representation of each address. // compare the normalized string representation of each address.
require.Equal(t, len(first.Addresses), len(second.Addresses)) assertEq := func(t *testing.T, x, y any) {
for i := range first.Addresses { require.IsType(t, &NodeAnnouncement{}, x)
require.Equal( first, _ := x.(*NodeAnnouncement)
t, first.Addresses[i].String(), require.IsType(t, &NodeAnnouncement{}, y)
second.Addresses[i].String(), second, _ := y.(*NodeAnnouncement)
)
}
first.Addresses = nil
second.Addresses = nil
require.Equal(t, first, second) require.Equal(
t, len(first.Addresses), len(second.Addresses),
)
for i := range first.Addresses {
require.Equal(
t, first.Addresses[i].String(),
second.Addresses[i].String(),
)
}
first.Addresses = nil
second.Addresses = nil
require.Equal(t, first, second)
}
wireMsgHarnessCustom(t, data, MsgNodeAnnouncement, assertEq)
}) })
} }
func FuzzOpenChannel(f *testing.F) { func FuzzOpenChannel(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgOpenChannel.
data = prefixWithMsgType(data, MsgOpenChannel)
// We have to do this here instead of in harness so that
// reflect.DeepEqual isn't called. Because of the
// UpfrontShutdownScript encoding, the first message and second
// message aren't deeply equal since the first has a nil slice
// and the other has an empty slice.
// Create a reader with the byte array.
r := bytes.NewReader(data)
// Make sure byte array length (excluding 2 bytes for message
// type) is less than max payload size for the wire message.
payloadLen := uint32(len(data)) - 2
if payloadLen > MaxMsgBody {
return
}
msg, err := ReadMessage(r, 0)
if err != nil {
return
}
// We will serialize the message into a new bytes buffer.
var b bytes.Buffer
_, err = WriteMessage(&b, msg, 0)
require.NoError(t, err)
// Deserialize the message from the serialized bytes buffer, and
// then assert that the original message is equal to the newly
// deserialized message.
newMsg, err := ReadMessage(&b, 0)
require.NoError(t, err)
require.IsType(t, &OpenChannel{}, msg)
first, _ := msg.(*OpenChannel)
require.IsType(t, &OpenChannel{}, newMsg)
second, _ := newMsg.(*OpenChannel)
// We can't use require.Equal for UpfrontShutdownScript, since // We can't use require.Equal for UpfrontShutdownScript, since
// we consider the empty slice and nil to be equivalent. // we consider the empty slice and nil to be equivalent.
require.True( assertEq := func(t *testing.T, x, y any) {
t, bytes.Equal( require.IsType(t, &OpenChannel{}, x)
first.UpfrontShutdownScript, first, _ := x.(*OpenChannel)
second.UpfrontShutdownScript, require.IsType(t, &OpenChannel{}, y)
), second, _ := y.(*OpenChannel)
)
first.UpfrontShutdownScript = nil
second.UpfrontShutdownScript = nil
require.Equal(t, first, second) require.True(
t, bytes.Equal(
first.UpfrontShutdownScript,
second.UpfrontShutdownScript,
),
)
first.UpfrontShutdownScript = nil
second.UpfrontShutdownScript = nil
require.Equal(t, first, second)
}
wireMsgHarnessCustom(t, data, MsgOpenChannel, assertEq)
}) })
} }
func FuzzPing(f *testing.F) { func FuzzPing(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgPing. wireMsgHarness(t, data, MsgPing)
data = prefixWithMsgType(data, MsgPing)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzPong(f *testing.F) { func FuzzPong(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgPong. wireMsgHarness(t, data, MsgPong)
data = prefixWithMsgType(data, MsgPong)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzQueryChannelRange(f *testing.F) { func FuzzQueryChannelRange(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgQueryChannelRange. wireMsgHarness(t, data, MsgQueryChannelRange)
data = prefixWithMsgType(data, MsgQueryChannelRange)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
@ -495,23 +312,13 @@ func FuzzZlibQueryShortChanIDs(f *testing.F) {
payload = append(payload, zlibByte...) payload = append(payload, zlibByte...)
payload = append(payload, compressedPayload...) payload = append(payload, compressedPayload...)
// Prefix with MsgQueryShortChanIDs. wireMsgHarness(t, payload, MsgQueryShortChanIDs)
payload = prefixWithMsgType(payload, MsgQueryShortChanIDs)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, payload)
}) })
} }
func FuzzQueryShortChanIDs(f *testing.F) { func FuzzQueryShortChanIDs(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgQueryShortChanIDs. wireMsgHarness(t, data, MsgQueryShortChanIDs)
data = prefixWithMsgType(data, MsgQueryShortChanIDs)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
@ -547,193 +354,107 @@ func FuzzZlibReplyChannelRange(f *testing.F) {
payload = append(payload, zlibByte...) payload = append(payload, zlibByte...)
payload = append(payload, compressedPayload...) payload = append(payload, compressedPayload...)
// Prefix with MsgReplyChannelRange. wireMsgHarness(t, payload, MsgReplyChannelRange)
payload = prefixWithMsgType(payload, MsgReplyChannelRange)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, payload)
}) })
} }
func FuzzReplyChannelRange(f *testing.F) { func FuzzReplyChannelRange(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgReplyChannelRange.
data = prefixWithMsgType(data, MsgReplyChannelRange)
// Because require.Equal considers nil slices and empty slices
// to be non-equal, we must manually compare the Timestamps
// field rather than using the harness.
if len(data) > MaxSliceLength {
return
}
r := bytes.NewReader(data)
msg, err := ReadMessage(r, 0)
if err != nil {
return
}
// We will serialize the message into a new bytes buffer.
var b bytes.Buffer
_, err = WriteMessage(&b, msg, 0)
require.NoError(t, err)
// Deserialize the message from the serialized bytes buffer, and
// then assert that the original message is equal to the newly
// deserialized message.
newMsg, err := ReadMessage(&b, 0)
require.NoError(t, err)
require.IsType(t, &ReplyChannelRange{}, msg)
first, _ := msg.(*ReplyChannelRange)
require.IsType(t, &ReplyChannelRange{}, newMsg)
second, _ := newMsg.(*ReplyChannelRange)
// We can't use require.Equal for Timestamps, since we consider // We can't use require.Equal for Timestamps, since we consider
// the empty slice and nil to be equivalent. // the empty slice and nil to be equivalent.
require.Equal(t, len(first.Timestamps), len(second.Timestamps)) assertEq := func(t *testing.T, x, y any) {
for i, ts1 := range first.Timestamps { require.IsType(t, &ReplyChannelRange{}, x)
ts2 := second.Timestamps[i] first, _ := x.(*ReplyChannelRange)
require.Equal(t, ts1, ts2) require.IsType(t, &ReplyChannelRange{}, y)
} second, _ := y.(*ReplyChannelRange)
first.Timestamps = nil
second.Timestamps = nil
require.Equal(t, first, second) require.Equal(
t, len(first.Timestamps),
len(second.Timestamps),
)
for i, ts1 := range first.Timestamps {
ts2 := second.Timestamps[i]
require.Equal(t, ts1, ts2)
}
first.Timestamps = nil
second.Timestamps = nil
require.Equal(t, first, second)
}
wireMsgHarnessCustom(t, data, MsgReplyChannelRange, assertEq)
}) })
} }
func FuzzReplyShortChanIDsEnd(f *testing.F) { func FuzzReplyShortChanIDsEnd(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgReplyShortChanIDsEnd. wireMsgHarness(t, data, MsgReplyShortChanIDsEnd)
data = prefixWithMsgType(data, MsgReplyShortChanIDsEnd)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzRevokeAndAck(f *testing.F) { func FuzzRevokeAndAck(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgRevokeAndAck. wireMsgHarness(t, data, MsgRevokeAndAck)
data = prefixWithMsgType(data, MsgRevokeAndAck)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzShutdown(f *testing.F) { func FuzzShutdown(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgShutdown. wireMsgHarness(t, data, MsgShutdown)
data = prefixWithMsgType(data, MsgShutdown)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzUpdateAddHTLC(f *testing.F) { func FuzzUpdateAddHTLC(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgUpdateAddHTLC. wireMsgHarness(t, data, MsgUpdateAddHTLC)
data = prefixWithMsgType(data, MsgUpdateAddHTLC)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzUpdateFailHTLC(f *testing.F) { func FuzzUpdateFailHTLC(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgUpdateFailHTLC. wireMsgHarness(t, data, MsgUpdateFailHTLC)
data = prefixWithMsgType(data, MsgUpdateFailHTLC)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzUpdateFailMalformedHTLC(f *testing.F) { func FuzzUpdateFailMalformedHTLC(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgUpdateFailMalformedHTLC. wireMsgHarness(t, data, MsgUpdateFailMalformedHTLC)
data = prefixWithMsgType(data, MsgUpdateFailMalformedHTLC)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzUpdateFee(f *testing.F) { func FuzzUpdateFee(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgUpdateFee. wireMsgHarness(t, data, MsgUpdateFee)
data = prefixWithMsgType(data, MsgUpdateFee)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzUpdateFulfillHTLC(f *testing.F) { func FuzzUpdateFulfillHTLC(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with MsgUpdateFulFillHTLC. wireMsgHarness(t, data, MsgUpdateFulfillHTLC)
data = prefixWithMsgType(data, MsgUpdateFulfillHTLC)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzDynPropose(f *testing.F) { func FuzzDynPropose(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with DynPropose. wireMsgHarness(t, data, MsgDynPropose)
data = prefixWithMsgType(data, MsgDynPropose)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzDynReject(f *testing.F) { func FuzzDynReject(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with DynReject. wireMsgHarness(t, data, MsgDynReject)
data = prefixWithMsgType(data, MsgDynReject)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzDynAck(f *testing.F) { func FuzzDynAck(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with DynReject. wireMsgHarness(t, data, MsgDynAck)
data = prefixWithMsgType(data, MsgDynAck)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzKickoffSig(f *testing.F) { func FuzzKickoffSig(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with KickoffSig wireMsgHarness(t, data, MsgKickoffSig)
data = prefixWithMsgType(data, MsgKickoffSig)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
@ -743,12 +464,7 @@ func FuzzCustomMessage(f *testing.F) {
customMessageType += uint16(CustomTypeStart) customMessageType += uint16(CustomTypeStart)
} }
// Prefix with CustomMessage. wireMsgHarness(t, data, MessageType(customMessageType))
data = prefixWithMsgType(data, MessageType(customMessageType))
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
@ -837,16 +553,12 @@ func prefixWithFailCode(data []byte, code FailCode) []byte {
return data return data
} }
// equalFunc is a function used to determine whether two deserialized messages
// are equivalent.
type equalFunc func(x, y any) bool
// onionFailureHarnessCustom performs the actual fuzz testing of the appropriate // onionFailureHarnessCustom performs the actual fuzz testing of the appropriate
// onion failure message. This function will check that the passed-in message // onion failure message. This function will check that the passed-in message
// passes wire length checks, is a valid message once deserialized, and passes a // passes wire length checks, is a valid message once deserialized, and passes a
// sequence of serialization and deserialization checks. // sequence of serialization and deserialization checks.
func onionFailureHarnessCustom(t *testing.T, data []byte, code FailCode, func onionFailureHarnessCustom(t *testing.T, data []byte, code FailCode,
eq equalFunc) { assertEqual assertEqualFunc) {
data = prefixWithFailCode(data, code) data = prefixWithFailCode(data, code)
@ -872,12 +584,7 @@ func onionFailureHarnessCustom(t *testing.T, data []byte, code FailCode,
newMsg, err := DecodeFailureMessage(&b, 0) newMsg, err := DecodeFailureMessage(&b, 0)
require.NoError(t, err, "failed to decode serialized failure message") require.NoError(t, err, "failed to decode serialized failure message")
require.True( assertEqual(t, msg, newMsg)
t, eq(msg, newMsg),
"original message and deserialized message are not equal: "+
"%v != %v",
msg, newMsg,
)
// Now verify that encoding/decoding full packets works as expected. // Now verify that encoding/decoding full packets works as expected.
@ -911,17 +618,15 @@ func onionFailureHarnessCustom(t *testing.T, data []byte, code FailCode,
pktMsg, err := DecodeFailure(&pktBuf, 0) pktMsg, err := DecodeFailure(&pktBuf, 0)
require.NoError(t, err, "failed to decode failure packet") require.NoError(t, err, "failed to decode failure packet")
require.True( assertEqual(t, msg, pktMsg)
t, eq(msg, pktMsg),
"original message and decoded packet message are not equal: "+
"%v != %v",
msg, pktMsg,
)
} }
func onionFailureHarness(t *testing.T, data []byte, code FailCode) { func onionFailureHarness(t *testing.T, data []byte, code FailCode) {
t.Helper() t.Helper()
onionFailureHarnessCustom(t, data, code, reflect.DeepEqual) assertEq := func(t *testing.T, x, y any) {
require.Equal(t, x, y)
}
onionFailureHarnessCustom(t, data, code, assertEq)
} }
func FuzzFailIncorrectDetails(f *testing.F) { func FuzzFailIncorrectDetails(f *testing.F) {
@ -929,7 +634,7 @@ func FuzzFailIncorrectDetails(f *testing.F) {
// Since FailIncorrectDetails.Decode can leave extraOpaqueData // Since FailIncorrectDetails.Decode can leave extraOpaqueData
// as nil while FailIncorrectDetails.Encode writes an empty // as nil while FailIncorrectDetails.Encode writes an empty
// slice, we need to use a custom equality function. // slice, we need to use a custom equality function.
eq := func(x, y any) bool { assertEq := func(t *testing.T, x, y any) {
msg1, ok := x.(*FailIncorrectDetails) msg1, ok := x.(*FailIncorrectDetails)
require.True( require.True(
t, ok, "msg1 was not FailIncorrectDetails", t, ok, "msg1 was not FailIncorrectDetails",
@ -940,16 +645,18 @@ func FuzzFailIncorrectDetails(f *testing.F) {
t, ok, "msg2 was not FailIncorrectDetails", t, ok, "msg2 was not FailIncorrectDetails",
) )
return msg1.amount == msg2.amount && require.Equal(t, msg1.amount, msg2.amount)
msg1.height == msg2.height && require.Equal(t, msg1.height, msg2.height)
bytes.Equal( require.True(
t, bytes.Equal(
msg1.extraOpaqueData, msg1.extraOpaqueData,
msg2.extraOpaqueData, msg2.extraOpaqueData,
) ),
)
} }
onionFailureHarnessCustom( onionFailureHarnessCustom(
t, data, CodeIncorrectOrUnknownPaymentDetails, eq, t, data, CodeIncorrectOrUnknownPaymentDetails, assertEq,
) )
}) })
} }
@ -1034,23 +741,13 @@ func FuzzFailInvalidBlinding(f *testing.F) {
func FuzzClosingSig(f *testing.F) { func FuzzClosingSig(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with ClosingSig. wireMsgHarness(t, data, MsgClosingSig)
data = prefixWithMsgType(data, MsgClosingSig)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }
func FuzzClosingComplete(f *testing.F) { func FuzzClosingComplete(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) { f.Fuzz(func(t *testing.T, data []byte) {
// Prefix with ClosingComplete. wireMsgHarness(t, data, MsgClosingComplete)
data = prefixWithMsgType(data, MsgClosingComplete)
// Pass the message into our general fuzz harness for wire
// messages!
harness(t, data)
}) })
} }