Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions channeldb/waitingproof_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ func TestWaitingProofV2RoundTrip(t *testing.T) {
annSig2 := lnwire.NewAnnSigs2(
lnwire.ChannelID{1, 2, 3},
lnwire.NewShortChanIDFromInt(42),
partialSig,
lnwire.NewAnnouncementSigPair(partialSig.Sig, partialSig.Sig),
[32]byte{1, 2, 3},
)

// Generate a deterministic public key for the combined nonce.
Expand Down Expand Up @@ -207,7 +208,8 @@ func TestWaitingProofV2Store(t *testing.T) {
annSig2 := lnwire.NewAnnSigs2(
lnwire.ChannelID{5, 6, 7},
lnwire.NewShortChanIDFromInt(100),
partialSig,
lnwire.NewAnnouncementSigPair(partialSig.Sig, partialSig.Sig),
[32]byte{5, 6, 7},
)

proof := NewV2WaitingProof(true, annSig2, pubKey)
Expand Down Expand Up @@ -253,7 +255,8 @@ func TestWaitingProofCrossVersionKeyIsolation(t *testing.T) {
v2AnnSig := lnwire.NewAnnSigs2(
lnwire.ChannelID{9, 9, 9},
scid,
partialSig,
lnwire.NewAnnouncementSigPair(partialSig.Sig, partialSig.Sig),
[32]byte{9, 9, 9},
)
v2Proof := NewV2WaitingProof(true, v2AnnSig, pubKey)

Expand Down
18 changes: 18 additions & 0 deletions docs/release-notes/release-notes-0.22.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,24 @@
later in the reservation flow as a funder-balance-dust error; they now
surface a clearer, spec-aligned error string up front.

* The gossip v2 wire messages in `lnwire`
([#10837](https://github.com/lightningnetwork/lnd/pull/10837)) have been
pulled in line with the BOLT taproot-gossip extension
([lightning/bolts#1059](https://github.com/lightning/bolts/pull/1059)):
signature TLVs move from type 160 to 240 (with the signed TLV range
widening from `0..=159` to `0..=239` to match BOLT 12); each gossip v2
reader now rejects messages missing any compulsory field; the
port-not-zero rule on `node_announcement_2` now also covers
`tor_v3_address`; `gossip_timestamp_filter`'s two block-height TLVs
collapse into a single `block_height_range` TLV;
`announcement_signatures_2` gains a required `funding_txid` TLV and
now carries two raw MuSig2 partial signatures (64 bytes) rather than a
single pre-aggregated 32-byte value; `channel_update_2`'s experimental
inbound-fee TLV is replaced with two properly typed `tu32` records at
types 20/22, and its `short_channel_id` now uses the `sciddir` form of
BOLT 1's `sciddir_or_pubkey` (the previous `second_peer` TLV is gone,
with direction folded into the leading dir byte).

## Testing

## Database
Expand Down
19 changes: 17 additions & 2 deletions graph/db/models/channel_edge_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,27 @@ func ChanEdgePolicyFromWire(scid uint64,
}, nil

case *lnwire.ChannelUpdate2:
// Inbound fees in gossip v2 are two uint32 TLVs that are
// suppressed on the wire when they take their default value
// of 0 (i.e. no inbound surcharge). Treat the both-zero case
// as "no inbound fee" so the downstream Option semantics
// still hold.
var inboundFee fn.Option[lnwire.Fee]
baseFee := upd.InboundFeeBaseMsat.Val
propFee := upd.InboundFeeProportionalMillionths.Val
if baseFee != 0 || propFee != 0 {
inboundFee = fn.Some(lnwire.Fee{
BaseFee: int32(baseFee),
FeeRate: int32(propFee),
})
}

return &ChannelEdgePolicy{
Version: lnwire.GossipVersion2,
SigBytes: upd.Signature.Val.ToSignatureBytes(),
ChannelID: scid,
LastBlockHeight: upd.BlockHeight.Val,
SecondPeer: upd.SecondPeer.IsSome(),
SecondPeer: !upd.IsNode1(),
DisableFlags: upd.DisabledFlags.Val,
TimeLockDelta: upd.CLTVExpiryDelta.Val,
MinHTLC: upd.HTLCMinimumMsat.Val,
Expand All @@ -140,7 +155,7 @@ func ChanEdgePolicyFromWire(scid uint64,
FeeProportionalMillionths: lnwire.MilliSatoshi(
upd.FeeProportionalMillionths.Val,
),
InboundFee: upd.InboundFee.ValOpt(),
InboundFee: inboundFee,
ExtraSignedFields: upd.ExtraSignedFields,
}, nil
}
Expand Down
42 changes: 33 additions & 9 deletions lnwire/announcement_signatures_2.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,19 @@ type AnnounceSignatures2 struct {
// index which pays to the channel.
ShortChannelID tlv.RecordT[tlv.TlvType2, ShortChannelID]

// PartialSignature is the combination of the partial Schnorr signature
// created for the node's bitcoin key with the partial signature created
// for the node's node ID key.
PartialSignature tlv.RecordT[tlv.TlvType4, PartialSig]
// PartialSignatures carries the two raw musig2 partial signatures
// produced by the sender (one with its node_id key, one with its
// bitcoin key), concatenated as `node || bitcoin` (64 bytes total).
// The receiver verifies each half independently with the standard
// MuSig2 partial-sig verify routine.
PartialSignatures tlv.RecordT[tlv.TlvType4, AnnouncementSigPair]

// FundingTxID is the txid of the funding transaction that this
// announcement signature covers. For an initial channel announcement
// this is the original funding transaction; for a spliced channel it
// is the txid of the splice transaction whose splice_locked triggered
// the new round of announcement signing.
FundingTxID tlv.RecordT[tlv.TlvType6, [32]byte]

// Any extra fields in the signed range that we do not yet know about,
// but we need to keep them for signature validation and to produce a
Expand All @@ -38,15 +47,19 @@ type AnnounceSignatures2 struct {

// NewAnnSigs2 is a constructor for AnnounceSignatures2.
func NewAnnSigs2(chanID ChannelID, scid ShortChannelID,
partialSig PartialSig) *AnnounceSignatures2 {
sigs AnnouncementSigPair,
fundingTxID [32]byte) *AnnounceSignatures2 {

return &AnnounceSignatures2{
ChannelID: tlv.NewRecordT[tlv.TlvType0, ChannelID](chanID),
ShortChannelID: tlv.NewRecordT[tlv.TlvType2, ShortChannelID](
scid,
),
PartialSignature: tlv.NewRecordT[tlv.TlvType4, PartialSig](
partialSig,
PartialSignatures: tlv.NewRecordT[
tlv.TlvType4, AnnouncementSigPair,
](sigs),
FundingTxID: tlv.NewPrimitiveRecord[tlv.TlvType6, [32]byte](
fundingTxID,
),
ExtraSignedFields: make(ExtraSignedFields),
}
Expand All @@ -70,7 +83,8 @@ var _ PureTLVMessage = (*AnnounceSignatures2)(nil)
// This is part of the lnwire.Message interface.
func (a *AnnounceSignatures2) Decode(r io.Reader, _ uint32) error {
stream, err := tlv.NewStream(ProduceRecordsSorted(
&a.ChannelID, &a.ShortChannelID, &a.PartialSignature,
&a.ChannelID, &a.ShortChannelID, &a.PartialSignatures,
&a.FundingTxID,
)...)
if err != nil {
return err
Expand All @@ -81,6 +95,16 @@ func (a *AnnounceSignatures2) Decode(r io.Reader, _ uint32) error {
return err
}

if err := AssertRequiredPresent(
typeMap,
a.ChannelID.TlvType(),
a.ShortChannelID.TlvType(),
a.PartialSignatures.TlvType(),
a.FundingTxID.TlvType(),
); err != nil {
return err
}

a.ExtraSignedFields = ExtraSignedFieldsFromTypeMap(typeMap)

return nil
Expand Down Expand Up @@ -124,7 +148,7 @@ func (a *AnnounceSignatures2) SerializedSize() (uint32, error) {
func (a *AnnounceSignatures2) AllRecords() []tlv.Record {
recordProducers := []tlv.RecordProducer{
&a.ChannelID, &a.ShortChannelID,
&a.PartialSignature,
&a.PartialSignatures, &a.FundingTxID,
}

recordProducers = append(recordProducers, RecordsAsProducers(
Expand Down
9 changes: 8 additions & 1 deletion lnwire/announcement_signatures_2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,16 @@ func TestAnnSigs2EncodeDecode(t *testing.T) {
0, 0, 1, 0, 0, 2, 0, 3, // value
}...)

// PartialSignature.
// PartialSignatures (node || bitcoin, 64 bytes total).
rawBytes = append(rawBytes, []byte{
0x04, // type
0x40, // length
}...)
rawBytes = append(rawBytes, make([]byte, 64)...) // value

// FundingTxID.
rawBytes = append(rawBytes, []byte{
0x06, // type
0x20, // length
}...)
rawBytes = append(rawBytes, make([]byte, 32)...) // value
Expand Down
14 changes: 13 additions & 1 deletion lnwire/channel_announcement_2.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ type ChannelAnnouncement2 struct {

// Signature is a Schnorr signature over serialised signed-range TLV
// stream of the message.
Signature tlv.RecordT[tlv.TlvType160, Sig]
Signature tlv.RecordT[tlv.TlvType240, Sig]

// Any extra fields in the signed range that we do not yet know about,
// but we need to keep them for signature validation and to produce a
Expand Down Expand Up @@ -166,6 +166,18 @@ func (c *ChannelAnnouncement2) Decode(r io.Reader, _ uint32) error {
return err
}

if err := AssertRequiredPresent(
typeMap,
c.ShortChannelID.TlvType(),
c.Outpoint.TlvType(),
c.Capacity.TlvType(),
c.NodeID1.TlvType(),
c.NodeID2.TlvType(),
c.Signature.TlvType(),
); err != nil {
return err
}

// By default, the chain-hash is the bitcoin mainnet genesis block hash.
c.ChainHash.Val = *chaincfg.MainNetParams.GenesisHash
if _, ok := typeMap[c.ChainHash.TlvType()]; ok {
Expand Down
2 changes: 1 addition & 1 deletion lnwire/channel_announcement_2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func TestChanAnn2EncodeDecode(t *testing.T) {
0x79, 0x79, // value.

// Signature.
0xa0, // type.
0xf0, // type.
0x40, // length.
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb,
0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
Expand Down
Loading
Loading