mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-08-25 13:12:11 +02:00
250 lines
6.3 KiB
Go
250 lines
6.3 KiB
Go
package lnwire
|
|
|
|
import (
|
|
"bytes"
|
|
crand "crypto/rand"
|
|
"encoding/hex"
|
|
"math"
|
|
"net"
|
|
"testing"
|
|
|
|
"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,
|
|
)
|
|
}))
|
|
}
|
|
}
|