lnd/lnwire/test_message.go
Olaoluwa Osuntokun eb877db2ff
lnwire: add new TestMessage interface for property tests
In this commit, we add a new `TestMessage` interface for use in property
tests. With this, we'll be able to generate a random instance of a given
message, using the rapid byte stream. This can also eventually be useful
for fuzzing.
2025-03-20 18:28:07 -07:00

1670 lines
47 KiB
Go

package lnwire
import (
"bytes"
"fmt"
"image/color"
"math"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/lightningnetwork/lnd/fn/v2"
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
"github.com/lightningnetwork/lnd/tlv"
"pgregory.net/rapid"
)
// TestMessage is an interface that extends the base Message interface with a
// method to populate the message with random testing data.
type TestMessage interface {
Message
// RandTestMessage populates the message with random data suitable for
// testing. It uses the rapid testing framework to generate random
// values.
RandTestMessage(t *rapid.T) Message
}
// A compile time check to ensure AcceptChannel implements the TestMessage
// interface.
var _ TestMessage = (*AcceptChannel)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (a *AcceptChannel) RandTestMessage(t *rapid.T) Message {
var pendingChanID [32]byte
pendingChanIDBytes := rapid.SliceOfN(rapid.Byte(), 32, 32).Draw(
t, "pendingChanID",
)
copy(pendingChanID[:], pendingChanIDBytes)
var channelType *ChannelType
includeChannelType := rapid.Bool().Draw(t, "includeChannelType")
includeLeaseExpiry := rapid.Bool().Draw(t, "includeLeaseExpiry")
includeLocalNonce := rapid.Bool().Draw(t, "includeLocalNonce")
if includeChannelType {
channelType = RandChannelType(t)
}
var leaseExpiry *LeaseExpiry
if includeLeaseExpiry {
leaseExpiry = RandLeaseExpiry(t)
}
var localNonce OptMusig2NonceTLV
if includeLocalNonce {
nonce := RandMusig2Nonce(t)
localNonce = tlv.SomeRecordT(
tlv.NewRecordT[NonceRecordTypeT, Musig2Nonce](nonce),
)
}
return &AcceptChannel{
PendingChannelID: pendingChanID,
DustLimit: btcutil.Amount(
rapid.IntRange(100, 1000).Draw(t, "dustLimit"),
),
MaxValueInFlight: MilliSatoshi(
rapid.IntRange(10000, 1000000).Draw(
t, "maxValueInFlight",
),
),
ChannelReserve: btcutil.Amount(
rapid.IntRange(1000, 10000).Draw(t, "channelReserve"),
),
HtlcMinimum: MilliSatoshi(
rapid.IntRange(1, 1000).Draw(t, "htlcMinimum"),
),
MinAcceptDepth: uint32(
rapid.IntRange(1, 10).Draw(t, "minAcceptDepth"),
),
CsvDelay: uint16(
rapid.IntRange(144, 1000).Draw(t, "csvDelay"),
),
MaxAcceptedHTLCs: uint16(
rapid.IntRange(10, 500).Draw(t, "maxAcceptedHTLCs"),
),
FundingKey: RandPubKey(t),
RevocationPoint: RandPubKey(t),
PaymentPoint: RandPubKey(t),
DelayedPaymentPoint: RandPubKey(t),
HtlcPoint: RandPubKey(t),
FirstCommitmentPoint: RandPubKey(t),
UpfrontShutdownScript: RandDeliveryAddress(t),
ChannelType: channelType,
LeaseExpiry: leaseExpiry,
LocalNonce: localNonce,
ExtraData: RandExtraOpaqueData(t, nil),
}
}
// A compile time check to ensure AnnounceSignatures1 implements the
// lnwire.TestMessage interface.
var _ TestMessage = (*AnnounceSignatures1)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (a *AnnounceSignatures1) RandTestMessage(t *rapid.T) Message {
return &AnnounceSignatures1{
ChannelID: RandChannelID(t),
ShortChannelID: RandShortChannelID(t),
NodeSignature: RandSignature(t),
BitcoinSignature: RandSignature(t),
ExtraOpaqueData: RandExtraOpaqueData(t, nil),
}
}
// A compile time check to ensure AnnounceSignatures2 implements the
// lnwire.TestMessage interface.
var _ TestMessage = (*AnnounceSignatures2)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (a *AnnounceSignatures2) RandTestMessage(t *rapid.T) Message {
return &AnnounceSignatures2{
ChannelID: RandChannelID(t),
ShortChannelID: RandShortChannelID(t),
PartialSignature: *RandPartialSig(t),
ExtraOpaqueData: RandExtraOpaqueData(t, nil),
}
}
// A compile time check to ensure ChannelAnnouncement1 implements the
// TestMessage interface.
var _ TestMessage = (*ChannelAnnouncement1)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (a *ChannelAnnouncement1) RandTestMessage(t *rapid.T) Message {
// Generate Node IDs and Bitcoin keys (compressed public keys)
node1PubKey := RandPubKey(t)
node2PubKey := RandPubKey(t)
bitcoin1PubKey := RandPubKey(t)
bitcoin2PubKey := RandPubKey(t)
// Convert to byte arrays
var nodeID1, nodeID2, bitcoinKey1, bitcoinKey2 [33]byte
copy(nodeID1[:], node1PubKey.SerializeCompressed())
copy(nodeID2[:], node2PubKey.SerializeCompressed())
copy(bitcoinKey1[:], bitcoin1PubKey.SerializeCompressed())
copy(bitcoinKey2[:], bitcoin2PubKey.SerializeCompressed())
// Ensure nodeID1 is numerically less than nodeID2
// This is a requirement stated in the field description
if bytes.Compare(nodeID1[:], nodeID2[:]) > 0 {
nodeID1, nodeID2 = nodeID2, nodeID1
}
// Generate chain hash
chainHash := RandChainHash(t)
var hash chainhash.Hash
copy(hash[:], chainHash[:])
return &ChannelAnnouncement1{
NodeSig1: RandSignature(t),
NodeSig2: RandSignature(t),
BitcoinSig1: RandSignature(t),
BitcoinSig2: RandSignature(t),
Features: RandFeatureVector(t),
ChainHash: hash,
ShortChannelID: RandShortChannelID(t),
NodeID1: nodeID1,
NodeID2: nodeID2,
BitcoinKey1: bitcoinKey1,
BitcoinKey2: bitcoinKey2,
ExtraOpaqueData: RandExtraOpaqueData(t, nil),
}
}
// A compile time check to ensure ChannelAnnouncement2 implements the
// lnwire.TestMessage interface.
var _ TestMessage = (*ChannelAnnouncement2)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (c *ChannelAnnouncement2) RandTestMessage(t *rapid.T) Message {
features := RandFeatureVector(t)
shortChanID := RandShortChannelID(t)
capacity := uint64(rapid.IntRange(1, 16777215).Draw(t, "capacity"))
var nodeID1, nodeID2 [33]byte
copy(nodeID1[:], RandPubKey(t).SerializeCompressed())
copy(nodeID2[:], RandPubKey(t).SerializeCompressed())
// Make sure nodeID1 is numerically less than nodeID2 (as per spec).
if bytes.Compare(nodeID1[:], nodeID2[:]) > 0 {
nodeID1, nodeID2 = nodeID2, nodeID1
}
chainHash := RandChainHash(t)
var chainHashObj chainhash.Hash
copy(chainHashObj[:], chainHash[:])
msg := &ChannelAnnouncement2{
Signature: RandSignature(t),
ChainHash: tlv.NewPrimitiveRecord[tlv.TlvType0, chainhash.Hash](
chainHashObj,
),
Features: tlv.NewRecordT[tlv.TlvType2, RawFeatureVector](
*features,
),
ShortChannelID: tlv.NewRecordT[tlv.TlvType4, ShortChannelID](
shortChanID,
),
Capacity: tlv.NewPrimitiveRecord[tlv.TlvType6, uint64](
capacity,
),
NodeID1: tlv.NewPrimitiveRecord[tlv.TlvType8, [33]byte](
nodeID1,
),
NodeID2: tlv.NewPrimitiveRecord[tlv.TlvType10, [33]byte](
nodeID2,
),
ExtraOpaqueData: RandExtraOpaqueData(t, nil),
}
msg.Signature.ForceSchnorr()
// Randomly include optional fields
if rapid.Bool().Draw(t, "includeBitcoinKey1") {
var bitcoinKey1 [33]byte
copy(bitcoinKey1[:], RandPubKey(t).SerializeCompressed())
msg.BitcoinKey1 = tlv.SomeRecordT(
tlv.NewPrimitiveRecord[tlv.TlvType12, [33]byte](
bitcoinKey1,
),
)
}
if rapid.Bool().Draw(t, "includeBitcoinKey2") {
var bitcoinKey2 [33]byte
copy(bitcoinKey2[:], RandPubKey(t).SerializeCompressed())
msg.BitcoinKey2 = tlv.SomeRecordT(
tlv.NewPrimitiveRecord[tlv.TlvType14, [33]byte](
bitcoinKey2,
),
)
}
if rapid.Bool().Draw(t, "includeMerkleRootHash") {
hash := RandSHA256Hash(t)
var merkleRootHash [32]byte
copy(merkleRootHash[:], hash[:])
msg.MerkleRootHash = tlv.SomeRecordT(
tlv.NewPrimitiveRecord[tlv.TlvType16, [32]byte](
merkleRootHash,
),
)
}
return msg
}
// A compile time check to ensure ChannelReady implements the lnwire.TestMessage
// interface.
var _ TestMessage = (*ChannelReady)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (c *ChannelReady) RandTestMessage(t *rapid.T) Message {
msg := &ChannelReady{
ChanID: RandChannelID(t),
NextPerCommitmentPoint: RandPubKey(t),
ExtraData: RandExtraOpaqueData(t, nil),
}
includeAliasScid := rapid.Bool().Draw(t, "includeAliasScid")
includeNextLocalNonce := rapid.Bool().Draw(t, "includeNextLocalNonce")
includeAnnouncementNodeNonce := rapid.Bool().Draw(
t, "includeAnnouncementNodeNonce",
)
includeAnnouncementBitcoinNonce := rapid.Bool().Draw(
t, "includeAnnouncementBitcoinNonce",
)
if includeAliasScid {
scid := RandShortChannelID(t)
msg.AliasScid = &scid
}
if includeNextLocalNonce {
nonce := RandMusig2Nonce(t)
msg.NextLocalNonce = SomeMusig2Nonce(nonce)
}
if includeAnnouncementNodeNonce {
nonce := RandMusig2Nonce(t)
msg.AnnouncementNodeNonce = tlv.SomeRecordT(
tlv.NewRecordT[tlv.TlvType0, Musig2Nonce](nonce),
)
}
if includeAnnouncementBitcoinNonce {
nonce := RandMusig2Nonce(t)
msg.AnnouncementBitcoinNonce = tlv.SomeRecordT(
tlv.NewRecordT[tlv.TlvType2, Musig2Nonce](nonce),
)
}
return msg
}
// A compile time check to ensure ChannelReestablish implements the
// lnwire.TestMessage interface.
var _ TestMessage = (*ChannelReestablish)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (a *ChannelReestablish) RandTestMessage(t *rapid.T) Message {
msg := &ChannelReestablish{
ChanID: RandChannelID(t),
NextLocalCommitHeight: rapid.Uint64().Draw(
t, "nextLocalCommitHeight",
),
RemoteCommitTailHeight: rapid.Uint64().Draw(
t, "remoteCommitTailHeight",
),
LastRemoteCommitSecret: RandPaymentPreimage(t),
LocalUnrevokedCommitPoint: RandPubKey(t),
ExtraData: RandExtraOpaqueData(t, nil),
}
// Randomly decide whether to include optional fields
includeLocalNonce := rapid.Bool().Draw(t, "includeLocalNonce")
includeDynHeight := rapid.Bool().Draw(t, "includeDynHeight")
if includeLocalNonce {
nonce := RandMusig2Nonce(t)
msg.LocalNonce = SomeMusig2Nonce(nonce)
}
if includeDynHeight {
height := DynHeight(rapid.Uint64().Draw(t, "dynHeight"))
msg.DynHeight = fn.Some(height)
}
return msg
}
// A compile time check to ensure ChannelUpdate1 implements the TestMessage
// interface.
var _ TestMessage = (*ChannelUpdate1)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (a *ChannelUpdate1) RandTestMessage(t *rapid.T) Message {
// Generate random message flags
// Randomly decide whether to include max HTLC field
includeMaxHtlc := rapid.Bool().Draw(t, "includeMaxHtlc")
var msgFlags ChanUpdateMsgFlags
if includeMaxHtlc {
msgFlags |= ChanUpdateRequiredMaxHtlc
}
// Generate random channel flags
// Randomly decide direction (node1 or node2)
isNode2 := rapid.Bool().Draw(t, "isNode2")
var chanFlags ChanUpdateChanFlags
if isNode2 {
chanFlags |= ChanUpdateDirection
}
// Randomly decide if channel is disabled
isDisabled := rapid.Bool().Draw(t, "isDisabled")
if isDisabled {
chanFlags |= ChanUpdateDisabled
}
// Generate chain hash
chainHash := RandChainHash(t)
var hash chainhash.Hash
copy(hash[:], chainHash[:])
// Generate other random fields
maxHtlc := MilliSatoshi(rapid.Uint64().Draw(t, "maxHtlc"))
// If max HTLC flag is not set, we need to zero the value
if !includeMaxHtlc {
maxHtlc = 0
}
return &ChannelUpdate1{
Signature: RandSignature(t),
ChainHash: hash,
ShortChannelID: RandShortChannelID(t),
Timestamp: uint32(rapid.IntRange(0, 0x7FFFFFFF).Draw(
t, "timestamp"),
),
MessageFlags: msgFlags,
ChannelFlags: chanFlags,
TimeLockDelta: uint16(rapid.IntRange(0, 65535).Draw(
t, "timelockDelta"),
),
HtlcMinimumMsat: MilliSatoshi(rapid.Uint64().Draw(
t, "htlcMinimum"),
),
BaseFee: uint32(rapid.IntRange(0, 0x7FFFFFFF).Draw(
t, "baseFee"),
),
FeeRate: uint32(rapid.IntRange(0, 0x7FFFFFFF).Draw(
t, "feeRate"),
),
HtlcMaximumMsat: maxHtlc,
ExtraOpaqueData: RandExtraOpaqueData(t, nil),
}
}
// A compile time check to ensure ChannelUpdate2 implements the
// lnwire.TestMessage interface.
var _ TestMessage = (*ChannelUpdate2)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (c *ChannelUpdate2) RandTestMessage(t *rapid.T) Message {
shortChanID := RandShortChannelID(t)
blockHeight := uint32(rapid.IntRange(0, 1000000).Draw(t, "blockHeight"))
var disabledFlags ChanUpdateDisableFlags
if rapid.Bool().Draw(t, "disableIncoming") {
disabledFlags |= ChanUpdateDisableIncoming
}
if rapid.Bool().Draw(t, "disableOutgoing") {
disabledFlags |= ChanUpdateDisableOutgoing
}
cltvExpiryDelta := uint16(rapid.IntRange(10, 200).Draw(
t, "cltvExpiryDelta"),
)
htlcMinMsat := MilliSatoshi(rapid.IntRange(1, 10000).Draw(
t, "htlcMinMsat"),
)
htlcMaxMsat := MilliSatoshi(rapid.IntRange(10000, 100000000).Draw(
t, "htlcMaxMsat"),
)
feeBaseMsat := uint32(rapid.IntRange(0, 10000).Draw(t, "feeBaseMsat"))
feeProportionalMillionths := uint32(rapid.IntRange(0, 10000).Draw(
t, "feeProportionalMillionths"),
)
chainHash := RandChainHash(t)
var chainHashObj chainhash.Hash
copy(chainHashObj[:], chainHash[:])
//nolint:ll
msg := &ChannelUpdate2{
Signature: RandSignature(t),
ChainHash: tlv.NewPrimitiveRecord[tlv.TlvType0, chainhash.Hash](
chainHashObj,
),
ShortChannelID: tlv.NewRecordT[tlv.TlvType2, ShortChannelID](
shortChanID,
),
BlockHeight: tlv.NewPrimitiveRecord[tlv.TlvType4, uint32](
blockHeight,
),
DisabledFlags: tlv.NewPrimitiveRecord[tlv.TlvType6, ChanUpdateDisableFlags]( //nolint:ll
disabledFlags,
),
CLTVExpiryDelta: tlv.NewPrimitiveRecord[tlv.TlvType10, uint16](
cltvExpiryDelta,
),
HTLCMinimumMsat: tlv.NewPrimitiveRecord[tlv.TlvType12, MilliSatoshi](
htlcMinMsat,
),
HTLCMaximumMsat: tlv.NewPrimitiveRecord[tlv.TlvType14, MilliSatoshi](
htlcMaxMsat,
),
FeeBaseMsat: tlv.NewPrimitiveRecord[tlv.TlvType16, uint32](
feeBaseMsat,
),
FeeProportionalMillionths: tlv.NewPrimitiveRecord[tlv.TlvType18, uint32](
feeProportionalMillionths,
),
ExtraOpaqueData: RandExtraOpaqueData(t, nil),
}
msg.Signature.ForceSchnorr()
if rapid.Bool().Draw(t, "isSecondPeer") {
msg.SecondPeer = tlv.SomeRecordT(
tlv.RecordT[tlv.TlvType8, TrueBoolean]{},
)
}
return msg
}
// A compile time check to ensure ClosingComplete implements the
// lnwire.TestMessage interface.
var _ TestMessage = (*ClosingComplete)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (c *ClosingComplete) RandTestMessage(t *rapid.T) Message {
msg := &ClosingComplete{
ChannelID: RandChannelID(t),
FeeSatoshis: btcutil.Amount(rapid.Int64Range(0, 1000000).Draw(
t, "feeSatoshis"),
),
LockTime: rapid.Uint32Range(0, 0xffffffff).Draw(
t, "lockTime",
),
CloseeScript: RandDeliveryAddress(t),
CloserScript: RandDeliveryAddress(t),
ExtraData: RandExtraOpaqueData(t, nil),
}
includeCloserNoClosee := rapid.Bool().Draw(t, "includeCloserNoClosee")
includeNoCloserClosee := rapid.Bool().Draw(t, "includeNoCloserClosee")
includeCloserAndClosee := rapid.Bool().Draw(t, "includeCloserAndClosee")
// Ensure at least one signature is present.
if !includeCloserNoClosee && !includeNoCloserClosee &&
!includeCloserAndClosee {
// If all are false, enable at least one randomly.
choice := rapid.IntRange(0, 2).Draw(t, "sigChoice")
switch choice {
case 0:
includeCloserNoClosee = true
case 1:
includeNoCloserClosee = true
case 2:
includeCloserAndClosee = true
}
}
if includeCloserNoClosee {
sig := RandSignature(t)
msg.CloserNoClosee = tlv.SomeRecordT(
tlv.NewRecordT[tlv.TlvType1, Sig](sig),
)
}
if includeNoCloserClosee {
sig := RandSignature(t)
msg.NoCloserClosee = tlv.SomeRecordT(
tlv.NewRecordT[tlv.TlvType2, Sig](sig),
)
}
if includeCloserAndClosee {
sig := RandSignature(t)
msg.CloserAndClosee = tlv.SomeRecordT(
tlv.NewRecordT[tlv.TlvType3, Sig](sig),
)
}
return msg
}
// A compile time check to ensure ClosingSig implements the lnwire.TestMessage
// interface.
var _ TestMessage = (*ClosingSig)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (c *ClosingSig) RandTestMessage(t *rapid.T) Message {
msg := &ClosingSig{
ChannelID: RandChannelID(t),
CloseeScript: RandDeliveryAddress(t),
CloserScript: RandDeliveryAddress(t),
ExtraData: RandExtraOpaqueData(t, nil),
}
includeCloserNoClosee := rapid.Bool().Draw(t, "includeCloserNoClosee")
includeNoCloserClosee := rapid.Bool().Draw(t, "includeNoCloserClosee")
includeCloserAndClosee := rapid.Bool().Draw(t, "includeCloserAndClosee")
// Ensure at least one signature is present.
if !includeCloserNoClosee && !includeNoCloserClosee &&
!includeCloserAndClosee {
// If all are false, enable at least one randomly.
choice := rapid.IntRange(0, 2).Draw(t, "sigChoice")
switch choice {
case 0:
includeCloserNoClosee = true
case 1:
includeNoCloserClosee = true
case 2:
includeCloserAndClosee = true
}
}
if includeCloserNoClosee {
sig := RandSignature(t)
msg.CloserNoClosee = tlv.SomeRecordT(
tlv.NewRecordT[tlv.TlvType1, Sig](sig),
)
}
if includeNoCloserClosee {
sig := RandSignature(t)
msg.NoCloserClosee = tlv.SomeRecordT(
tlv.NewRecordT[tlv.TlvType2, Sig](sig),
)
}
if includeCloserAndClosee {
sig := RandSignature(t)
msg.CloserAndClosee = tlv.SomeRecordT(
tlv.NewRecordT[tlv.TlvType3, Sig](sig),
)
}
return msg
}
// A compile time check to ensure ClosingSigned implements the
// lnwire.TestMessage interface.
var _ TestMessage = (*ClosingSigned)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (c *ClosingSigned) RandTestMessage(t *rapid.T) Message {
// Generate a random boolean to decide whether to include CommitSig or
// PartialSig Since they're mutually exclusive, when one is populated,
// the other must be blank.
usePartialSig := rapid.Bool().Draw(t, "usePartialSig")
msg := &ClosingSigned{
ChannelID: RandChannelID(t),
FeeSatoshis: btcutil.Amount(
rapid.Int64Range(0, 1000000).Draw(t, "feeSatoshis"),
),
ExtraData: RandExtraOpaqueData(t, nil),
}
if usePartialSig {
sigBytes := rapid.SliceOfN(rapid.Byte(), 32, 32).Draw(
t, "sigScalar",
)
var s btcec.ModNScalar
_ = s.SetByteSlice(sigBytes)
msg.PartialSig = SomePartialSig(NewPartialSig(s))
msg.Signature = Sig{}
} else {
msg.Signature = RandSignature(t)
}
return msg
}
// A compile time check to ensure CommitSig implements the lnwire.TestMessage
// interface.
var _ TestMessage = (*CommitSig)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (c *CommitSig) RandTestMessage(t *rapid.T) Message {
cr, _ := RandCustomRecords(t, nil, true)
sig := &CommitSig{
ChanID: RandChannelID(t),
CommitSig: RandSignature(t),
CustomRecords: cr,
}
numHtlcSigs := rapid.IntRange(0, 20).Draw(t, "numHtlcSigs")
htlcSigs := make([]Sig, numHtlcSigs)
for i := 0; i < numHtlcSigs; i++ {
htlcSigs[i] = RandSignature(t)
}
if len(htlcSigs) > 0 {
sig.HtlcSigs = htlcSigs
}
includePartialSig := rapid.Bool().Draw(t, "includePartialSig")
if includePartialSig {
sigWithNonce := RandPartialSigWithNonce(t)
sig.PartialSig = MaybePartialSigWithNonce(sigWithNonce)
}
return sig
}
// A compile time check to ensure Custom implements the lnwire.TestMessage
// interface.
var _ TestMessage = (*Custom)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (c *Custom) RandTestMessage(t *rapid.T) Message {
msgType := MessageType(
rapid.IntRange(int(CustomTypeStart), 65535).Draw(
t, "customMsgType",
),
)
dataLen := rapid.IntRange(0, 1000).Draw(t, "customDataLength")
data := rapid.SliceOfN(rapid.Byte(), dataLen, dataLen).Draw(
t, "customData",
)
msg, err := NewCustom(msgType, data)
if err != nil {
panic(fmt.Sprintf("Error creating custom message: %v", err))
}
return msg
}
// A compile time check to ensure DynAck implements the lnwire.TestMessage
// interface.
var _ TestMessage = (*DynAck)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (da *DynAck) RandTestMessage(t *rapid.T) Message {
msg := &DynAck{
ChanID: RandChannelID(t),
ExtraData: RandExtraOpaqueData(t, nil),
}
includeLocalNonce := rapid.Bool().Draw(t, "includeLocalNonce")
if includeLocalNonce {
msg.LocalNonce = fn.Some(RandMusig2Nonce(t))
}
return msg
}
// A compile time check to ensure DynPropose implements the lnwire.TestMessage
// interface.
var _ TestMessage = (*DynPropose)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (dp *DynPropose) RandTestMessage(t *rapid.T) Message {
msg := &DynPropose{
ChanID: RandChannelID(t),
Initiator: rapid.Bool().Draw(t, "initiator"),
ExtraData: RandExtraOpaqueData(t, nil),
}
// Randomly decide which optional fields to include
includeDustLimit := rapid.Bool().Draw(t, "includeDustLimit")
includeMaxValueInFlight := rapid.Bool().Draw(
t, "includeMaxValueInFlight",
)
includeChannelReserve := rapid.Bool().Draw(t, "includeChannelReserve")
includeCsvDelay := rapid.Bool().Draw(t, "includeCsvDelay")
includeMaxAcceptedHTLCs := rapid.Bool().Draw(
t, "includeMaxAcceptedHTLCs",
)
includeFundingKey := rapid.Bool().Draw(t, "includeFundingKey")
includeChannelType := rapid.Bool().Draw(t, "includeChannelType")
includeKickoffFeerate := rapid.Bool().Draw(t, "includeKickoffFeerate")
// Generate random values for each included field
if includeDustLimit {
dl := btcutil.Amount(rapid.Uint32().Draw(t, "dustLimit"))
msg.DustLimit = fn.Some(dl)
}
if includeMaxValueInFlight {
mvif := MilliSatoshi(rapid.Uint64().Draw(t, "maxValueInFlight"))
msg.MaxValueInFlight = fn.Some(mvif)
}
if includeChannelReserve {
cr := btcutil.Amount(rapid.Uint32().Draw(t, "channelReserve"))
msg.ChannelReserve = fn.Some(cr)
}
if includeCsvDelay {
cd := rapid.Uint16().Draw(t, "csvDelay")
msg.CsvDelay = fn.Some(cd)
}
if includeMaxAcceptedHTLCs {
mah := rapid.Uint16().Draw(t, "maxAcceptedHTLCs")
msg.MaxAcceptedHTLCs = fn.Some(mah)
}
if includeFundingKey {
msg.FundingKey = fn.Some(*RandPubKey(t))
}
if includeChannelType {
msg.ChannelType = fn.Some(*RandChannelType(t))
}
if includeKickoffFeerate {
kf := chainfee.SatPerKWeight(rapid.Uint32().Draw(
t, "kickoffFeerate"),
)
msg.KickoffFeerate = fn.Some(kf)
}
return msg
}
// A compile time check to ensure DynReject implements the lnwire.TestMessage
// interface.
var _ TestMessage = (*DynReject)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (dr *DynReject) RandTestMessage(t *rapid.T) Message {
featureVec := NewRawFeatureVector()
numFeatures := rapid.IntRange(0, 8).Draw(t, "numRejections")
for i := 0; i < numFeatures; i++ {
bit := FeatureBit(
rapid.IntRange(0, 31).Draw(
t, fmt.Sprintf("rejectionBit-%d", i),
),
)
featureVec.Set(bit)
}
var extraData ExtraOpaqueData
randData := RandExtraOpaqueData(t, nil)
if len(randData) > 0 {
extraData = randData
}
return &DynReject{
ChanID: RandChannelID(t),
UpdateRejections: *featureVec,
ExtraData: extraData,
}
}
// A compile time check to ensure FundingCreated implements the TestMessage
// interface.
var _ TestMessage = (*FundingCreated)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (f *FundingCreated) RandTestMessage(t *rapid.T) Message {
var pendingChanID [32]byte
pendingChanIDBytes := rapid.SliceOfN(rapid.Byte(), 32, 32).Draw(
t, "pendingChanID",
)
copy(pendingChanID[:], pendingChanIDBytes)
includePartialSig := rapid.Bool().Draw(t, "includePartialSig")
var partialSig OptPartialSigWithNonceTLV
var commitSig Sig
if includePartialSig {
sigWithNonce := RandPartialSigWithNonce(t)
partialSig = MaybePartialSigWithNonce(sigWithNonce)
// When using partial sig, CommitSig should be empty/blank.
commitSig = Sig{}
} else {
commitSig = RandSignature(t)
}
return &FundingCreated{
PendingChannelID: pendingChanID,
FundingPoint: RandOutPoint(t),
CommitSig: commitSig,
PartialSig: partialSig,
ExtraData: RandExtraOpaqueData(t, nil),
}
}
// A compile time check to ensure FundingSigned implements the
// lnwire.TestMessage interface.
var _ TestMessage = (*FundingSigned)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (f *FundingSigned) RandTestMessage(t *rapid.T) Message {
usePartialSig := rapid.Bool().Draw(t, "usePartialSig")
msg := &FundingSigned{
ChanID: RandChannelID(t),
ExtraData: RandExtraOpaqueData(t, nil),
}
if usePartialSig {
sigWithNonce := RandPartialSigWithNonce(t)
msg.PartialSig = MaybePartialSigWithNonce(sigWithNonce)
msg.CommitSig = Sig{}
} else {
msg.CommitSig = RandSignature(t)
}
return msg
}
// A compile time check to ensure GossipTimestampRange implements the
// lnwire.TestMessage interface.
var _ TestMessage = (*GossipTimestampRange)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (g *GossipTimestampRange) RandTestMessage(t *rapid.T) Message {
var chainHash chainhash.Hash
hashBytes := rapid.SliceOfN(rapid.Byte(), 32, 32).Draw(t, "chainHash")
copy(chainHash[:], hashBytes)
msg := &GossipTimestampRange{
ChainHash: chainHash,
FirstTimestamp: rapid.Uint32().Draw(t, "firstTimestamp"),
TimestampRange: rapid.Uint32().Draw(t, "timestampRange"),
ExtraData: RandExtraOpaqueData(t, nil),
}
includeFirstBlockHeight := rapid.Bool().Draw(
t, "includeFirstBlockHeight",
)
includeBlockRange := rapid.Bool().Draw(t, "includeBlockRange")
if includeFirstBlockHeight {
height := rapid.Uint32().Draw(t, "firstBlockHeight")
msg.FirstBlockHeight = tlv.SomeRecordT(
tlv.RecordT[tlv.TlvType2, uint32]{Val: height},
)
}
if includeBlockRange {
blockRange := rapid.Uint32().Draw(t, "blockRange")
msg.BlockRange = tlv.SomeRecordT(
tlv.RecordT[tlv.TlvType4, uint32]{Val: blockRange},
)
}
return msg
}
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (msg *Init) RandTestMessage(t *rapid.T) Message {
global := NewRawFeatureVector()
local := NewRawFeatureVector()
numGlobalFeatures := rapid.IntRange(0, 20).Draw(t, "numGlobalFeatures")
for i := 0; i < numGlobalFeatures; i++ {
bit := FeatureBit(
rapid.IntRange(0, 100).Draw(
t, fmt.Sprintf("globalFeatureBit%d", i),
),
)
global.Set(bit)
}
numLocalFeatures := rapid.IntRange(0, 20).Draw(t, "numLocalFeatures")
for i := 0; i < numLocalFeatures; i++ {
bit := FeatureBit(
rapid.IntRange(0, 100).Draw(
t, fmt.Sprintf("localFeatureBit%d", i),
),
)
local.Set(bit)
}
return NewInitMessage(global, local)
}
// A compile time check to ensure KickoffSig implements the lnwire.TestMessage
// interface.
var _ TestMessage = (*KickoffSig)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (ks *KickoffSig) RandTestMessage(t *rapid.T) Message {
return &KickoffSig{
ChanID: RandChannelID(t),
Signature: RandSignature(t),
ExtraData: RandExtraOpaqueData(t, nil),
}
}
// A compile time check to ensure NodeAnnouncement implements the
// lnwire.TestMessage interface.
var _ TestMessage = (*NodeAnnouncement)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (a *NodeAnnouncement) RandTestMessage(t *rapid.T) Message {
// Generate random compressed public key for node ID
pubKey := RandPubKey(t)
var nodeID [33]byte
copy(nodeID[:], pubKey.SerializeCompressed())
// Generate random RGB color
rgbColor := color.RGBA{
R: uint8(rapid.IntRange(0, 255).Draw(t, "rgbR")),
G: uint8(rapid.IntRange(0, 255).Draw(t, "rgbG")),
B: uint8(rapid.IntRange(0, 255).Draw(t, "rgbB")),
}
return &NodeAnnouncement{
Signature: RandSignature(t),
Features: RandFeatureVector(t),
Timestamp: uint32(rapid.IntRange(0, 0x7FFFFFFF).Draw(
t, "timestamp"),
),
NodeID: nodeID,
RGBColor: rgbColor,
Alias: RandNodeAlias(t),
Addresses: RandNetAddrs(t),
ExtraOpaqueData: RandExtraOpaqueData(t, nil),
}
}
// A compile time check to ensure OpenChannel implements the TestMessage
// interface.
var _ TestMessage = (*OpenChannel)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (o *OpenChannel) RandTestMessage(t *rapid.T) Message {
chainHash := RandChainHash(t)
var hash chainhash.Hash
copy(hash[:], chainHash[:])
var pendingChanID [32]byte
pendingChanIDBytes := rapid.SliceOfN(rapid.Byte(), 32, 32).Draw(
t, "pendingChanID",
)
copy(pendingChanID[:], pendingChanIDBytes)
includeChannelType := rapid.Bool().Draw(t, "includeChannelType")
includeLeaseExpiry := rapid.Bool().Draw(t, "includeLeaseExpiry")
includeLocalNonce := rapid.Bool().Draw(t, "includeLocalNonce")
var channelFlags FundingFlag
if rapid.Bool().Draw(t, "announceChannel") {
channelFlags |= FFAnnounceChannel
}
var localNonce OptMusig2NonceTLV
if includeLocalNonce {
nonce := RandMusig2Nonce(t)
localNonce = tlv.SomeRecordT(
tlv.NewRecordT[NonceRecordTypeT, Musig2Nonce](nonce),
)
}
var channelType *ChannelType
if includeChannelType {
channelType = RandChannelType(t)
}
var leaseExpiry *LeaseExpiry
if includeLeaseExpiry {
leaseExpiry = RandLeaseExpiry(t)
}
return &OpenChannel{
ChainHash: hash,
PendingChannelID: pendingChanID,
FundingAmount: btcutil.Amount(
rapid.IntRange(5000, 10000000).Draw(t, "fundingAmount"),
),
PushAmount: MilliSatoshi(
rapid.IntRange(0, 1000000).Draw(t, "pushAmount"),
),
DustLimit: btcutil.Amount(
rapid.IntRange(100, 1000).Draw(t, "dustLimit"),
),
MaxValueInFlight: MilliSatoshi(
rapid.IntRange(10000, 1000000).Draw(
t, "maxValueInFlight",
),
),
ChannelReserve: btcutil.Amount(
rapid.IntRange(1000, 10000).Draw(t, "channelReserve"),
),
HtlcMinimum: MilliSatoshi(
rapid.IntRange(1, 1000).Draw(t, "htlcMinimum"),
),
FeePerKiloWeight: uint32(
rapid.IntRange(250, 10000).Draw(t, "feePerKw"),
),
CsvDelay: uint16(
rapid.IntRange(144, 1000).Draw(t, "csvDelay"),
),
MaxAcceptedHTLCs: uint16(
rapid.IntRange(10, 500).Draw(t, "maxAcceptedHTLCs"),
),
FundingKey: RandPubKey(t),
RevocationPoint: RandPubKey(t),
PaymentPoint: RandPubKey(t),
DelayedPaymentPoint: RandPubKey(t),
HtlcPoint: RandPubKey(t),
FirstCommitmentPoint: RandPubKey(t),
ChannelFlags: channelFlags,
UpfrontShutdownScript: RandDeliveryAddress(t),
ChannelType: channelType,
LeaseExpiry: leaseExpiry,
LocalNonce: localNonce,
ExtraData: RandExtraOpaqueData(t, nil),
}
}
// A compile time check to ensure Ping implements the lnwire.TestMessage
// interface.
var _ TestMessage = (*Ping)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (p *Ping) RandTestMessage(t *rapid.T) Message {
numPongBytes := uint16(rapid.IntRange(0, int(MaxPongBytes)).Draw(
t, "numPongBytes"),
)
// Generate padding bytes (but keeping within allowed message size)
// MaxMsgBody - 2 (for NumPongBytes) - 2 (for padding length)
maxPaddingLen := MaxMsgBody - 4
paddingLen := rapid.IntRange(0, maxPaddingLen).Draw(
t, "paddingLen",
)
padding := make(PingPayload, paddingLen)
// Fill padding with random bytes
for i := 0; i < paddingLen; i++ {
padding[i] = byte(rapid.IntRange(0, 255).Draw(
t, fmt.Sprintf("paddingByte%d", i)),
)
}
return &Ping{
NumPongBytes: numPongBytes,
PaddingBytes: padding,
}
}
// A compile time check to ensure Pong implements the lnwire.TestMessage
// interface.
var _ TestMessage = (*Pong)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (p *Pong) RandTestMessage(t *rapid.T) Message {
payloadLen := rapid.IntRange(0, 1000).Draw(t, "pongPayloadLength")
payload := rapid.SliceOfN(rapid.Byte(), payloadLen, payloadLen).Draw(
t, "pongPayload",
)
return &Pong{
PongBytes: payload,
}
}
// A compile time check to ensure QueryChannelRange implements the
// lnwire.TestMessage interface.
var _ TestMessage = (*QueryChannelRange)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (q *QueryChannelRange) RandTestMessage(t *rapid.T) Message {
msg := &QueryChannelRange{
FirstBlockHeight: uint32(rapid.IntRange(0, 1000000).Draw(
t, "firstBlockHeight"),
),
NumBlocks: uint32(rapid.IntRange(1, 10000).Draw(
t, "numBlocks"),
),
ExtraData: RandExtraOpaqueData(t, nil),
}
// Generate chain hash
chainHash := RandChainHash(t)
var chainHashObj chainhash.Hash
copy(chainHashObj[:], chainHash[:])
msg.ChainHash = chainHashObj
// Randomly include QueryOptions
if rapid.Bool().Draw(t, "includeQueryOptions") {
queryOptions := &QueryOptions{}
*queryOptions = QueryOptions(*RandFeatureVector(t))
msg.QueryOptions = queryOptions
}
return msg
}
// A compile time check to ensure QueryShortChanIDs implements the
// lnwire.TestMessage interface.
var _ TestMessage = (*QueryShortChanIDs)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (q *QueryShortChanIDs) RandTestMessage(t *rapid.T) Message {
var chainHash chainhash.Hash
hashBytes := rapid.SliceOfN(rapid.Byte(), 32, 32).Draw(t, "chainHash")
copy(chainHash[:], hashBytes)
encodingType := EncodingSortedPlain
if rapid.Bool().Draw(t, "useZlibEncoding") {
encodingType = EncodingSortedZlib
}
msg := &QueryShortChanIDs{
ChainHash: chainHash,
EncodingType: encodingType,
ExtraData: RandExtraOpaqueData(t, nil),
noSort: false,
}
numIDs := rapid.IntRange(2, 20).Draw(t, "numShortChanIDs")
// Generate sorted short channel IDs.
shortChanIDs := make([]ShortChannelID, numIDs)
for i := 0; i < numIDs; i++ {
shortChanIDs[i] = RandShortChannelID(t)
// Ensure they're properly sorted.
if i > 0 && shortChanIDs[i].ToUint64() <=
shortChanIDs[i-1].ToUint64() {
// Ensure this ID is larger than the previous one.
shortChanIDs[i] = NewShortChanIDFromInt(
shortChanIDs[i-1].ToUint64() + 1,
)
}
}
msg.ShortChanIDs = shortChanIDs
return msg
}
// A compile time check to ensure ReplyChannelRange implements the
// lnwire.TestMessage interface.
var _ TestMessage = (*ReplyChannelRange)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (c *ReplyChannelRange) RandTestMessage(t *rapid.T) Message {
msg := &ReplyChannelRange{
FirstBlockHeight: uint32(rapid.IntRange(0, 1000000).Draw(
t, "firstBlockHeight"),
),
NumBlocks: uint32(rapid.IntRange(1, 10000).Draw(
t, "numBlocks"),
),
Complete: uint8(rapid.IntRange(0, 1).Draw(t, "complete")),
EncodingType: QueryEncoding(
rapid.IntRange(0, 1).Draw(t, "encodingType"),
),
ExtraData: RandExtraOpaqueData(t, nil),
}
msg.ChainHash = RandChainHash(t)
numShortChanIDs := rapid.IntRange(0, 20).Draw(t, "numShortChanIDs")
if numShortChanIDs == 0 {
return msg
}
scidSet := fn.NewSet[ShortChannelID]()
scids := make([]ShortChannelID, numShortChanIDs)
for i := 0; i < numShortChanIDs; i++ {
scid := RandShortChannelID(t)
for scidSet.Contains(scid) {
scid = RandShortChannelID(t)
}
scids[i] = scid
scidSet.Add(scid)
}
// Make sure there're no duplicates.
msg.ShortChanIDs = scids
if rapid.Bool().Draw(t, "includeTimestamps") && numShortChanIDs > 0 {
msg.Timestamps = make(Timestamps, numShortChanIDs)
for i := 0; i < numShortChanIDs; i++ {
msg.Timestamps[i] = ChanUpdateTimestamps{
Timestamp1: uint32(rapid.IntRange(0, math.MaxInt32).Draw(t, fmt.Sprintf("timestamp-1-%d", i))), //nolint:ll
Timestamp2: uint32(rapid.IntRange(0, math.MaxInt32).Draw(t, fmt.Sprintf("timestamp-2-%d", i))), //nolint:ll
}
}
}
return msg
}
// A compile time check to ensure ReplyShortChanIDsEnd implements the
// lnwire.TestMessage interface.
var _ TestMessage = (*ReplyShortChanIDsEnd)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (c *ReplyShortChanIDsEnd) RandTestMessage(t *rapid.T) Message {
var chainHash chainhash.Hash
hashBytes := rapid.SliceOfN(rapid.Byte(), 32, 32).Draw(t, "chainHash")
copy(chainHash[:], hashBytes)
complete := uint8(rapid.IntRange(0, 1).Draw(t, "complete"))
return &ReplyShortChanIDsEnd{
ChainHash: chainHash,
Complete: complete,
ExtraData: RandExtraOpaqueData(t, nil),
}
}
// RandTestMessage returns a RevokeAndAck message populated with random data.
//
// This is part of the TestMessage interface.
func (c *RevokeAndAck) RandTestMessage(t *rapid.T) Message {
msg := NewRevokeAndAck()
var chanID ChannelID
bytes := rapid.SliceOfN(rapid.Byte(), 32, 32).Draw(t, "channelID")
copy(chanID[:], bytes)
msg.ChanID = chanID
revBytes := rapid.SliceOfN(rapid.Byte(), 32, 32).Draw(t, "revocation")
copy(msg.Revocation[:], revBytes)
msg.NextRevocationKey = RandPubKey(t)
if rapid.Bool().Draw(t, "includeLocalNonce") {
var nonce Musig2Nonce
nonceBytes := rapid.SliceOfN(rapid.Byte(), 32, 32).Draw(
t, "nonce",
)
copy(nonce[:], nonceBytes)
msg.LocalNonce = tlv.SomeRecordT(
tlv.NewRecordT[NonceRecordTypeT, Musig2Nonce](nonce),
)
}
return msg
}
// A compile-time check to ensure Shutdown implements the lnwire.TestMessage
// interface.
var _ TestMessage = (*Shutdown)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (s *Shutdown) RandTestMessage(t *rapid.T) Message {
// Generate random delivery address
// First decide the address type (P2PKH, P2SH, P2WPKH, P2WSH, P2TR)
addrType := rapid.IntRange(0, 4).Draw(t, "addrType")
// Generate random address length based on type
var addrLen int
switch addrType {
// P2PKH
case 0:
addrLen = 25
// P2SH
case 1:
addrLen = 23
// P2WPKH
case 2:
addrLen = 22
// P2WSH
case 3:
addrLen = 34
// P2TR
case 4:
addrLen = 34
}
addr := rapid.SliceOfN(rapid.Byte(), addrLen, addrLen).Draw(
t, "address",
)
// Randomly decide whether to include a shutdown nonce
includeNonce := rapid.Bool().Draw(t, "includeNonce")
var shutdownNonce ShutdownNonceTLV
if includeNonce {
shutdownNonce = SomeShutdownNonce(RandMusig2Nonce(t))
}
cr, _ := RandCustomRecords(t, nil, true)
return &Shutdown{
ChannelID: RandChannelID(t),
Address: addr,
ShutdownNonce: shutdownNonce,
CustomRecords: cr,
}
}
// A compile time check to ensure Stfu implements the lnwire.TestMessage
// interface.
var _ TestMessage = (*Stfu)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (s *Stfu) RandTestMessage(t *rapid.T) Message {
m := &Stfu{
ChanID: RandChannelID(t),
Initiator: rapid.Bool().Draw(t, "initiator"),
}
extraData := RandExtraOpaqueData(t, nil)
if len(extraData) > 0 {
m.ExtraData = extraData
}
return m
}
// A compile time check to ensure UpdateAddHTLC implements the
// lnwire.TestMessage interface.
var _ TestMessage = (*UpdateAddHTLC)(nil)
// RandTestMessage returns an UpdateAddHTLC message populated with random data.
//
// This is part of the TestMessage interface.
func (c *UpdateAddHTLC) RandTestMessage(t *rapid.T) Message {
msg := &UpdateAddHTLC{
ChanID: RandChannelID(t),
ID: rapid.Uint64().Draw(t, "id"),
Amount: MilliSatoshi(rapid.Uint64().Draw(t, "amount")),
Expiry: rapid.Uint32().Draw(t, "expiry"),
}
hashBytes := rapid.SliceOfN(rapid.Byte(), 32, 32).Draw(t, "paymentHash")
copy(msg.PaymentHash[:], hashBytes)
onionBytes := rapid.SliceOfN(
rapid.Byte(), OnionPacketSize, OnionPacketSize,
).Draw(t, "onionBlob")
copy(msg.OnionBlob[:], onionBytes)
numRecords := rapid.IntRange(0, 5).Draw(t, "numRecords")
if numRecords > 0 {
msg.CustomRecords, _ = RandCustomRecords(t, nil, true)
}
// 50/50 chance to add a blinding point
if rapid.Bool().Draw(t, "includeBlindingPoint") {
pubKey := RandPubKey(t)
msg.BlindingPoint = tlv.SomeRecordT(
tlv.NewPrimitiveRecord[BlindingPointTlvType](pubKey),
)
}
return msg
}
// A compile time check to ensure UpdateFailHTLC implements the TestMessage
// interface.
var _ TestMessage = (*UpdateFailHTLC)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (c *UpdateFailHTLC) RandTestMessage(t *rapid.T) Message {
return &UpdateFailHTLC{
ChanID: RandChannelID(t),
ID: rapid.Uint64().Draw(t, "id"),
Reason: RandOpaqueReason(t),
ExtraData: RandExtraOpaqueData(t, nil),
}
}
// A compile time check to ensure UpdateFailMalformedHTLC implements the
// TestMessage interface.
var _ TestMessage = (*UpdateFailMalformedHTLC)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (c *UpdateFailMalformedHTLC) RandTestMessage(t *rapid.T) Message {
return &UpdateFailMalformedHTLC{
ChanID: RandChannelID(t),
ID: rapid.Uint64().Draw(t, "id"),
ShaOnionBlob: RandSHA256Hash(t),
FailureCode: RandFailCode(t),
ExtraData: RandExtraOpaqueData(t, nil),
}
}
// A compile time check to ensure UpdateFee implements the TestMessage
// interface.
var _ TestMessage = (*UpdateFee)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (c *UpdateFee) RandTestMessage(t *rapid.T) Message {
return &UpdateFee{
ChanID: RandChannelID(t),
FeePerKw: uint32(rapid.IntRange(1, 10000).Draw(t, "feePerKw")),
ExtraData: RandExtraOpaqueData(t, nil),
}
}
// A compile time check to ensure UpdateFulfillHTLC implements the TestMessage
// interface.
var _ TestMessage = (*UpdateFulfillHTLC)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (c *UpdateFulfillHTLC) RandTestMessage(t *rapid.T) Message {
msg := &UpdateFulfillHTLC{
ChanID: RandChannelID(t),
ID: rapid.Uint64().Draw(t, "id"),
PaymentPreimage: RandPaymentPreimage(t),
}
cr, ignoreRecords := RandCustomRecords(t, nil, true)
msg.CustomRecords = cr
randData := RandExtraOpaqueData(t, ignoreRecords)
if len(randData) > 0 {
msg.ExtraData = randData
}
return msg
}
// A compile time check to ensure Warning implements the lnwire.TestMessage
// interface.
var _ TestMessage = (*Warning)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (c *Warning) RandTestMessage(t *rapid.T) Message {
msg := &Warning{
ChanID: RandChannelID(t),
}
useASCII := rapid.Bool().Draw(t, "useASCII")
if useASCII {
length := rapid.IntRange(1, 100).Draw(t, "warningDataLength")
data := make([]byte, length)
for i := 0; i < length; i++ {
data[i] = byte(
rapid.IntRange(32, 126).Draw(
t, fmt.Sprintf("warningDataByte-%d", i),
),
)
}
msg.Data = data
} else {
length := rapid.IntRange(1, 100).Draw(t, "warningDataLength")
msg.Data = rapid.SliceOfN(rapid.Byte(), length, length).Draw(
t, "warningData",
)
}
return msg
}
// A compile time check to ensure Error implements the lnwire.TestMessage
// interface.
var _ TestMessage = (*Error)(nil)
// RandTestMessage populates the message with random data suitable for testing.
// It uses the rapid testing framework to generate random values.
//
// This is part of the TestMessage interface.
func (c *Error) RandTestMessage(t *rapid.T) Message {
msg := &Error{
ChanID: RandChannelID(t),
}
useASCII := rapid.Bool().Draw(t, "useASCII")
if useASCII {
length := rapid.IntRange(1, 100).Draw(t, "errorDataLength")
data := make([]byte, length)
for i := 0; i < length; i++ {
data[i] = byte(
rapid.IntRange(32, 126).Draw(
t, fmt.Sprintf("errorDataByte-%d", i),
),
)
}
msg.Data = data
} else {
// Generate random binary data
length := rapid.IntRange(1, 100).Draw(t, "errorDataLength")
msg.Data = rapid.SliceOfN(
rapid.Byte(), length, length,
).Draw(t, "errorData")
}
return msg
}