lnwire: add local_nonces field to revoke_and_ack
What changed, and why it matters
This commit adds a new optional data field called local_nonces to a Lightning network control message (revoke_and_ack). It is part of the protocol plumbing for a feature called splice nonce coordination. There is no indication in the commit that this fixes a security bug; it appears to be a feature addition or protocol update.
Treat as a routine feature commit unless additional context shows it is part of a security fix. If reviewing for security, verify that LocalNonces parsing enforces size limits and that nonce values are validated before use in MuSig2 signing.
Security signals we found
New optional TLV field added to a channel control message
No input validation or bounds checks visible in the diff
No security relevance disclosed by the commit message or diff
Evidence from the diff
The change extends lnwire.RevokeAndAck with an optional TLV field LocalNonces (OptLocalNonces) that carries a map of MuSig2 local nonces keyed by transaction ID. Encode/Decode logic is updated to serialize/deserialize the new TLV, and the rapid test generator is updated to produce random instances. No validation, authorization, or cryptographic logic changes are visible in this diff.
Changed components
lnwire/revoke_and_ack.golnwire/test_message.goInspect captured patch +40 / −3
diff --git a/lnwire/revoke_and_ack.go b/lnwire/revoke_and_ack.go
index 3c9775c..676ac01 100644
--- a/lnwire/revoke_and_ack.go
+++ b/lnwire/revoke_and_ack.go
@@ -38,6 +38,10 @@ type RevokeAndAck struct {
// remote nonce and the sender's local nonce.
LocalNonce OptMusig2NonceTLV
+ // LocalNonces is an optional field that stores a map of local musig2
+ // nonces, keyed by TXID. This is used for splice nonce coordination.
+ LocalNonces OptLocalNonces
+
// ExtraData is the set of data that was appended to this message to
// fill out the full maximum transport message size. These fields can
// be used to specify optional data such as custom TLV fields.
@@ -78,8 +82,14 @@ func (c *RevokeAndAck) Decode(r io.Reader, pver uint32) error {
return err
}
- localNonce := c.LocalNonce.Zero()
- typeMap, err := tlvRecords.ExtractRecords(&localNonce)
+ var (
+ localNonce = c.LocalNonce.Zero()
+ localNoncesData LocalNoncesData
+ )
+
+ typeMap, err := tlvRecords.ExtractRecords(
+ &localNonce, &localNoncesData,
+ )
if err != nil {
return err
}
@@ -88,6 +98,9 @@ func (c *RevokeAndAck) Decode(r io.Reader, pver uint32) error {
if val, ok := typeMap[c.LocalNonce.TlvType()]; ok && val == nil {
c.LocalNonce = tlv.SomeRecordT(localNonce)
}
+ if val, ok := typeMap[(LocalNoncesRecordTypeDef)(nil).TypeVal()]; ok && val == nil {
+ c.LocalNonces = SomeLocalNonces(localNoncesData)
+ }
if len(tlvRecords) != 0 {
c.ExtraData = tlvRecords
@@ -101,10 +114,13 @@ func (c *RevokeAndAck) Decode(r io.Reader, pver uint32) error {
//
// This is part of the lnwire.Message interface.
func (c *RevokeAndAck) Encode(w *bytes.Buffer, pver uint32) error {
- recordProducers := make([]tlv.RecordProducer, 0, 1)
+ recordProducers := make([]tlv.RecordProducer, 0, 2)
c.LocalNonce.WhenSome(func(localNonce Musig2NonceTLV) {
recordProducers = append(recordProducers, &localNonce)
})
+ c.LocalNonces.WhenSome(func(ln LocalNoncesData) {
+ recordProducers = append(recordProducers, &ln)
+ })
err := EncodeMessageExtraData(&c.ExtraData, recordProducers...)
if err != nil {
return err
diff --git a/lnwire/test_message.go b/lnwire/test_message.go
index 0d95db2..5fee057 100644
--- a/lnwire/test_message.go
+++ b/lnwire/test_message.go
@@ -1854,6 +1854,27 @@ func (c *RevokeAndAck) RandTestMessage(t *rapid.T) Message {
)
}
+ if rapid.Bool().Draw(t, "includeLocalNonces") {
+ numNonces := rapid.IntRange(0, 3).Draw(t, "numLocalNonces")
+ nonces := make(map[chainhash.Hash]Musig2Nonce)
+ for i := 0; i < numNonces; i++ {
+ txid := RandChainHash(t)
+
+ // Ensure unique txids for the map.
+ for {
+ _, ok := nonces[txid]
+ if !ok {
+ break
+ }
+ txid = RandChainHash(t)
+ }
+
+ nonces[txid] = RandMusig2Nonce(t)
+ }
+
+ msg.LocalNonces = SomeLocalNonces(LocalNoncesData{NoncesMap: nonces})
+ }
+
return msg
}
Why this scored 11/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.