mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-01-19 05:45:21 +01:00
discovery: move ann sig handling to handleAnnSig
This commit is contained in:
parent
1e9220dab6
commit
932c5f1a7b
@ -1758,10 +1758,7 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(
|
|||||||
schedulerOp = append(schedulerOp, batch.LazyAdd())
|
schedulerOp = append(schedulerOp, batch.LazyAdd())
|
||||||
}
|
}
|
||||||
|
|
||||||
var announcements []networkMsg
|
|
||||||
|
|
||||||
switch msg := nMsg.msg.(type) {
|
switch msg := nMsg.msg.(type) {
|
||||||
|
|
||||||
// A new node announcement has arrived which either presents new
|
// A new node announcement has arrived which either presents new
|
||||||
// information about a node in one of the channels we know about, or a
|
// information about a node in one of the channels we know about, or a
|
||||||
// updating previously advertised information.
|
// updating previously advertised information.
|
||||||
@ -1785,324 +1782,7 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(
|
|||||||
// willingness of nodes involved in the funding of a channel to
|
// willingness of nodes involved in the funding of a channel to
|
||||||
// announce this new channel to the rest of the world.
|
// announce this new channel to the rest of the world.
|
||||||
case *lnwire.AnnounceSignatures:
|
case *lnwire.AnnounceSignatures:
|
||||||
needBlockHeight := msg.ShortChannelID.BlockHeight +
|
return d.handleAnnSig(nMsg, msg)
|
||||||
d.cfg.ProofMatureDelta
|
|
||||||
shortChanID := msg.ShortChannelID.ToUint64()
|
|
||||||
|
|
||||||
prefix := "local"
|
|
||||||
if nMsg.isRemote {
|
|
||||||
prefix = "remote"
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("Received new %v channel announcement for %v", prefix,
|
|
||||||
msg.ShortChannelID)
|
|
||||||
|
|
||||||
// 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 premature.
|
|
||||||
d.Lock()
|
|
||||||
premature := d.isPremature(
|
|
||||||
msg.ShortChannelID, d.cfg.ProofMatureDelta, nMsg,
|
|
||||||
)
|
|
||||||
if premature {
|
|
||||||
log.Warnf("Premature proof announcement, current "+
|
|
||||||
"block height lower than needed: %v < %v",
|
|
||||||
d.bestHeight, needBlockHeight)
|
|
||||||
d.Unlock()
|
|
||||||
nMsg.err <- nil
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
d.Unlock()
|
|
||||||
|
|
||||||
// Ensure that we know of a channel with the target channel ID
|
|
||||||
// before proceeding further.
|
|
||||||
//
|
|
||||||
// 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(msg.ShortChannelID.ToUint64())
|
|
||||||
defer d.channelMtx.Unlock(msg.ShortChannelID.ToUint64())
|
|
||||||
|
|
||||||
chanInfo, e1, e2, err := d.cfg.Router.GetChannelByID(
|
|
||||||
msg.ShortChannelID)
|
|
||||||
if err != nil {
|
|
||||||
// TODO(andrew.shvv) this is dangerous because remote
|
|
||||||
// node might rewrite the waiting proof.
|
|
||||||
proof := channeldb.NewWaitingProof(nMsg.isRemote, msg)
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
nodeID := nMsg.source.SerializeCompressed()
|
|
||||||
isFirstNode := bytes.Equal(nodeID, chanInfo.NodeKey1Bytes[:])
|
|
||||||
isSecondNode := bytes.Equal(nodeID, chanInfo.NodeKey2Bytes[:])
|
|
||||||
|
|
||||||
// Ensure that channel that was retrieved belongs to the peer
|
|
||||||
// which sent the proof announcement.
|
|
||||||
if !(isFirstNode || isSecondNode) {
|
|
||||||
err := fmt.Errorf("channel that was received not "+
|
|
||||||
"belongs to the peer which sent the proof, "+
|
|
||||||
"short_chan_id=%v", shortChanID)
|
|
||||||
log.Error(err)
|
|
||||||
nMsg.err <- err
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// If proof was sent by a local sub-system, then we'll
|
|
||||||
// send the announcement signature to the remote node
|
|
||||||
// so they can also reconstruct the full channel
|
|
||||||
// announcement.
|
|
||||||
if !nMsg.isRemote {
|
|
||||||
var remotePubKey [33]byte
|
|
||||||
if isFirstNode {
|
|
||||||
remotePubKey = chanInfo.NodeKey2Bytes
|
|
||||||
} else {
|
|
||||||
remotePubKey = chanInfo.NodeKey1Bytes
|
|
||||||
}
|
|
||||||
// Since the remote peer might not be online
|
|
||||||
// we'll call a method that will attempt to
|
|
||||||
// deliver the proof when it comes online.
|
|
||||||
err := d.reliableSender.sendMessage(msg, remotePubKey)
|
|
||||||
if err != nil {
|
|
||||||
err := fmt.Errorf("unable to reliably send %v "+
|
|
||||||
"for channel=%v to peer=%x: %v",
|
|
||||||
msg.MsgType(), msg.ShortChannelID,
|
|
||||||
remotePubKey, err)
|
|
||||||
nMsg.err <- err
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we already have the full proof for this channel.
|
|
||||||
if chanInfo.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.
|
|
||||||
if nMsg.isRemote {
|
|
||||||
peerID := nMsg.source.SerializeCompressed()
|
|
||||||
log.Debugf("Got AnnounceSignatures for " +
|
|
||||||
"channel with full proof.")
|
|
||||||
|
|
||||||
d.wg.Add(1)
|
|
||||||
go func() {
|
|
||||||
defer d.wg.Done()
|
|
||||||
log.Debugf("Received half proof for "+
|
|
||||||
"channel %v with existing "+
|
|
||||||
"full proof. Sending full "+
|
|
||||||
"proof to peer=%x",
|
|
||||||
msg.ChannelID,
|
|
||||||
peerID)
|
|
||||||
|
|
||||||
chanAnn, _, _, err := netann.CreateChanAnnouncement(
|
|
||||||
chanInfo.AuthProof, chanInfo,
|
|
||||||
e1, e2,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("unable to gen "+
|
|
||||||
"ann: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = nMsg.peer.SendMessage(
|
|
||||||
false, chanAnn,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("Failed sending "+
|
|
||||||
"full proof to "+
|
|
||||||
"peer=%x: %v",
|
|
||||||
peerID, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.Debugf("Full proof sent to peer=%x"+
|
|
||||||
" for chanID=%v", peerID,
|
|
||||||
msg.ChannelID)
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debugf("Already have proof for channel "+
|
|
||||||
"with chanID=%v", msg.ChannelID)
|
|
||||||
nMsg.err <- nil
|
|
||||||
return nil, true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that we received the opposite proof. If so, then we're
|
|
||||||
// now able to construct the full proof, and create the channel
|
|
||||||
// announcement. If we didn't receive the opposite half of the
|
|
||||||
// proof than we should store it this one, and wait for
|
|
||||||
// opposite to be received.
|
|
||||||
proof := channeldb.NewWaitingProof(nMsg.isRemote, msg)
|
|
||||||
oppositeProof, err := d.cfg.WaitingProofStore.Get(
|
|
||||||
proof.OppositeKey(),
|
|
||||||
)
|
|
||||||
if err != nil && err != channeldb.ErrWaitingProofNotFound {
|
|
||||||
err := fmt.Errorf("unable to get "+
|
|
||||||
"the opposite proof for short_chan_id=%v: %v",
|
|
||||||
shortChanID, err)
|
|
||||||
log.Error(err)
|
|
||||||
nMsg.err <- err
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
if err == channeldb.ErrWaitingProofNotFound {
|
|
||||||
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("1/2 of channel ann proof received for "+
|
|
||||||
"short_chan_id=%v, waiting for other half",
|
|
||||||
shortChanID)
|
|
||||||
|
|
||||||
nMsg.err <- nil
|
|
||||||
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 channeldb.ChannelAuthProof
|
|
||||||
if isFirstNode {
|
|
||||||
dbProof.NodeSig1Bytes = msg.NodeSignature.ToSignatureBytes()
|
|
||||||
dbProof.NodeSig2Bytes = oppositeProof.NodeSignature.ToSignatureBytes()
|
|
||||||
dbProof.BitcoinSig1Bytes = msg.BitcoinSignature.ToSignatureBytes()
|
|
||||||
dbProof.BitcoinSig2Bytes = oppositeProof.BitcoinSignature.ToSignatureBytes()
|
|
||||||
} else {
|
|
||||||
dbProof.NodeSig1Bytes = oppositeProof.NodeSignature.ToSignatureBytes()
|
|
||||||
dbProof.NodeSig2Bytes = msg.NodeSignature.ToSignatureBytes()
|
|
||||||
dbProof.BitcoinSig1Bytes = oppositeProof.BitcoinSignature.ToSignatureBytes()
|
|
||||||
dbProof.BitcoinSig2Bytes = msg.BitcoinSignature.ToSignatureBytes()
|
|
||||||
}
|
|
||||||
chanAnn, e1Ann, e2Ann, err := netann.CreateChanAnnouncement(
|
|
||||||
&dbProof, chanInfo, e1, e2,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
nMsg.err <- err
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// With all the necessary components assembled validate the
|
|
||||||
// full channel announcement proof.
|
|
||||||
if err := routing.ValidateChannelAnn(chanAnn); err != nil {
|
|
||||||
err := fmt.Errorf("channel announcement proof "+
|
|
||||||
"for short_chan_id=%v isn't valid: %v",
|
|
||||||
shortChanID, err)
|
|
||||||
|
|
||||||
log.Error(err)
|
|
||||||
nMsg.err <- err
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the channel was returned by the router it means that
|
|
||||||
// existence of funding point and inclusion of nodes bitcoin
|
|
||||||
// keys in it already checked by the router. In this stage we
|
|
||||||
// should check that node keys are 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.Router.AddProof(msg.ShortChannelID, &dbProof)
|
|
||||||
if err != nil {
|
|
||||||
err := fmt.Errorf("unable add proof to the "+
|
|
||||||
"channel chanID=%v: %v", msg.ChannelID, err)
|
|
||||||
log.Error(err)
|
|
||||||
nMsg.err <- err
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
err = d.cfg.WaitingProofStore.Remove(proof.OppositeKey())
|
|
||||||
if err != nil {
|
|
||||||
err := fmt.Errorf("unable remove opposite proof "+
|
|
||||||
"for the channel with chanID=%v: %v",
|
|
||||||
msg.ChannelID, err)
|
|
||||||
log.Error(err)
|
|
||||||
nMsg.err <- err
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Proof was successfully created and now can announce the
|
|
||||||
// channel to the remain network.
|
|
||||||
log.Infof("Fully valid channel proof for short_chan_id=%v "+
|
|
||||||
"constructed, adding to next ann batch",
|
|
||||||
shortChanID)
|
|
||||||
|
|
||||||
// Assemble the necessary announcements to add to the next
|
|
||||||
// broadcasting batch.
|
|
||||||
announcements = append(announcements, networkMsg{
|
|
||||||
peer: nMsg.peer,
|
|
||||||
source: nMsg.source,
|
|
||||||
msg: chanAnn,
|
|
||||||
})
|
|
||||||
if src, err := chanInfo.NodeKey1(); err == nil && e1Ann != nil {
|
|
||||||
announcements = append(announcements, networkMsg{
|
|
||||||
peer: nMsg.peer,
|
|
||||||
source: src,
|
|
||||||
msg: e1Ann,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if src, err := chanInfo.NodeKey2(); err == nil && e2Ann != nil {
|
|
||||||
announcements = append(announcements, networkMsg{
|
|
||||||
peer: nMsg.peer,
|
|
||||||
source: src,
|
|
||||||
msg: e2Ann,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// We'll also send along the node announcements for each channel
|
|
||||||
// participant if we know of them. To ensure our node
|
|
||||||
// announcement propagates to our channel counterparty, we'll
|
|
||||||
// set the source for each announcement to the node it belongs
|
|
||||||
// to, otherwise we won't send it since the source gets skipped.
|
|
||||||
// This isn't necessary for channel updates and announcement
|
|
||||||
// signatures since we send those directly to our channel
|
|
||||||
// counterparty through the gossiper's reliable sender.
|
|
||||||
node1Ann, err := d.fetchNodeAnn(chanInfo.NodeKey1Bytes)
|
|
||||||
if err != nil {
|
|
||||||
log.Debugf("Unable to fetch node announcement for "+
|
|
||||||
"%x: %v", chanInfo.NodeKey1Bytes, err)
|
|
||||||
} else {
|
|
||||||
if nodeKey1, err := chanInfo.NodeKey1(); err == nil {
|
|
||||||
announcements = append(announcements, networkMsg{
|
|
||||||
peer: nMsg.peer,
|
|
||||||
source: nodeKey1,
|
|
||||||
msg: node1Ann,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
node2Ann, err := d.fetchNodeAnn(chanInfo.NodeKey2Bytes)
|
|
||||||
if err != nil {
|
|
||||||
log.Debugf("Unable to fetch node announcement for "+
|
|
||||||
"%x: %v", chanInfo.NodeKey2Bytes, err)
|
|
||||||
} else {
|
|
||||||
if nodeKey2, err := chanInfo.NodeKey2(); err == nil {
|
|
||||||
announcements = append(announcements, networkMsg{
|
|
||||||
peer: nMsg.peer,
|
|
||||||
source: nodeKey2,
|
|
||||||
msg: node2Ann,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nMsg.err <- nil
|
|
||||||
return announcements, true
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
err := errors.New("wrong type of the announcement")
|
err := errors.New("wrong type of the announcement")
|
||||||
@ -2978,3 +2658,309 @@ func (d *AuthenticatedGossiper) handleChanUpdate(nMsg *networkMsg,
|
|||||||
nMsg.err <- nil
|
nMsg.err <- nil
|
||||||
return announcements, true
|
return announcements, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handleAnnSig processes a new announcement signatures message.
|
||||||
|
func (d *AuthenticatedGossiper) handleAnnSig(nMsg *networkMsg,
|
||||||
|
ann *lnwire.AnnounceSignatures) ([]networkMsg, bool) {
|
||||||
|
|
||||||
|
needBlockHeight := ann.ShortChannelID.BlockHeight +
|
||||||
|
d.cfg.ProofMatureDelta
|
||||||
|
shortChanID := ann.ShortChannelID.ToUint64()
|
||||||
|
|
||||||
|
prefix := "local"
|
||||||
|
if nMsg.isRemote {
|
||||||
|
prefix = "remote"
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("Received new %v channel announcement for %v", prefix,
|
||||||
|
ann.ShortChannelID)
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
)
|
||||||
|
if premature {
|
||||||
|
log.Warnf("Premature proof announcement, current block height"+
|
||||||
|
"lower than needed: %v < %v", d.bestHeight,
|
||||||
|
needBlockHeight)
|
||||||
|
d.Unlock()
|
||||||
|
nMsg.err <- nil
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
d.Unlock()
|
||||||
|
|
||||||
|
// Ensure that we know of a channel with the target channel ID before
|
||||||
|
// proceeding further.
|
||||||
|
//
|
||||||
|
// 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())
|
||||||
|
|
||||||
|
chanInfo, e1, e2, err := d.cfg.Router.GetChannelByID(
|
||||||
|
ann.ShortChannelID,
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
proof := channeldb.NewWaitingProof(nMsg.isRemote, ann)
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeID := nMsg.source.SerializeCompressed()
|
||||||
|
isFirstNode := bytes.Equal(nodeID, chanInfo.NodeKey1Bytes[:])
|
||||||
|
isSecondNode := bytes.Equal(nodeID, chanInfo.NodeKey2Bytes[:])
|
||||||
|
|
||||||
|
// Ensure that channel that was retrieved belongs to the peer which
|
||||||
|
// sent the proof announcement.
|
||||||
|
if !(isFirstNode || isSecondNode) {
|
||||||
|
err := fmt.Errorf("channel that was received doesn't belong "+
|
||||||
|
"to the peer which sent the proof, short_chan_id=%v",
|
||||||
|
shortChanID)
|
||||||
|
log.Error(err)
|
||||||
|
nMsg.err <- err
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// If proof was sent by a local sub-system, then we'll send the
|
||||||
|
// announcement signature to the remote node so they can also
|
||||||
|
// reconstruct the full channel announcement.
|
||||||
|
if !nMsg.isRemote {
|
||||||
|
var remotePubKey [33]byte
|
||||||
|
if isFirstNode {
|
||||||
|
remotePubKey = chanInfo.NodeKey2Bytes
|
||||||
|
} else {
|
||||||
|
remotePubKey = chanInfo.NodeKey1Bytes
|
||||||
|
}
|
||||||
|
// Since the remote peer might not be online we'll call a
|
||||||
|
// method that will attempt to deliver the proof when it comes
|
||||||
|
// online.
|
||||||
|
err := d.reliableSender.sendMessage(ann, remotePubKey)
|
||||||
|
if err != nil {
|
||||||
|
err := fmt.Errorf("unable to reliably send %v for "+
|
||||||
|
"channel=%v to peer=%x: %v", ann.MsgType(),
|
||||||
|
ann.ShortChannelID, remotePubKey, err)
|
||||||
|
nMsg.err <- err
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we already have the full proof for this channel.
|
||||||
|
if chanInfo.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.
|
||||||
|
if nMsg.isRemote {
|
||||||
|
peerID := nMsg.source.SerializeCompressed()
|
||||||
|
log.Debugf("Got AnnounceSignatures for channel with " +
|
||||||
|
"full proof.")
|
||||||
|
|
||||||
|
d.wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer d.wg.Done()
|
||||||
|
log.Debugf("Received half proof for channel "+
|
||||||
|
"%v with existing full proof. Sending"+
|
||||||
|
" full proof to peer=%x",
|
||||||
|
ann.ChannelID, peerID)
|
||||||
|
|
||||||
|
ca, _, _, err := netann.CreateChanAnnouncement(
|
||||||
|
chanInfo.AuthProof, chanInfo, e1, e2,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("unable to gen ann: %v",
|
||||||
|
err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = nMsg.peer.SendMessage(false, ca)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Failed sending full proof"+
|
||||||
|
" to peer=%x: %v", peerID, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debugf("Full proof sent to peer=%x for "+
|
||||||
|
"chanID=%v", peerID, ann.ChannelID)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debugf("Already have proof for channel with chanID=%v",
|
||||||
|
ann.ChannelID)
|
||||||
|
nMsg.err <- nil
|
||||||
|
return nil, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that we received the opposite proof. If so, then we're now
|
||||||
|
// able to construct the full proof, and create the channel
|
||||||
|
// 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.NewWaitingProof(nMsg.isRemote, ann)
|
||||||
|
oppProof, err := d.cfg.WaitingProofStore.Get(proof.OppositeKey())
|
||||||
|
if err != nil && err != channeldb.ErrWaitingProofNotFound {
|
||||||
|
err := fmt.Errorf("unable to get the opposite proof for "+
|
||||||
|
"short_chan_id=%v: %v", shortChanID, err)
|
||||||
|
log.Error(err)
|
||||||
|
nMsg.err <- err
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == channeldb.ErrWaitingProofNotFound {
|
||||||
|
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("1/2 of channel ann proof received for "+
|
||||||
|
"short_chan_id=%v, waiting for other half",
|
||||||
|
shortChanID)
|
||||||
|
|
||||||
|
nMsg.err <- nil
|
||||||
|
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 channeldb.ChannelAuthProof
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
|
||||||
|
chanAnn, e1Ann, e2Ann, err := netann.CreateChanAnnouncement(
|
||||||
|
&dbProof, chanInfo, e1, e2,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
nMsg.err <- err
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// With all the necessary components assembled validate the full
|
||||||
|
// channel announcement proof.
|
||||||
|
if err := routing.ValidateChannelAnn(chanAnn); err != nil {
|
||||||
|
err := fmt.Errorf("channel announcement proof for "+
|
||||||
|
"short_chan_id=%v isn't valid: %v", shortChanID, err)
|
||||||
|
|
||||||
|
log.Error(err)
|
||||||
|
nMsg.err <- err
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the channel was returned by the router it means that existence of
|
||||||
|
// funding point and inclusion of nodes bitcoin keys in it already
|
||||||
|
// checked by the router. In this stage we should check that node keys
|
||||||
|
// 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.Router.AddProof(ann.ShortChannelID, &dbProof)
|
||||||
|
if err != nil {
|
||||||
|
err := fmt.Errorf("unable add proof to the channel chanID=%v:"+
|
||||||
|
" %v", ann.ChannelID, err)
|
||||||
|
log.Error(err)
|
||||||
|
nMsg.err <- err
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
log.Error(err)
|
||||||
|
nMsg.err <- err
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proof was successfully created and now can announce the channel to
|
||||||
|
// the remain network.
|
||||||
|
log.Infof("Fully valid channel proof for short_chan_id=%v constructed"+
|
||||||
|
", adding to next ann batch", shortChanID)
|
||||||
|
|
||||||
|
// Assemble the necessary announcements to add to the next broadcasting
|
||||||
|
// batch.
|
||||||
|
var announcements []networkMsg
|
||||||
|
announcements = append(announcements, networkMsg{
|
||||||
|
peer: nMsg.peer,
|
||||||
|
source: nMsg.source,
|
||||||
|
msg: chanAnn,
|
||||||
|
})
|
||||||
|
if src, err := chanInfo.NodeKey1(); err == nil && e1Ann != nil {
|
||||||
|
announcements = append(announcements, networkMsg{
|
||||||
|
peer: nMsg.peer,
|
||||||
|
source: src,
|
||||||
|
msg: e1Ann,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if src, err := chanInfo.NodeKey2(); err == nil && e2Ann != nil {
|
||||||
|
announcements = append(announcements, networkMsg{
|
||||||
|
peer: nMsg.peer,
|
||||||
|
source: src,
|
||||||
|
msg: e2Ann,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// We'll also send along the node announcements for each channel
|
||||||
|
// participant if we know of them. To ensure our node announcement
|
||||||
|
// propagates to our channel counterparty, we'll set the source for
|
||||||
|
// each announcement to the node it belongs to, otherwise we won't send
|
||||||
|
// it since the source gets skipped. This isn't necessary for channel
|
||||||
|
// updates and announcement signatures since we send those directly to
|
||||||
|
// our channel counterparty through the gossiper's reliable sender.
|
||||||
|
node1Ann, err := d.fetchNodeAnn(chanInfo.NodeKey1Bytes)
|
||||||
|
if err != nil {
|
||||||
|
log.Debugf("Unable to fetch node announcement for %x: %v",
|
||||||
|
chanInfo.NodeKey1Bytes, err)
|
||||||
|
} else {
|
||||||
|
if nodeKey1, err := chanInfo.NodeKey1(); err == nil {
|
||||||
|
announcements = append(announcements, networkMsg{
|
||||||
|
peer: nMsg.peer,
|
||||||
|
source: nodeKey1,
|
||||||
|
msg: node1Ann,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
node2Ann, err := d.fetchNodeAnn(chanInfo.NodeKey2Bytes)
|
||||||
|
if err != nil {
|
||||||
|
log.Debugf("Unable to fetch node announcement for %x: %v",
|
||||||
|
chanInfo.NodeKey2Bytes, err)
|
||||||
|
} else {
|
||||||
|
if nodeKey2, err := chanInfo.NodeKey2(); err == nil {
|
||||||
|
announcements = append(announcements, networkMsg{
|
||||||
|
peer: nMsg.peer,
|
||||||
|
source: nodeKey2,
|
||||||
|
msg: node2Ann,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nMsg.err <- nil
|
||||||
|
return announcements, true
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user