2022-07-29 17:42:42 -04:00
|
|
|
package lnwire
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"compress/zlib"
|
|
|
|
"encoding/binary"
|
|
|
|
"testing"
|
2023-05-19 11:59:45 -05:00
|
|
|
|
|
|
|
"github.com/stretchr/testify/require"
|
2022-07-29 17:42:42 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
// prefixWithMsgType takes []byte and adds a wire protocol prefix
|
|
|
|
// to make the []byte into an actual message to be used in fuzzing.
|
|
|
|
func prefixWithMsgType(data []byte, prefix MessageType) []byte {
|
|
|
|
var prefixBytes [2]byte
|
|
|
|
binary.BigEndian.PutUint16(prefixBytes[:], uint16(prefix))
|
|
|
|
data = append(prefixBytes[:], data...)
|
2022-11-07 16:38:16 -06:00
|
|
|
|
2022-07-29 17:42:42 -04:00
|
|
|
return data
|
|
|
|
}
|
|
|
|
|
2024-11-12 16:03:25 -06:00
|
|
|
// assertEqualFunc is a function used to assert that two deserialized messages
|
|
|
|
// are equivalent.
|
|
|
|
type assertEqualFunc func(t *testing.T, x, y any)
|
|
|
|
|
|
|
|
// wireMsgHarnessCustom performs the actual fuzz testing of the appropriate wire
|
2024-11-12 14:55:43 -06:00
|
|
|
// 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
|
2022-07-29 17:42:42 -04:00
|
|
|
// serialization and deserialization checks.
|
2024-11-12 16:03:25 -06:00
|
|
|
func wireMsgHarnessCustom(t *testing.T, data []byte, msgType MessageType,
|
|
|
|
assertEqual assertEqualFunc) {
|
2022-11-07 16:38:16 -06:00
|
|
|
|
2024-11-12 15:14:51 -06:00
|
|
|
data = prefixWithMsgType(data, msgType)
|
|
|
|
|
2022-07-29 17:42:42 -04:00
|
|
|
// Create a reader with the byte array.
|
|
|
|
r := bytes.NewReader(data)
|
|
|
|
|
|
|
|
// Check that the created message is not greater than the maximum
|
|
|
|
// message size.
|
|
|
|
if len(data) > MaxSliceLength {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
msg, err := ReadMessage(r, 0)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// We will serialize the message into a new bytes buffer.
|
|
|
|
var b bytes.Buffer
|
2023-05-19 11:59:45 -05:00
|
|
|
_, err = WriteMessage(&b, msg, 0)
|
|
|
|
require.NoError(t, err)
|
2022-07-29 17:42:42 -04:00
|
|
|
|
|
|
|
// 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)
|
2023-05-19 11:59:45 -05:00
|
|
|
require.NoError(t, err)
|
2024-11-12 16:03:25 -06:00
|
|
|
|
|
|
|
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)
|
2022-07-29 17:42:42 -04:00
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzAcceptChannel(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 16:03:25 -06:00
|
|
|
// We can't use require.Equal for UpfrontShutdownScript, since
|
|
|
|
// we consider the empty slice and nil to be equivalent.
|
|
|
|
assertEq := func(t *testing.T, x, y any) {
|
|
|
|
require.IsType(t, &AcceptChannel{}, x)
|
|
|
|
first, _ := x.(*AcceptChannel)
|
|
|
|
require.IsType(t, &AcceptChannel{}, y)
|
|
|
|
second, _ := y.(*AcceptChannel)
|
|
|
|
|
|
|
|
require.True(
|
|
|
|
t, bytes.Equal(
|
|
|
|
first.UpfrontShutdownScript,
|
|
|
|
second.UpfrontShutdownScript,
|
|
|
|
),
|
|
|
|
)
|
|
|
|
first.UpfrontShutdownScript = nil
|
|
|
|
second.UpfrontShutdownScript = nil
|
2022-07-29 17:42:42 -04:00
|
|
|
|
2024-11-12 16:03:25 -06:00
|
|
|
require.Equal(t, first, second)
|
2022-07-29 17:42:42 -04:00
|
|
|
}
|
|
|
|
|
2024-11-12 16:03:25 -06:00
|
|
|
wireMsgHarnessCustom(t, data, MsgAcceptChannel, assertEq)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzAnnounceSignatures(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgAnnounceSignatures)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-11-08 14:57:13 -06:00
|
|
|
func FuzzAnnounceSignatures2(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgAnnounceSignatures2)
|
2024-11-08 14:57:13 -06:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzChannelAnnouncement(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgChannelAnnouncement)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-11-08 14:57:13 -06:00
|
|
|
func FuzzChannelAnnouncement2(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
|
|
// We can't use require.Equal for Features, since we consider
|
|
|
|
// the empty map and nil to be equivalent.
|
2024-11-12 16:03:25 -06:00
|
|
|
assertEq := func(t *testing.T, x, y any) {
|
|
|
|
require.IsType(t, &ChannelAnnouncement2{}, x)
|
|
|
|
first, _ := x.(*ChannelAnnouncement2)
|
|
|
|
require.IsType(t, &ChannelAnnouncement2{}, y)
|
|
|
|
second, _ := y.(*ChannelAnnouncement2)
|
|
|
|
|
|
|
|
require.True(
|
|
|
|
t,
|
|
|
|
first.Features.Val.Equals(&second.Features.Val),
|
|
|
|
)
|
|
|
|
first.Features.Val = *NewRawFeatureVector()
|
|
|
|
second.Features.Val = *NewRawFeatureVector()
|
2024-11-08 14:57:13 -06:00
|
|
|
|
2024-11-12 16:03:25 -06:00
|
|
|
require.Equal(t, first, second)
|
|
|
|
}
|
|
|
|
|
|
|
|
wireMsgHarnessCustom(t, data, MsgChannelAnnouncement2, assertEq)
|
2024-11-08 14:57:13 -06:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzChannelReestablish(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgChannelReestablish)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzChannelUpdate(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgChannelUpdate)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-11-08 14:57:13 -06:00
|
|
|
func FuzzChannelUpdate2(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgChannelUpdate2)
|
2024-11-08 14:57:13 -06:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzClosingSigned(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgClosingSigned)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzCommitSig(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgCommitSig)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzError(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgError)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-11 11:45:30 -06:00
|
|
|
func FuzzWarning(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgWarning)
|
2022-11-11 11:45:30 -06:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-12-06 16:44:59 -08:00
|
|
|
func FuzzStfu(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgStfu)
|
2023-12-06 16:44:59 -08:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzFundingCreated(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgFundingCreated)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-03-16 05:04:26 +08:00
|
|
|
func FuzzChannelReady(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgChannelReady)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzFundingSigned(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgFundingSigned)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzGossipTimestampRange(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgGossipTimestampRange)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzInit(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgInit)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzNodeAnnouncement(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2023-05-19 11:59:45 -05:00
|
|
|
// We can't use require.Equal for Addresses, since the same IP
|
|
|
|
// can be represented by different underlying bytes. Instead, we
|
|
|
|
// compare the normalized string representation of each address.
|
2024-11-12 16:03:25 -06:00
|
|
|
assertEq := func(t *testing.T, x, y any) {
|
|
|
|
require.IsType(t, &NodeAnnouncement{}, x)
|
|
|
|
first, _ := x.(*NodeAnnouncement)
|
|
|
|
require.IsType(t, &NodeAnnouncement{}, y)
|
|
|
|
second, _ := y.(*NodeAnnouncement)
|
|
|
|
|
2023-05-19 11:59:45 -05:00
|
|
|
require.Equal(
|
2024-11-12 16:03:25 -06:00
|
|
|
t, len(first.Addresses), len(second.Addresses),
|
2023-05-19 11:59:45 -05:00
|
|
|
)
|
2024-11-12 16:03:25 -06:00
|
|
|
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)
|
2022-07-29 17:42:42 -04:00
|
|
|
}
|
|
|
|
|
2024-11-12 16:03:25 -06:00
|
|
|
wireMsgHarnessCustom(t, data, MsgNodeAnnouncement, assertEq)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzOpenChannel(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 16:03:25 -06:00
|
|
|
// We can't use require.Equal for UpfrontShutdownScript, since
|
|
|
|
// we consider the empty slice and nil to be equivalent.
|
|
|
|
assertEq := func(t *testing.T, x, y any) {
|
|
|
|
require.IsType(t, &OpenChannel{}, x)
|
|
|
|
first, _ := x.(*OpenChannel)
|
|
|
|
require.IsType(t, &OpenChannel{}, y)
|
|
|
|
second, _ := y.(*OpenChannel)
|
|
|
|
|
|
|
|
require.True(
|
|
|
|
t, bytes.Equal(
|
|
|
|
first.UpfrontShutdownScript,
|
|
|
|
second.UpfrontShutdownScript,
|
|
|
|
),
|
|
|
|
)
|
|
|
|
first.UpfrontShutdownScript = nil
|
|
|
|
second.UpfrontShutdownScript = nil
|
2022-07-29 17:42:42 -04:00
|
|
|
|
2024-11-12 16:03:25 -06:00
|
|
|
require.Equal(t, first, second)
|
2022-07-29 17:42:42 -04:00
|
|
|
}
|
|
|
|
|
2024-11-12 16:03:25 -06:00
|
|
|
wireMsgHarnessCustom(t, data, MsgOpenChannel, assertEq)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzPing(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgPing)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzPong(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgPong)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzQueryChannelRange(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgQueryChannelRange)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzZlibQueryShortChanIDs(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
zlibWriter := zlib.NewWriter(&buf)
|
|
|
|
_, err := zlibWriter.Write(data)
|
2023-05-19 11:59:45 -05:00
|
|
|
require.NoError(t, err) // Zlib bug?
|
2022-07-29 17:42:42 -04:00
|
|
|
|
2023-05-19 11:59:45 -05:00
|
|
|
err = zlibWriter.Close()
|
|
|
|
require.NoError(t, err) // Zlib bug?
|
2022-07-29 17:42:42 -04:00
|
|
|
|
|
|
|
compressedPayload := buf.Bytes()
|
|
|
|
|
|
|
|
chainhash := []byte("00000000000000000000000000000000")
|
|
|
|
numBytesInBody := len(compressedPayload) + 1
|
|
|
|
zlibByte := []byte("\x01")
|
|
|
|
|
|
|
|
bodyBytes := make([]byte, 2)
|
|
|
|
binary.BigEndian.PutUint16(bodyBytes, uint16(numBytesInBody))
|
|
|
|
|
|
|
|
payload := chainhash
|
|
|
|
payload = append(payload, bodyBytes...)
|
|
|
|
payload = append(payload, zlibByte...)
|
|
|
|
payload = append(payload, compressedPayload...)
|
|
|
|
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, payload, MsgQueryShortChanIDs)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzQueryShortChanIDs(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgQueryShortChanIDs)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzZlibReplyChannelRange(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
zlibWriter := zlib.NewWriter(&buf)
|
|
|
|
_, err := zlibWriter.Write(data)
|
2023-05-19 11:59:45 -05:00
|
|
|
require.NoError(t, err) // Zlib bug?
|
2022-07-29 17:42:42 -04:00
|
|
|
|
2023-05-19 11:59:45 -05:00
|
|
|
err = zlibWriter.Close()
|
|
|
|
require.NoError(t, err) // Zlib bug?
|
2022-07-29 17:42:42 -04:00
|
|
|
|
|
|
|
compressedPayload := buf.Bytes()
|
|
|
|
|
|
|
|
// Initialize some []byte vars which will prefix our payload
|
|
|
|
chainhash := []byte("00000000000000000000000000000000")
|
|
|
|
firstBlockHeight := []byte("\x00\x00\x00\x00")
|
|
|
|
numBlocks := []byte("\x00\x00\x00\x00")
|
|
|
|
completeByte := []byte("\x00")
|
|
|
|
|
|
|
|
numBytesInBody := len(compressedPayload) + 1
|
|
|
|
zlibByte := []byte("\x01")
|
|
|
|
|
|
|
|
bodyBytes := make([]byte, 2)
|
|
|
|
binary.BigEndian.PutUint16(bodyBytes, uint16(numBytesInBody))
|
|
|
|
|
|
|
|
payload := chainhash
|
|
|
|
payload = append(payload, firstBlockHeight...)
|
|
|
|
payload = append(payload, numBlocks...)
|
|
|
|
payload = append(payload, completeByte...)
|
|
|
|
payload = append(payload, bodyBytes...)
|
|
|
|
payload = append(payload, zlibByte...)
|
|
|
|
payload = append(payload, compressedPayload...)
|
|
|
|
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, payload, MsgReplyChannelRange)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzReplyChannelRange(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-09-10 11:41:31 -05:00
|
|
|
// We can't use require.Equal for Timestamps, since we consider
|
|
|
|
// the empty slice and nil to be equivalent.
|
2024-11-12 16:03:25 -06:00
|
|
|
assertEq := func(t *testing.T, x, y any) {
|
|
|
|
require.IsType(t, &ReplyChannelRange{}, x)
|
|
|
|
first, _ := x.(*ReplyChannelRange)
|
|
|
|
require.IsType(t, &ReplyChannelRange{}, y)
|
|
|
|
second, _ := y.(*ReplyChannelRange)
|
|
|
|
|
|
|
|
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)
|
2024-09-10 11:41:31 -05:00
|
|
|
}
|
|
|
|
|
2024-11-12 16:03:25 -06:00
|
|
|
wireMsgHarnessCustom(t, data, MsgReplyChannelRange, assertEq)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzReplyShortChanIDsEnd(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgReplyShortChanIDsEnd)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzRevokeAndAck(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgRevokeAndAck)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzShutdown(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgShutdown)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzUpdateAddHTLC(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgUpdateAddHTLC)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzUpdateFailHTLC(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgUpdateFailHTLC)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzUpdateFailMalformedHTLC(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgUpdateFailMalformedHTLC)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzUpdateFee(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgUpdateFee)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-11-07 14:58:46 -06:00
|
|
|
func FuzzUpdateFulfillHTLC(f *testing.F) {
|
2022-07-29 17:42:42 -04:00
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgUpdateFulfillHTLC)
|
2022-07-29 17:42:42 -04:00
|
|
|
})
|
|
|
|
}
|
2023-01-08 00:07:35 +01:00
|
|
|
|
2023-10-14 12:00:30 -06:00
|
|
|
func FuzzDynPropose(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgDynPropose)
|
2023-10-14 12:00:30 -06:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func FuzzDynReject(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgDynReject)
|
2023-10-14 12:00:30 -06:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func FuzzDynAck(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgDynAck)
|
2023-10-14 12:00:30 -06:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-10-18 20:28:51 -07:00
|
|
|
func FuzzKickoffSig(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgKickoffSig)
|
2023-10-18 20:28:51 -07:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-01-08 00:07:35 +01:00
|
|
|
func FuzzCustomMessage(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte, customMessageType uint16) {
|
|
|
|
if customMessageType < uint16(CustomTypeStart) {
|
|
|
|
customMessageType += uint16(CustomTypeStart)
|
|
|
|
}
|
|
|
|
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MessageType(customMessageType))
|
2023-01-08 00:07:35 +01:00
|
|
|
})
|
|
|
|
}
|
2023-04-27 15:25:13 -05:00
|
|
|
|
|
|
|
// FuzzParseRawSignature tests that our DER-encoded signature parsing does not
|
|
|
|
// panic for arbitrary inputs and that serializing and reparsing the signatures
|
|
|
|
// does not mutate them.
|
|
|
|
func FuzzParseRawSignature(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2023-01-16 19:33:21 -08:00
|
|
|
sig, err := NewSigFromECDSARawSignature(data)
|
2023-04-27 15:25:13 -05:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-01-16 19:33:21 -08:00
|
|
|
sig2, err := NewSigFromECDSARawSignature(sig.ToSignatureBytes())
|
2023-05-19 11:59:45 -05:00
|
|
|
require.NoError(t, err, "failed to reparse signature")
|
2023-04-27 15:25:13 -05:00
|
|
|
|
2023-05-19 11:59:45 -05:00
|
|
|
require.Equal(t, sig, sig2, "signature mismatch")
|
2023-04-27 15:25:13 -05:00
|
|
|
})
|
|
|
|
}
|
2023-04-28 10:20:08 -05:00
|
|
|
|
|
|
|
// FuzzConvertFixedSignature tests that conversion of fixed 64-byte signatures
|
|
|
|
// to DER-encoded signatures does not panic and that parsing and reconverting
|
|
|
|
// the signatures does not mutate them.
|
|
|
|
func FuzzConvertFixedSignature(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
|
|
var sig Sig
|
2023-01-16 19:33:21 -08:00
|
|
|
if len(data) > len(sig.bytes[:]) {
|
2023-04-28 10:20:08 -05:00
|
|
|
return
|
|
|
|
}
|
2023-01-16 19:33:21 -08:00
|
|
|
copy(sig.bytes[:], data)
|
2023-04-28 10:20:08 -05:00
|
|
|
|
|
|
|
derSig, err := sig.ToSignature()
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
sig2, err := NewSigFromSignature(derSig)
|
2023-05-19 11:59:45 -05:00
|
|
|
require.NoError(t, err, "failed to parse signature")
|
2023-04-28 10:20:08 -05:00
|
|
|
|
|
|
|
derSig2, err := sig2.ToSignature()
|
2023-05-19 11:59:45 -05:00
|
|
|
require.NoError(t, err, "failed to reconvert signature to DER")
|
2023-04-28 10:20:08 -05:00
|
|
|
|
|
|
|
derBytes := derSig.Serialize()
|
|
|
|
derBytes2 := derSig2.Serialize()
|
2023-05-19 11:59:45 -05:00
|
|
|
require.Equal(t, derBytes, derBytes2, "signature mismatch")
|
2023-04-28 10:20:08 -05:00
|
|
|
})
|
|
|
|
}
|
2023-05-02 17:04:48 -05:00
|
|
|
|
2024-11-08 15:01:48 -06:00
|
|
|
// FuzzConvertFixedSchnorrSignature tests that conversion of fixed 64-byte
|
|
|
|
// Schnorr signatures to and from the btcec format does not panic or mutate the
|
|
|
|
// signatures.
|
|
|
|
func FuzzConvertFixedSchnorrSignature(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
|
|
var sig Sig
|
|
|
|
if len(data) > len(sig.bytes[:]) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
copy(sig.bytes[:], data)
|
|
|
|
sig.ForceSchnorr()
|
|
|
|
|
|
|
|
btcecSig, err := sig.ToSignature()
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
sig2, err := NewSigFromSignature(btcecSig)
|
|
|
|
require.NoError(t, err, "failed to parse signature")
|
|
|
|
|
|
|
|
btcecSig2, err := sig2.ToSignature()
|
|
|
|
require.NoError(
|
|
|
|
t, err, "failed to reconvert signature to btcec format",
|
|
|
|
)
|
|
|
|
|
|
|
|
btcecBytes := btcecSig.Serialize()
|
|
|
|
btcecBytes2 := btcecSig2.Serialize()
|
|
|
|
require.Equal(t, btcecBytes, btcecBytes2, "signature mismatch")
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-05-02 17:04:48 -05:00
|
|
|
// prefixWithFailCode adds a failure code prefix to data.
|
|
|
|
func prefixWithFailCode(data []byte, code FailCode) []byte {
|
|
|
|
var codeBytes [2]byte
|
|
|
|
binary.BigEndian.PutUint16(codeBytes[:], uint16(code))
|
|
|
|
data = append(codeBytes[:], data...)
|
|
|
|
|
|
|
|
return data
|
|
|
|
}
|
|
|
|
|
2023-05-02 18:07:49 -05:00
|
|
|
// onionFailureHarnessCustom performs the actual fuzz testing of the appropriate
|
|
|
|
// 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
|
2023-05-02 17:04:48 -05:00
|
|
|
// sequence of serialization and deserialization checks.
|
2023-05-02 18:07:49 -05:00
|
|
|
func onionFailureHarnessCustom(t *testing.T, data []byte, code FailCode,
|
2024-11-12 16:11:17 -06:00
|
|
|
assertEqual assertEqualFunc) {
|
2023-05-02 18:07:49 -05:00
|
|
|
|
2023-05-02 17:04:48 -05:00
|
|
|
data = prefixWithFailCode(data, code)
|
|
|
|
|
|
|
|
// Don't waste time fuzzing messages larger than we'll ever accept.
|
|
|
|
if len(data) > MaxSliceLength {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// First check whether the failure message can be decoded.
|
|
|
|
r := bytes.NewReader(data)
|
|
|
|
msg, err := DecodeFailureMessage(r, 0)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// We now have a valid decoded message. Verify that encoding and
|
|
|
|
// decoding the message does not mutate it.
|
|
|
|
|
|
|
|
var b bytes.Buffer
|
2023-10-27 14:30:56 -05:00
|
|
|
err = EncodeFailureMessage(&b, msg, 0)
|
|
|
|
require.NoError(t, err, "failed to encode failure message")
|
2023-05-02 17:04:48 -05:00
|
|
|
|
|
|
|
newMsg, err := DecodeFailureMessage(&b, 0)
|
2023-10-27 14:30:56 -05:00
|
|
|
require.NoError(t, err, "failed to decode serialized failure message")
|
2023-05-02 17:04:48 -05:00
|
|
|
|
2024-11-12 16:11:17 -06:00
|
|
|
assertEqual(t, msg, newMsg)
|
2023-05-02 17:04:48 -05:00
|
|
|
|
|
|
|
// Now verify that encoding/decoding full packets works as expected.
|
|
|
|
|
|
|
|
var pktBuf bytes.Buffer
|
|
|
|
if err := EncodeFailure(&pktBuf, msg, 0); err != nil {
|
|
|
|
// EncodeFailure returns an error if the encoded message would
|
|
|
|
// exceed FailureMessageLength bytes, as LND always encodes
|
|
|
|
// fixed-size packets for privacy. But it is valid to decode
|
|
|
|
// messages longer than this, so we should not report an error
|
|
|
|
// if the original message was longer.
|
|
|
|
//
|
|
|
|
// We add 2 to the length of the original message since it may
|
|
|
|
// have omitted a channel_update type prefix of 2 bytes. When
|
|
|
|
// we re-encode such a message, we will add the 2-byte prefix
|
|
|
|
// as prescribed by the spec.
|
|
|
|
if len(data)+2 > FailureMessageLength {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Fatalf("failed to encode failure packet: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// We should use FailureMessageLength sized packets plus 2 bytes to
|
|
|
|
// encode the message length and 2 bytes to encode the padding length,
|
|
|
|
// as recommended by the spec.
|
2023-10-27 14:30:56 -05:00
|
|
|
require.Equal(
|
|
|
|
t, pktBuf.Len(), FailureMessageLength+4,
|
|
|
|
"wrong failure message length",
|
|
|
|
)
|
2023-05-02 17:04:48 -05:00
|
|
|
|
|
|
|
pktMsg, err := DecodeFailure(&pktBuf, 0)
|
2023-10-27 14:30:56 -05:00
|
|
|
require.NoError(t, err, "failed to decode failure packet")
|
2023-05-02 17:04:48 -05:00
|
|
|
|
2024-11-12 16:11:17 -06:00
|
|
|
assertEqual(t, msg, pktMsg)
|
2023-05-02 17:04:48 -05:00
|
|
|
}
|
|
|
|
|
2023-05-02 18:07:49 -05:00
|
|
|
func onionFailureHarness(t *testing.T, data []byte, code FailCode) {
|
|
|
|
t.Helper()
|
2024-11-12 16:11:17 -06:00
|
|
|
assertEq := func(t *testing.T, x, y any) {
|
|
|
|
require.Equal(t, x, y)
|
|
|
|
}
|
|
|
|
onionFailureHarnessCustom(t, data, code, assertEq)
|
2023-05-02 18:07:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func FuzzFailIncorrectDetails(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
|
|
// Since FailIncorrectDetails.Decode can leave extraOpaqueData
|
|
|
|
// as nil while FailIncorrectDetails.Encode writes an empty
|
|
|
|
// slice, we need to use a custom equality function.
|
2024-11-12 16:11:17 -06:00
|
|
|
assertEq := func(t *testing.T, x, y any) {
|
2023-05-02 18:07:49 -05:00
|
|
|
msg1, ok := x.(*FailIncorrectDetails)
|
2023-10-27 14:30:56 -05:00
|
|
|
require.True(
|
|
|
|
t, ok, "msg1 was not FailIncorrectDetails",
|
|
|
|
)
|
2023-05-02 18:07:49 -05:00
|
|
|
|
|
|
|
msg2, ok := y.(*FailIncorrectDetails)
|
2023-10-27 14:30:56 -05:00
|
|
|
require.True(
|
|
|
|
t, ok, "msg2 was not FailIncorrectDetails",
|
|
|
|
)
|
2023-05-02 18:07:49 -05:00
|
|
|
|
2024-11-12 16:11:17 -06:00
|
|
|
require.Equal(t, msg1.amount, msg2.amount)
|
|
|
|
require.Equal(t, msg1.height, msg2.height)
|
|
|
|
require.True(
|
|
|
|
t, bytes.Equal(
|
2023-05-02 18:07:49 -05:00
|
|
|
msg1.extraOpaqueData,
|
|
|
|
msg2.extraOpaqueData,
|
2024-11-12 16:11:17 -06:00
|
|
|
),
|
|
|
|
)
|
2023-05-02 18:07:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
onionFailureHarnessCustom(
|
2024-11-12 16:11:17 -06:00
|
|
|
t, data, CodeIncorrectOrUnknownPaymentDetails, assertEq,
|
2023-05-02 18:07:49 -05:00
|
|
|
)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-05-02 17:04:48 -05:00
|
|
|
func FuzzFailInvalidOnionVersion(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
|
|
onionFailureHarness(t, data, CodeInvalidOnionVersion)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func FuzzFailInvalidOnionHmac(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
|
|
onionFailureHarness(t, data, CodeInvalidOnionHmac)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func FuzzFailInvalidOnionKey(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
|
|
onionFailureHarness(t, data, CodeInvalidOnionKey)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func FuzzFailTemporaryChannelFailure(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
|
|
onionFailureHarness(t, data, CodeTemporaryChannelFailure)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func FuzzFailAmountBelowMinimum(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
|
|
onionFailureHarness(t, data, CodeAmountBelowMinimum)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func FuzzFailFeeInsufficient(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
|
|
onionFailureHarness(t, data, CodeFeeInsufficient)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func FuzzFailIncorrectCltvExpiry(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
|
|
onionFailureHarness(t, data, CodeIncorrectCltvExpiry)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func FuzzFailExpiryTooSoon(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
|
|
onionFailureHarness(t, data, CodeExpiryTooSoon)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func FuzzFailChannelDisabled(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
|
|
onionFailureHarness(t, data, CodeChannelDisabled)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func FuzzFailFinalIncorrectCltvExpiry(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
|
|
onionFailureHarness(t, data, CodeFinalIncorrectCltvExpiry)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func FuzzFailFinalIncorrectHtlcAmount(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
|
|
onionFailureHarness(t, data, CodeFinalIncorrectHtlcAmount)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func FuzzInvalidOnionPayload(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
|
|
onionFailureHarness(t, data, CodeInvalidOnionPayload)
|
|
|
|
})
|
|
|
|
}
|
2024-02-02 17:21:55 -08:00
|
|
|
|
2024-11-08 15:00:06 -06:00
|
|
|
func FuzzFailInvalidBlinding(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
|
|
onionFailureHarness(t, data, CodeInvalidBlinding)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-02-02 17:21:55 -08:00
|
|
|
func FuzzClosingSig(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgClosingSig)
|
2024-02-02 17:21:55 -08:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func FuzzClosingComplete(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
2024-11-12 15:14:51 -06:00
|
|
|
wireMsgHarness(t, data, MsgClosingComplete)
|
2024-02-02 17:21:55 -08:00
|
|
|
})
|
|
|
|
}
|
2024-11-08 15:03:30 -06:00
|
|
|
|
|
|
|
// FuzzFee tests that decoding and re-encoding a Fee TLV does not mutate it.
|
|
|
|
func FuzzFee(f *testing.F) {
|
|
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
|
|
if len(data) > 8 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
var fee Fee
|
|
|
|
var buf [8]byte
|
|
|
|
r := bytes.NewReader(data)
|
|
|
|
|
|
|
|
if err := feeDecoder(r, &fee, &buf, 8); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
var b bytes.Buffer
|
|
|
|
require.NoError(t, feeEncoder(&b, &fee, &buf))
|
|
|
|
|
|
|
|
// Use bytes.Equal instead of require.Equal so that nil and
|
|
|
|
// empty slices are considered equal.
|
|
|
|
require.True(
|
|
|
|
t, bytes.Equal(data, b.Bytes()), "%v != %v", data,
|
|
|
|
b.Bytes(),
|
|
|
|
)
|
|
|
|
})
|
|
|
|
}
|