mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-04-07 03:28:05 +02:00
discovery: let handlAnnSig take lnwire.AnnounceSigs interface
This commit is contained in:
parent
c0b66d76df
commit
2767c4e8a5
@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
|
||||
"github.com/btcsuite/btcd/btcec/v2/schnorr/musig2"
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
@ -85,6 +86,7 @@ type optionalMsgFields struct {
|
||||
capacity *btcutil.Amount
|
||||
channelPoint *wire.OutPoint
|
||||
remoteAlias *lnwire.ShortChannelID
|
||||
aggNonce *btcec.PublicKey
|
||||
}
|
||||
|
||||
// apply applies the optional fields within the functional options.
|
||||
@ -115,6 +117,15 @@ func ChannelPoint(op wire.OutPoint) OptionalMsgField {
|
||||
}
|
||||
}
|
||||
|
||||
// AggregateNonce is an optional field that lets the gossiper know of the
|
||||
// aggregate nonce used in the construction of the channel announcement
|
||||
// signature.
|
||||
func AggregateNonce(nonce *btcec.PublicKey) OptionalMsgField {
|
||||
return func(f *optionalMsgFields) {
|
||||
f.aggNonce = nonce
|
||||
}
|
||||
}
|
||||
|
||||
// RemoteAlias is an optional field that lets the gossiper know that a locally
|
||||
// sent channel update is actually an update for the peer that should replace
|
||||
// the ShortChannelID field with the remote's alias. This is only used for
|
||||
@ -2088,7 +2099,7 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(
|
||||
// A new signature announcement has been received. This indicates
|
||||
// willingness of nodes involved in the funding of a channel to
|
||||
// announce this new channel to the rest of the world.
|
||||
case *lnwire.AnnounceSignatures1:
|
||||
case lnwire.AnnounceSignatures:
|
||||
return d.handleAnnSig(nMsg, msg)
|
||||
|
||||
default:
|
||||
@ -3293,27 +3304,28 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
|
||||
|
||||
// handleAnnSig processes a new announcement signatures message.
|
||||
func (d *AuthenticatedGossiper) handleAnnSig(nMsg *networkMsg,
|
||||
ann *lnwire.AnnounceSignatures1) ([]networkMsg, bool) {
|
||||
ann lnwire.AnnounceSignatures) ([]networkMsg, bool) {
|
||||
|
||||
needBlockHeight := ann.ShortChannelID.BlockHeight +
|
||||
d.cfg.ProofMatureDelta
|
||||
shortChanID := ann.ShortChannelID.ToUint64()
|
||||
var (
|
||||
scid = ann.SCID()
|
||||
chanID = ann.ChanID()
|
||||
)
|
||||
|
||||
needBlockHeight := scid.BlockHeight + d.cfg.ProofMatureDelta
|
||||
shortChanID := scid.ToUint64()
|
||||
|
||||
prefix := "local"
|
||||
if nMsg.isRemote {
|
||||
prefix = "remote"
|
||||
}
|
||||
|
||||
log.Infof("Received new %v announcement signature for %v", prefix,
|
||||
ann.ShortChannelID)
|
||||
log.Infof("Received new %v announcement signature for %v", prefix, scid)
|
||||
|
||||
// By the specification, channel announcement proofs should be sent
|
||||
// after some number of confirmations after channel was registered in
|
||||
// bitcoin blockchain. Therefore, we check if the proof is mature.
|
||||
d.Lock()
|
||||
premature := d.isPremature(
|
||||
ann.ShortChannelID, d.cfg.ProofMatureDelta, nMsg,
|
||||
)
|
||||
premature := d.isPremature(scid, d.cfg.ProofMatureDelta, nMsg)
|
||||
if premature {
|
||||
log.Warnf("Premature proof announcement, current block height"+
|
||||
"lower than needed: %v < %v", d.bestHeight,
|
||||
@ -3330,14 +3342,12 @@ func (d *AuthenticatedGossiper) handleAnnSig(nMsg *networkMsg,
|
||||
// We must acquire the mutex for this channel ID before getting the
|
||||
// channel from the database, to ensure what we read does not change
|
||||
// before we call AddProof() later.
|
||||
d.channelMtx.Lock(ann.ShortChannelID.ToUint64())
|
||||
defer d.channelMtx.Unlock(ann.ShortChannelID.ToUint64())
|
||||
d.channelMtx.Lock(scid.ToUint64())
|
||||
defer d.channelMtx.Unlock(scid.ToUint64())
|
||||
|
||||
chanInfo, e1, e2, err := d.cfg.Graph.GetChannelByID(
|
||||
ann.ShortChannelID,
|
||||
)
|
||||
chanInfo, e1, e2, err := d.cfg.Graph.GetChannelByID(scid)
|
||||
if err != nil {
|
||||
_, err = d.cfg.FindChannel(nMsg.source, ann.ChannelID)
|
||||
_, err = d.cfg.FindChannel(nMsg.source, chanID)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("unable to store the proof for "+
|
||||
"short_chan_id=%v: %v", shortChanID, err)
|
||||
@ -3347,19 +3357,37 @@ func (d *AuthenticatedGossiper) handleAnnSig(nMsg *networkMsg,
|
||||
return nil, false
|
||||
}
|
||||
|
||||
proof := channeldb.NewLegacyWaitingProof(nMsg.isRemote, ann)
|
||||
var proof *channeldb.WaitingProof
|
||||
switch a := ann.(type) {
|
||||
case *lnwire.AnnounceSignatures1:
|
||||
proof = channeldb.NewLegacyWaitingProof(
|
||||
nMsg.isRemote, a,
|
||||
)
|
||||
case *lnwire.AnnounceSignatures2:
|
||||
var aggNonce *btcec.PublicKey
|
||||
if nMsg.optionalMsgFields != nil {
|
||||
aggNonce = nMsg.optionalMsgFields.aggNonce
|
||||
}
|
||||
|
||||
proof = channeldb.NewTaprootWaitingProof(
|
||||
nMsg.isRemote, a, aggNonce,
|
||||
)
|
||||
}
|
||||
|
||||
err := d.cfg.WaitingProofStore.Add(proof)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("unable to store the proof for "+
|
||||
"short_chan_id=%v: %v", shortChanID, err)
|
||||
log.Error(err)
|
||||
nMsg.err <- err
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
log.Infof("Orphan %v proof announcement with short_chan_id=%v"+
|
||||
", adding to waiting batch", prefix, shortChanID)
|
||||
nMsg.err <- nil
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
@ -3401,15 +3429,15 @@ func (d *AuthenticatedGossiper) handleAnnSig(nMsg *networkMsg,
|
||||
if err != nil {
|
||||
err := fmt.Errorf("unable to reliably send %v for "+
|
||||
"channel=%v to peer=%x: %v", ann.MsgType(),
|
||||
ann.ShortChannelID, remotePubKey, err)
|
||||
scid, remotePubKey, err)
|
||||
nMsg.err <- err
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we already have the full proof for this channel.
|
||||
authInfo := chanInfo.GetAuthProof()
|
||||
if authInfo != nil {
|
||||
authProof := chanInfo.GetAuthProof()
|
||||
if authProof != nil {
|
||||
// If we already have the fully assembled proof, then the peer
|
||||
// sending us their proof has probably not received our local
|
||||
// proof yet. So be kind and send them the full proof.
|
||||
@ -3425,10 +3453,10 @@ func (d *AuthenticatedGossiper) handleAnnSig(nMsg *networkMsg,
|
||||
log.Debugf("Received half proof for channel "+
|
||||
"%v with existing full proof. Sending"+
|
||||
" full proof to peer=%x",
|
||||
ann.ChannelID, peerID)
|
||||
chanID, peerID)
|
||||
|
||||
ca, _, _, err := netann.CreateChanAnnouncement(
|
||||
authInfo, chanInfo, e1, e2,
|
||||
authProof, chanInfo, e1, e2,
|
||||
)
|
||||
if err != nil {
|
||||
log.Errorf("unable to gen ann: %v",
|
||||
@ -3444,12 +3472,12 @@ func (d *AuthenticatedGossiper) handleAnnSig(nMsg *networkMsg,
|
||||
}
|
||||
|
||||
log.Debugf("Full proof sent to peer=%x for "+
|
||||
"chanID=%v", peerID, ann.ChannelID)
|
||||
"chanID=%v", peerID, chanID)
|
||||
}()
|
||||
}
|
||||
|
||||
log.Debugf("Already have proof for channel with chanID=%v",
|
||||
ann.ChannelID)
|
||||
chanID)
|
||||
nMsg.err <- nil
|
||||
return nil, true
|
||||
}
|
||||
@ -3459,7 +3487,25 @@ func (d *AuthenticatedGossiper) handleAnnSig(nMsg *networkMsg,
|
||||
// announcement. If we didn't receive the opposite half of the proof
|
||||
// then we should store this one, and wait for the opposite to be
|
||||
// received.
|
||||
proof := channeldb.NewLegacyWaitingProof(nMsg.isRemote, ann)
|
||||
var (
|
||||
proof *channeldb.WaitingProof
|
||||
aggNonce *btcec.PublicKey
|
||||
)
|
||||
switch a := ann.(type) {
|
||||
case *lnwire.AnnounceSignatures1:
|
||||
proof = channeldb.NewLegacyWaitingProof(
|
||||
nMsg.isRemote, a,
|
||||
)
|
||||
case *lnwire.AnnounceSignatures2:
|
||||
if nMsg.optionalMsgFields != nil {
|
||||
aggNonce = nMsg.optionalMsgFields.aggNonce
|
||||
}
|
||||
|
||||
proof = channeldb.NewTaprootWaitingProof(
|
||||
nMsg.isRemote, a, aggNonce,
|
||||
)
|
||||
}
|
||||
|
||||
oppositeProof, err := d.cfg.WaitingProofStore.Get(proof.OppositeKey())
|
||||
if err != nil && err != channeldb.ErrWaitingProofNotFound {
|
||||
err := fmt.Errorf("unable to get the opposite proof for "+
|
||||
@ -3487,36 +3533,93 @@ func (d *AuthenticatedGossiper) handleAnnSig(nMsg *networkMsg,
|
||||
return nil, false
|
||||
}
|
||||
|
||||
oppProof, ok := oppositeProof.
|
||||
WaitingProofInterface.(*channeldb.LegacyWaitingProof)
|
||||
if !ok {
|
||||
nMsg.err <- fmt.Errorf("got wrong waiting proof type")
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// We now have both halves of the channel announcement proof, then
|
||||
// we'll reconstruct the initial announcement so we can validate it
|
||||
// shortly below.
|
||||
var dbProof models.ChannelAuthProof1
|
||||
if isFirstNode {
|
||||
dbProof.NodeSig1Bytes = ann.NodeSignature.ToSignatureBytes()
|
||||
dbProof.NodeSig2Bytes = oppProof.NodeSignature.ToSignatureBytes()
|
||||
dbProof.BitcoinSig1Bytes = ann.BitcoinSignature.ToSignatureBytes()
|
||||
dbProof.BitcoinSig2Bytes = oppProof.BitcoinSignature.ToSignatureBytes()
|
||||
} else {
|
||||
dbProof.NodeSig1Bytes = oppProof.NodeSignature.ToSignatureBytes()
|
||||
dbProof.NodeSig2Bytes = ann.NodeSignature.ToSignatureBytes()
|
||||
dbProof.BitcoinSig1Bytes = oppProof.BitcoinSignature.ToSignatureBytes()
|
||||
dbProof.BitcoinSig2Bytes = ann.BitcoinSignature.ToSignatureBytes()
|
||||
var dbProof models.ChannelAuthProof
|
||||
|
||||
switch oppProof := oppositeProof.WaitingProofInterface.(type) {
|
||||
case *channeldb.LegacyWaitingProof:
|
||||
a, ok := ann.(*lnwire.AnnounceSignatures1)
|
||||
if !ok {
|
||||
err := fmt.Errorf("expected "+
|
||||
"*lnwire.AnnouncementSignatures1, got: %T", ann)
|
||||
|
||||
log.Error(err)
|
||||
nMsg.err <- err
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
var (
|
||||
dbProof1 models.ChannelAuthProof1
|
||||
nodeSig = a.NodeSignature.ToSignatureBytes()
|
||||
btcSig = a.BitcoinSignature.ToSignatureBytes()
|
||||
oppNodeSig = oppProof.NodeSignature.ToSignatureBytes()
|
||||
oppBtcSig = oppProof.BitcoinSignature.
|
||||
ToSignatureBytes()
|
||||
)
|
||||
if isFirstNode {
|
||||
dbProof1.NodeSig1Bytes = nodeSig
|
||||
dbProof1.NodeSig2Bytes = oppNodeSig
|
||||
dbProof1.BitcoinSig1Bytes = btcSig
|
||||
dbProof1.BitcoinSig2Bytes = oppBtcSig
|
||||
} else {
|
||||
dbProof1.NodeSig1Bytes = oppNodeSig
|
||||
dbProof1.NodeSig2Bytes = nodeSig
|
||||
dbProof1.BitcoinSig1Bytes = oppBtcSig
|
||||
dbProof1.BitcoinSig2Bytes = btcSig
|
||||
}
|
||||
dbProof = &dbProof1
|
||||
|
||||
case *channeldb.TaprootWaitingProof:
|
||||
a, ok := ann.(*lnwire.AnnounceSignatures2)
|
||||
if !ok {
|
||||
err := fmt.Errorf("expected "+
|
||||
"*lnwire.AnnouncementSignatures2, got: %T", ann)
|
||||
log.Error(err)
|
||||
nMsg.err <- err
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// First, combine the two partial sigs to get the final sig. At
|
||||
// least one of proofs should have an agg nonce.
|
||||
switch {
|
||||
case aggNonce != nil:
|
||||
case oppProof.AggNonce != nil:
|
||||
aggNonce = oppProof.AggNonce
|
||||
default:
|
||||
nMsg.err <- fmt.Errorf("didnt get an agg nonce")
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
ps1 := musig2.NewPartialSignature(
|
||||
&a.PartialSignature.Sig, aggNonce,
|
||||
)
|
||||
|
||||
ps2 := musig2.NewPartialSignature(
|
||||
&oppProof.PartialSignature.Sig, aggNonce,
|
||||
)
|
||||
|
||||
// Now aggregate the partial sigs.
|
||||
s := musig2.CombineSigs(
|
||||
aggNonce, []*musig2.PartialSignature{&ps1, &ps2},
|
||||
)
|
||||
|
||||
dbProof = &models.ChannelAuthProof2{
|
||||
SchnorrSigBytes: s.Serialize(),
|
||||
}
|
||||
}
|
||||
|
||||
chanAnn, e1Ann, e2Ann, err := netann.CreateChanAnnouncement(
|
||||
&dbProof, chanInfo, e1, e2,
|
||||
dbProof, chanInfo, e1, e2,
|
||||
)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
nMsg.err <- err
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
@ -3537,10 +3640,10 @@ func (d *AuthenticatedGossiper) handleAnnSig(nMsg *networkMsg,
|
||||
// attest to the bitcoin keys by validating the signatures of
|
||||
// announcement. If proof is valid then we'll populate the channel edge
|
||||
// with it, so we can announce it on peer connect.
|
||||
err = d.cfg.Graph.AddProof(ann.ShortChannelID, &dbProof)
|
||||
err = d.cfg.Graph.AddProof(scid, dbProof)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("unable add proof to the channel chanID=%v:"+
|
||||
" %v", ann.ChannelID, err)
|
||||
" %v", chanID, err)
|
||||
log.Error(err)
|
||||
nMsg.err <- err
|
||||
return nil, false
|
||||
@ -3549,7 +3652,7 @@ func (d *AuthenticatedGossiper) handleAnnSig(nMsg *networkMsg,
|
||||
err = d.cfg.WaitingProofStore.Remove(proof.OppositeKey())
|
||||
if err != nil {
|
||||
err := fmt.Errorf("unable to remove opposite proof for the "+
|
||||
"channel with chanID=%v: %v", ann.ChannelID, err)
|
||||
"channel with chanID=%v: %v", chanID, err)
|
||||
log.Error(err)
|
||||
nMsg.err <- err
|
||||
return nil, false
|
||||
|
Loading…
x
Reference in New Issue
Block a user