mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-03-24 16:51:54 +01:00
With what we added in the prior commit, we can significantly shrink the size of this test. We also make it easier to extend in the future, as this will fail if a new message is added, that doesn't have the needed methods, as long as MsgEnd is updated.
256 lines
6.4 KiB
Go
256 lines
6.4 KiB
Go
package lnwire
|
|
|
|
import (
|
|
"bytes"
|
|
crand "crypto/rand"
|
|
"encoding/hex"
|
|
"math"
|
|
"math/rand"
|
|
"net"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/btcsuite/btcd/btcec/v2"
|
|
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
|
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
|
"github.com/btcsuite/btcd/wire"
|
|
"github.com/lightningnetwork/lnd/tor"
|
|
"github.com/stretchr/testify/require"
|
|
"pgregory.net/rapid"
|
|
)
|
|
|
|
var (
|
|
shaHash1Bytes, _ = hex.DecodeString("e3b0c44298fc1c149afbf4c8996fb" +
|
|
"92427ae41e4649b934ca495991b7852b855")
|
|
|
|
shaHash1, _ = chainhash.NewHash(shaHash1Bytes)
|
|
outpoint1 = wire.NewOutPoint(shaHash1, 0)
|
|
|
|
testRBytes, _ = hex.DecodeString("8ce2bc69281ce27da07e6683571" +
|
|
"319d18e949ddfa2965fb6caa1bf0314f882d7")
|
|
testSBytes, _ = hex.DecodeString("299105481d63e0f4bc2a" +
|
|
"88121167221b6700d72a0ead154c03be696a292d24ae")
|
|
testRScalar = new(btcec.ModNScalar)
|
|
testSScalar = new(btcec.ModNScalar)
|
|
_ = testRScalar.SetByteSlice(testRBytes)
|
|
_ = testSScalar.SetByteSlice(testSBytes)
|
|
testSig = ecdsa.NewSignature(testRScalar, testSScalar)
|
|
testSchnorrSigStr, _ = hex.DecodeString("04E7F9037658A92AFEB4F2" +
|
|
"5BAE5339E3DDCA81A353493827D26F16D92308E49E2A25E9220867" +
|
|
"8A2DF86970DA91B03A8AF8815A8A60498B358DAF560B347AA557")
|
|
testSchnorrSig, _ = NewSigFromSchnorrRawSignature(testSchnorrSigStr)
|
|
)
|
|
|
|
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
|
|
// generateRandomBytes returns a slice of n random bytes.
|
|
func generateRandomBytes(n int) ([]byte, error) {
|
|
b := make([]byte, n)
|
|
_, err := crand.Read(b)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return b, nil
|
|
}
|
|
|
|
func randRawKey(t *testing.T) [33]byte {
|
|
var n [33]byte
|
|
|
|
priv, err := btcec.NewPrivateKey()
|
|
require.NoError(t, err)
|
|
|
|
copy(n[:], priv.PubKey().SerializeCompressed())
|
|
|
|
return n
|
|
}
|
|
|
|
func randPubKey() (*btcec.PublicKey, error) {
|
|
priv, err := btcec.NewPrivateKey()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return priv.PubKey(), nil
|
|
}
|
|
|
|
// pubkeyFromHex parses a Bitcoin public key from a hex encoded string.
|
|
func pubkeyFromHex(keyHex string) (*btcec.PublicKey, error) {
|
|
pubKeyBytes, err := hex.DecodeString(keyHex)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return btcec.ParsePubKey(pubKeyBytes)
|
|
}
|
|
|
|
// TestChanUpdateChanFlags ensures that converting the ChanUpdateChanFlags and
|
|
// ChanUpdateMsgFlags bitfields to a string behaves as expected.
|
|
func TestChanUpdateChanFlags(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testCases := []struct {
|
|
flags uint8
|
|
expected string
|
|
}{
|
|
{
|
|
flags: 0,
|
|
expected: "00000000",
|
|
},
|
|
{
|
|
flags: 1,
|
|
expected: "00000001",
|
|
},
|
|
{
|
|
flags: 3,
|
|
expected: "00000011",
|
|
},
|
|
{
|
|
flags: 255,
|
|
expected: "11111111",
|
|
},
|
|
}
|
|
|
|
for _, test := range testCases {
|
|
chanFlag := ChanUpdateChanFlags(test.flags)
|
|
toStr := chanFlag.String()
|
|
if toStr != test.expected {
|
|
t.Fatalf("expected %v, got %v",
|
|
test.expected, toStr)
|
|
}
|
|
|
|
msgFlag := ChanUpdateMsgFlags(test.flags)
|
|
toStr = msgFlag.String()
|
|
if toStr != test.expected {
|
|
t.Fatalf("expected %v, got %v",
|
|
test.expected, toStr)
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestDecodeUnknownAddressType shows that an unknown address type is correctly
|
|
// decoded and encoded.
|
|
func TestDecodeUnknownAddressType(t *testing.T) {
|
|
// Add a normal, clearnet address.
|
|
tcpAddr := &net.TCPAddr{
|
|
IP: net.IP{127, 0, 0, 1},
|
|
Port: 8080,
|
|
}
|
|
|
|
// Add an onion address.
|
|
onionAddr := &tor.OnionAddr{
|
|
OnionService: "abcdefghijklmnop.onion",
|
|
Port: 9065,
|
|
}
|
|
|
|
// Now add an address with an unknown type.
|
|
var newAddrType addressType = math.MaxUint8
|
|
data := make([]byte, 0, 16)
|
|
data = append(data, uint8(newAddrType))
|
|
opaqueAddrs := &OpaqueAddrs{
|
|
Payload: data,
|
|
}
|
|
|
|
buffer := bytes.NewBuffer(make([]byte, 0, MaxMsgBody))
|
|
err := WriteNetAddrs(
|
|
buffer, []net.Addr{tcpAddr, onionAddr, opaqueAddrs},
|
|
)
|
|
require.NoError(t, err)
|
|
|
|
// Now we attempt to parse the bytes and assert that we get an error.
|
|
var addrs []net.Addr
|
|
err = ReadElement(buffer, &addrs)
|
|
require.NoError(t, err)
|
|
require.Len(t, addrs, 3)
|
|
require.Equal(t, tcpAddr.String(), addrs[0].String())
|
|
require.Equal(t, onionAddr.String(), addrs[1].String())
|
|
require.Equal(t, hex.EncodeToString(data), addrs[2].String())
|
|
}
|
|
|
|
func TestMaxOutPointIndex(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
op := wire.OutPoint{
|
|
Index: math.MaxUint32,
|
|
}
|
|
|
|
var b bytes.Buffer
|
|
if err := WriteOutPoint(&b, op); err == nil {
|
|
t.Fatalf("write of outPoint should fail, index exceeds 16-bits")
|
|
}
|
|
}
|
|
|
|
func TestEmptyMessageUnknownType(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
fakeType := CustomTypeStart - 1
|
|
if _, err := makeEmptyMessage(fakeType); err == nil {
|
|
t.Fatalf("should not be able to make an empty message of an " +
|
|
"unknown type")
|
|
}
|
|
}
|
|
|
|
// TestLightningWireProtocol uses the rapid property-based testing framework to
|
|
// verify that all message types can be serialized and deserialized correctly.
|
|
func TestLightningWireProtocol(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
for msgType := MessageType(0); msgType < MsgEnd; msgType++ {
|
|
// If MakeEmptyMessage returns an error, then this isn't yet a
|
|
// used message type.
|
|
if _, err := MakeEmptyMessage(msgType); err != nil {
|
|
continue
|
|
}
|
|
|
|
t.Run(msgType.String(), rapid.MakeCheck(func(t *rapid.T) {
|
|
// Create an empty message of the given type.
|
|
m, err := MakeEmptyMessage(msgType)
|
|
|
|
// An error means this isn't a valid message type, so we
|
|
// skip it.
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// The message must support the message type interface.
|
|
testMsg, ok := m.(TestMessage)
|
|
require.True(
|
|
t, ok, "message %v doesn't support TestMessage",
|
|
msgType,
|
|
)
|
|
|
|
// Use the RandTestMessage method to create a randomized
|
|
// message.
|
|
msg := testMsg.RandTestMessage(t)
|
|
|
|
// Serialize the message to a buffer.
|
|
var b bytes.Buffer
|
|
writtenBytes, err := WriteMessage(&b, msg, 0)
|
|
require.NoError(t, err, "unable to write msg")
|
|
|
|
// Check that the serialized payload is below the max
|
|
// payload size, accounting for the message type size.
|
|
payloadLen := uint32(writtenBytes) - 2
|
|
require.LessOrEqual(
|
|
t, payloadLen, uint32(MaxMsgBody),
|
|
"msg payload constraint violated: %v > %v",
|
|
payloadLen, MaxMsgBody,
|
|
)
|
|
|
|
// Deserialize the message from the buffer.
|
|
newMsg, err := ReadMessage(&b, 0)
|
|
require.NoError(t, err, "unable to read msg")
|
|
|
|
// Verify the deserialized message matches the original.
|
|
require.Equal(
|
|
t, msg, newMsg,
|
|
"message mismatch for type %s", msgType,
|
|
)
|
|
}))
|
|
}
|
|
}
|
|
|
|
func init() {
|
|
rand.Seed(time.Now().Unix())
|
|
}
|