mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-05-29 17:19:33 +02:00
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.
1670 lines
47 KiB
Go
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
|
|
}
|