discovery+funding: add 'AnnounceSignature' proof exchange
Add the interaction between nodes of announce signature messages, which will allow us to exhcnage the half channel announcemen proofs later.
This commit is contained in:
1 parent
07076cce21
commit
fbf766e3c6
6 files changed
+891
-289
No files matched your search
+359
-133
@@ -5,6 +5,8 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"bytes"
|
||||||
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
|
||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
@@ -16,12 +18,23 @@ import (
|
|||||||
"github.com/roasbeef/btcutil"
|
"github.com/roasbeef/btcutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// waitingProofKey is the proof key which uniquely identifies the
|
||||||
|
// announcement signature message. The goal of this key is distinguish the
|
||||||
|
// local and remote proof for the same channel id.
|
||||||
|
// TODO(andrew.shvv) move to the channeldb package after waiting proof map
|
||||||
|
// becomes persistent.
|
||||||
|
type waitingProofKey struct {
|
||||||
|
chanID uint64
|
||||||
|
isRemote bool
|
||||||
|
}
|
||||||
|
|
||||||
// networkMsg couples a routing related wire message with the peer that
|
// networkMsg couples a routing related wire message with the peer that
|
||||||
// originally sent it.
|
// originally sent it.
|
||||||
type networkMsg struct {
|
type networkMsg struct {
|
||||||
msg lnwire.Message
|
msg lnwire.Message
|
||||||
isRemote bool
|
isRemote bool
|
||||||
peer *btcec.PublicKey
|
peer *btcec.PublicKey
|
||||||
|
err chan error
|
||||||
}
|
}
|
||||||
|
|
||||||
// syncRequest represents a request from an outside subsystem to the wallet to
|
// syncRequest represents a request from an outside subsystem to the wallet to
|
||||||
@@ -51,10 +64,19 @@ type Config struct {
|
|||||||
// indicates that the target peer should be excluded from the broadcast.
|
// indicates that the target peer should be excluded from the broadcast.
|
||||||
Broadcast func(exclude *btcec.PublicKey, msg ...lnwire.Message) error
|
Broadcast func(exclude *btcec.PublicKey, msg ...lnwire.Message) error
|
||||||
|
|
||||||
// SendMessages is a function which allows the service to send a set of
|
// SendToPeer is a function which allows the service to send a set of
|
||||||
// messages to a particular peer identified by the target public
|
// messages to a particular peer identified by the target public
|
||||||
// key.
|
// key.
|
||||||
SendMessages func(target *btcec.PublicKey, msg ...lnwire.Message) error
|
SendToPeer func(target *btcec.PublicKey, msg ...lnwire.Message) error
|
||||||
|
|
||||||
|
// ProofMatureDelta the number of confirmations which is needed
|
||||||
|
// before exchange the channel announcement proofs.
|
||||||
|
ProofMatureDelta uint32
|
||||||
|
|
||||||
|
// TrickleDelay the period of trickle timer which flushing to the
|
||||||
|
// network the pending batch of new announcements we've received since
|
||||||
|
// the last trickle tick.
|
||||||
|
TrickleDelay time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
// New create new discovery service structure.
|
// New create new discovery service structure.
|
||||||
@@ -79,6 +101,7 @@ func New(cfg Config) (*Discovery, error) {
|
|||||||
quit: make(chan bool),
|
quit: make(chan bool),
|
||||||
syncRequests: make(chan *syncRequest),
|
syncRequests: make(chan *syncRequest),
|
||||||
prematureAnnouncements: make(map[uint32][]*networkMsg),
|
prematureAnnouncements: make(map[uint32][]*networkMsg),
|
||||||
|
waitingProofs: make(map[waitingProofKey]*lnwire.AnnounceSignatures),
|
||||||
fakeSig: fakeSig,
|
fakeSig: fakeSig,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@@ -104,16 +127,23 @@ type Discovery struct {
|
|||||||
// the main chain are sent over.
|
// the main chain are sent over.
|
||||||
newBlocks <-chan *chainntnfs.BlockEpoch
|
newBlocks <-chan *chainntnfs.BlockEpoch
|
||||||
|
|
||||||
// prematureAnnouncements maps a blockheight to a set of announcements
|
// prematureAnnouncements maps a block height to a set of network
|
||||||
// which are "premature" from our PoV. An message is premature if
|
// messages which are "premature" from our PoV. An message is premature
|
||||||
// it claims to be anchored in a block which is beyond the current main
|
// if it claims to be anchored in a block which is beyond the current
|
||||||
// chain tip as we know it. Premature network messages will be processed
|
// main chain tip as we know it. Premature network messages will be
|
||||||
// once the chain tip as we know it extends to/past the premature
|
// processed once the chain tip as we know it extends to/past the
|
||||||
// height.
|
// premature height.
|
||||||
//
|
//
|
||||||
// TODO(roasbeef): limit premature networkMsgs to N
|
// TODO(roasbeef): limit premature networkMsgs to N
|
||||||
prematureAnnouncements map[uint32][]*networkMsg
|
prematureAnnouncements map[uint32][]*networkMsg
|
||||||
|
|
||||||
|
// waitingProofs is the map of proof announcement messages which were
|
||||||
|
// processed and waiting for opposite local or remote proof to be
|
||||||
|
// received in order to construct full proof, validate it and
|
||||||
|
// announce the channel.
|
||||||
|
// TODO(andrew.shvv) make this map persistent.
|
||||||
|
waitingProofs map[waitingProofKey]*lnwire.AnnounceSignatures
|
||||||
|
|
||||||
// networkMsgs is a channel that carries new network broadcasted
|
// networkMsgs is a channel that carries new network broadcasted
|
||||||
// message from outside the discovery service to be processed by the
|
// message from outside the discovery service to be processed by the
|
||||||
// networkHandler.
|
// networkHandler.
|
||||||
@@ -137,20 +167,22 @@ type Discovery struct {
|
|||||||
// Remote channel announcements should contain the announcement proof and be
|
// Remote channel announcements should contain the announcement proof and be
|
||||||
// fully validated.
|
// fully validated.
|
||||||
func (d *Discovery) ProcessRemoteAnnouncement(msg lnwire.Message,
|
func (d *Discovery) ProcessRemoteAnnouncement(msg lnwire.Message,
|
||||||
src *btcec.PublicKey) error {
|
src *btcec.PublicKey) chan error {
|
||||||
|
|
||||||
aMsg := &networkMsg{
|
nMsg := &networkMsg{
|
||||||
msg: msg,
|
msg: msg,
|
||||||
isRemote: true,
|
isRemote: true,
|
||||||
peer: src,
|
peer: src,
|
||||||
|
err: make(chan error, 1),
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case d.networkMsgs <- aMsg:
|
case d.networkMsgs <- nMsg:
|
||||||
return nil
|
|
||||||
case <-d.quit:
|
case <-d.quit:
|
||||||
return errors.New("discovery has been shutted down")
|
nMsg.err <- errors.New("discovery has shut down")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nMsg.err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProcessLocalAnnouncement sends a new remote announcement message along with
|
// ProcessLocalAnnouncement sends a new remote announcement message along with
|
||||||
@@ -160,20 +192,22 @@ func (d *Discovery) ProcessRemoteAnnouncement(msg lnwire.Message,
|
|||||||
// fully validated. The channels proofs will be included farther if nodes agreed
|
// fully validated. The channels proofs will be included farther if nodes agreed
|
||||||
// to announce this channel to the rest of the network.
|
// to announce this channel to the rest of the network.
|
||||||
func (d *Discovery) ProcessLocalAnnouncement(msg lnwire.Message,
|
func (d *Discovery) ProcessLocalAnnouncement(msg lnwire.Message,
|
||||||
src *btcec.PublicKey) error {
|
src *btcec.PublicKey) chan error {
|
||||||
|
|
||||||
aMsg := &networkMsg{
|
nMsg := &networkMsg{
|
||||||
msg: msg,
|
msg: msg,
|
||||||
isRemote: false,
|
isRemote: false,
|
||||||
peer: src,
|
peer: src,
|
||||||
|
err: make(chan error, 1),
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case d.networkMsgs <- aMsg:
|
case d.networkMsgs <- nMsg:
|
||||||
return nil
|
|
||||||
case <-d.quit:
|
case <-d.quit:
|
||||||
return errors.New("discovery has been shutted down")
|
nMsg.err <- errors.New("discovery has shut down")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nMsg.err
|
||||||
}
|
}
|
||||||
|
|
||||||
// SynchronizeNode sends a message to the service indicating it should
|
// SynchronizeNode sends a message to the service indicating it should
|
||||||
@@ -246,7 +280,7 @@ func (d *Discovery) networkHandler() {
|
|||||||
defer retransmitTimer.Stop()
|
defer retransmitTimer.Stop()
|
||||||
|
|
||||||
// TODO(roasbeef): parametrize the above
|
// TODO(roasbeef): parametrize the above
|
||||||
trickleTimer := time.NewTicker(time.Millisecond * 300)
|
trickleTimer := time.NewTicker(d.cfg.TrickleDelay)
|
||||||
defer trickleTimer.Stop()
|
defer trickleTimer.Stop()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
@@ -254,18 +288,18 @@ func (d *Discovery) networkHandler() {
|
|||||||
case announcement := <-d.networkMsgs:
|
case announcement := <-d.networkMsgs:
|
||||||
// Process the network announcement to determine if
|
// Process the network announcement to determine if
|
||||||
// this is either a new announcement from our PoV or an
|
// this is either a new announcement from our PoV or an
|
||||||
// updates to a prior vertex/edge we previously
|
// edges to a prior vertex/edge we previously
|
||||||
// accepted.
|
// proceeded.
|
||||||
accepted := d.processNetworkAnnouncement(announcement)
|
emittedAnnouncements := d.processNetworkAnnouncement(announcement)
|
||||||
|
|
||||||
// If the updates was accepted, then add it to our next
|
// If the announcement was accepted, then add the
|
||||||
// announcement batch to be broadcast once the trickle
|
// emitted announcements to our announce batch to be
|
||||||
// timer ticks gain.
|
// broadcast once the trickle timer ticks gain.
|
||||||
if accepted {
|
if emittedAnnouncements != nil {
|
||||||
// TODO(roasbeef): exclude peer that sent
|
// TODO(roasbeef): exclude peer that sent
|
||||||
announcementBatch = append(
|
announcementBatch = append(
|
||||||
announcementBatch,
|
announcementBatch,
|
||||||
announcement.msg,
|
emittedAnnouncements...,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,12 +328,11 @@ func (d *Discovery) networkHandler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, ann := range prematureAnns {
|
for _, ann := range prematureAnns {
|
||||||
accepted := d.processNetworkAnnouncement(ann)
|
emittedAnnouncements := d.processNetworkAnnouncement(ann)
|
||||||
|
if emittedAnnouncements != nil {
|
||||||
if accepted {
|
|
||||||
announcementBatch = append(
|
announcementBatch = append(
|
||||||
announcementBatch,
|
announcementBatch,
|
||||||
ann.msg,
|
emittedAnnouncements...,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -309,7 +342,7 @@ func (d *Discovery) networkHandler() {
|
|||||||
// flush to the network the pending batch of new announcements
|
// flush to the network the pending batch of new announcements
|
||||||
// we've received since the last trickle tick.
|
// we've received since the last trickle tick.
|
||||||
case <-trickleTimer.C:
|
case <-trickleTimer.C:
|
||||||
// If the current announcement batch is nil, then we
|
// If the current announcements batch is nil, then we
|
||||||
// have no further work here.
|
// have no further work here.
|
||||||
if len(announcementBatch) == 0 {
|
if len(announcementBatch) == 0 {
|
||||||
continue
|
continue
|
||||||
@@ -322,7 +355,8 @@ func (d *Discovery) networkHandler() {
|
|||||||
// them to all our immediately connected peers.
|
// them to all our immediately connected peers.
|
||||||
err := d.cfg.Broadcast(nil, announcementBatch...)
|
err := d.cfg.Broadcast(nil, announcementBatch...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("unable to send batch announcement: %v", err)
|
log.Errorf("unable to send batch "+
|
||||||
|
"announcements: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,7 +377,7 @@ func (d *Discovery) networkHandler() {
|
|||||||
err := d.cfg.Router.ForAllOutgoingChannels(
|
err := d.cfg.Router.ForAllOutgoingChannels(
|
||||||
func(p *channeldb.ChannelEdgePolicy) error {
|
func(p *channeldb.ChannelEdgePolicy) error {
|
||||||
c := &lnwire.ChannelUpdateAnnouncement{
|
c := &lnwire.ChannelUpdateAnnouncement{
|
||||||
Signature: d.fakeSig,
|
Signature: p.Signature,
|
||||||
ShortChannelID: lnwire.NewShortChanIDFromInt(p.ChannelID),
|
ShortChannelID: lnwire.NewShortChanIDFromInt(p.ChannelID),
|
||||||
Timestamp: uint32(p.LastUpdate.Unix()),
|
Timestamp: uint32(p.LastUpdate.Unix()),
|
||||||
Flags: p.Flags,
|
Flags: p.Flags,
|
||||||
@@ -381,8 +415,6 @@ func (d *Discovery) networkHandler() {
|
|||||||
// through the (subjectively) new information on their own.
|
// through the (subjectively) new information on their own.
|
||||||
case syncReq := <-d.syncRequests:
|
case syncReq := <-d.syncRequests:
|
||||||
nodePub := syncReq.node.SerializeCompressed()
|
nodePub := syncReq.node.SerializeCompressed()
|
||||||
log.Infof("Synchronizing channel graph with %x", nodePub)
|
|
||||||
|
|
||||||
if err := d.synchronize(syncReq); err != nil {
|
if err := d.synchronize(syncReq); err != nil {
|
||||||
log.Errorf("unable to sync graph state with %x: %v",
|
log.Errorf("unable to sync graph state with %x: %v",
|
||||||
nodePub, err)
|
nodePub, err)
|
||||||
@@ -397,23 +429,22 @@ func (d *Discovery) networkHandler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// processNetworkAnnouncement processes a new network relate authenticated
|
// processNetworkAnnouncement processes a new network relate authenticated
|
||||||
// channel or node announcement. If the updates didn't affect the internal state
|
// channel or node announcement or announcements proofs. If the announcement
|
||||||
// of the draft due to either being out of date, invalid, or redundant, then
|
// didn't affect the internal state due to either being out of date, invalid,
|
||||||
// false is returned. Otherwise, true is returned indicating that the caller
|
// or redundant, then nil is returned. Otherwise, the set of announcements
|
||||||
// may want to batch this request to be broadcast to immediate peers during the
|
// will be returned which should be broadcasted to the rest of the network.
|
||||||
// next announcement epoch.
|
func (d *Discovery) processNetworkAnnouncement(nMsg *networkMsg) []lnwire.Message {
|
||||||
func (d *Discovery) processNetworkAnnouncement(aMsg *networkMsg) bool {
|
var announcements []lnwire.Message
|
||||||
isPremature := func(chanID *lnwire.ShortChannelID) bool {
|
isPremature := func(chanID lnwire.ShortChannelID, delta uint32) bool {
|
||||||
return chanID.BlockHeight > d.bestHeight
|
return chanID.BlockHeight+delta > d.bestHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
switch msg := aMsg.msg.(type) {
|
switch msg := nMsg.msg.(type) {
|
||||||
|
|
||||||
// A new node announcement has arrived which either presents a new
|
// A new node announcement has arrived which either presents a new
|
||||||
// node, or a node updating previously advertised information.
|
// node, or a node updating previously advertised information.
|
||||||
case *lnwire.NodeAnnouncement:
|
case *lnwire.NodeAnnouncement:
|
||||||
if aMsg.isRemote {
|
if nMsg.isRemote {
|
||||||
// TODO(andrew.shvv) Add node validation
|
// TODO(andrew.shvv) add validation
|
||||||
}
|
}
|
||||||
|
|
||||||
node := &channeldb.LightningNode{
|
node := &channeldb.LightningNode{
|
||||||
@@ -426,10 +457,25 @@ func (d *Discovery) processNetworkAnnouncement(aMsg *networkMsg) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := d.cfg.Router.AddNode(node); err != nil {
|
if err := d.cfg.Router.AddNode(node); err != nil {
|
||||||
log.Errorf("unable to add node: %v", err)
|
e := errors.Errorf("unable to add node: %v", err)
|
||||||
return false
|
if routing.IsError(err,
|
||||||
|
routing.ErrOutdated,
|
||||||
|
routing.ErrIgnored) {
|
||||||
|
log.Info(e)
|
||||||
|
} else {
|
||||||
|
log.Error(e)
|
||||||
|
}
|
||||||
|
nMsg.err <- e
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Node announcement was successfully proceeded and know it
|
||||||
|
// might be broadcasted to other connected nodes.
|
||||||
|
announcements = append(announcements, msg)
|
||||||
|
|
||||||
|
nMsg.err <- nil
|
||||||
|
return announcements
|
||||||
|
|
||||||
// A new channel announcement has arrived, this indicates the
|
// A new channel announcement has arrived, this indicates the
|
||||||
// *creation* of a new channel within the network. This only advertises
|
// *creation* of a new channel within the network. This only advertises
|
||||||
// the existence of a channel and not yet the routing policies in
|
// the existence of a channel and not yet the routing policies in
|
||||||
@@ -438,7 +484,7 @@ func (d *Discovery) processNetworkAnnouncement(aMsg *networkMsg) bool {
|
|||||||
// If the advertised inclusionary block is beyond our knowledge
|
// If the advertised inclusionary block is beyond our knowledge
|
||||||
// of the chain tip, then we'll put the announcement in limbo
|
// of the chain tip, then we'll put the announcement in limbo
|
||||||
// to be fully verified once we advance forward in the chain.
|
// to be fully verified once we advance forward in the chain.
|
||||||
if isPremature(&msg.ShortChannelID) {
|
if isPremature(msg.ShortChannelID, 0) {
|
||||||
blockHeight := msg.ShortChannelID.BlockHeight
|
blockHeight := msg.ShortChannelID.BlockHeight
|
||||||
log.Infof("Announcement for chan_id=(%v), is "+
|
log.Infof("Announcement for chan_id=(%v), is "+
|
||||||
"premature: advertises height %v, only height "+
|
"premature: advertises height %v, only height "+
|
||||||
@@ -447,21 +493,21 @@ func (d *Discovery) processNetworkAnnouncement(aMsg *networkMsg) bool {
|
|||||||
|
|
||||||
d.prematureAnnouncements[blockHeight] = append(
|
d.prematureAnnouncements[blockHeight] = append(
|
||||||
d.prematureAnnouncements[blockHeight],
|
d.prematureAnnouncements[blockHeight],
|
||||||
aMsg,
|
nMsg,
|
||||||
)
|
)
|
||||||
return false
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var proof *channeldb.ChannelAuthProof
|
var proof *channeldb.ChannelAuthProof
|
||||||
if aMsg.isRemote {
|
if nMsg.isRemote {
|
||||||
// TODO(andrew.shvv) Add channel validation
|
// TODO(andrew.shvv) Add validation
|
||||||
}
|
|
||||||
|
|
||||||
proof = &channeldb.ChannelAuthProof{
|
proof = &channeldb.ChannelAuthProof{
|
||||||
NodeSig1: msg.NodeSig1,
|
NodeSig1: msg.NodeSig1,
|
||||||
NodeSig2: msg.NodeSig2,
|
NodeSig2: msg.NodeSig2,
|
||||||
BitcoinSig1: msg.BitcoinSig1,
|
BitcoinSig1: msg.BitcoinSig1,
|
||||||
BitcoinSig2: msg.BitcoinSig2,
|
BitcoinSig2: msg.BitcoinSig2,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
edge := &channeldb.ChannelEdgeInfo{
|
edge := &channeldb.ChannelEdgeInfo{
|
||||||
@@ -474,45 +520,69 @@ func (d *Discovery) processNetworkAnnouncement(aMsg *networkMsg) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := d.cfg.Router.AddEdge(edge); err != nil {
|
if err := d.cfg.Router.AddEdge(edge); err != nil {
|
||||||
if !routing.IsError(err, routing.ErrOutdated) {
|
e := errors.Errorf("unable to add edge: %v", err)
|
||||||
log.Errorf("unable to add edge: %v", err)
|
if routing.IsError(err,
|
||||||
|
routing.ErrOutdated,
|
||||||
|
routing.ErrIgnored) {
|
||||||
|
log.Info(e)
|
||||||
} else {
|
} else {
|
||||||
log.Info("Unable to add edge: %v", err)
|
log.Error(e)
|
||||||
}
|
}
|
||||||
|
nMsg.err <- e
|
||||||
return false
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// A new authenticated channel updates has arrived, this indicates
|
// Channel announcement was successfully proceeded and know it
|
||||||
|
// might be broadcasted to other connected nodes if it was
|
||||||
|
// announcement with proof (remote).
|
||||||
|
if proof != nil {
|
||||||
|
announcements = append(announcements, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
nMsg.err <- nil
|
||||||
|
return announcements
|
||||||
|
|
||||||
|
// A new authenticated channel edges has arrived, this indicates
|
||||||
// that the directional information for an already known channel has
|
// that the directional information for an already known channel has
|
||||||
// been updated.
|
// been updated.
|
||||||
case *lnwire.ChannelUpdateAnnouncement:
|
case *lnwire.ChannelUpdateAnnouncement:
|
||||||
chanID := msg.ShortChannelID.ToUint64()
|
blockHeight := msg.ShortChannelID.BlockHeight
|
||||||
|
shortChanID := msg.ShortChannelID.ToUint64()
|
||||||
|
|
||||||
// If the advertised inclusionary block is beyond our knowledge
|
// If the advertised inclusionary block is beyond our knowledge
|
||||||
// of the chain tip, then we'll put the announcement in limbo
|
// of the chain tip, then we'll put the announcement in limbo
|
||||||
// to be fully verified once we advance forward in the chain.
|
// to be fully verified once we advance forward in the chain.
|
||||||
if isPremature(&msg.ShortChannelID) {
|
if isPremature(msg.ShortChannelID, 0) {
|
||||||
blockHeight := msg.ShortChannelID.BlockHeight
|
log.Infof("Update announcement for "+
|
||||||
log.Infof("Update announcement for chan_id=(%v), is "+
|
"shortChanID=(%v), is premature: advertises "+
|
||||||
"premature: advertises height %v, only height "+
|
"height %v, only height %v is known",
|
||||||
"%v is known", chanID, blockHeight,
|
shortChanID, blockHeight, d.bestHeight)
|
||||||
d.bestHeight)
|
|
||||||
|
|
||||||
d.prematureAnnouncements[blockHeight] = append(
|
d.prematureAnnouncements[blockHeight] = append(
|
||||||
d.prematureAnnouncements[blockHeight],
|
d.prematureAnnouncements[blockHeight],
|
||||||
aMsg,
|
nMsg,
|
||||||
)
|
)
|
||||||
return false
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if aMsg.isRemote {
|
// Get the node pub key as far as we don't have it in
|
||||||
// TODO(andrew.shvv) Add update channel validation
|
// channel update announcement message and verify
|
||||||
|
// message signature.
|
||||||
|
chanInfo, _, _, err := d.cfg.Router.GetChannelByID(msg.ShortChannelID)
|
||||||
|
if err != nil {
|
||||||
|
err := errors.Errorf("unable to validate "+
|
||||||
|
"channel update shortChanID=%v: %v",
|
||||||
|
shortChanID, err)
|
||||||
|
nMsg.err <- err
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(andrew.shvv) Add validation
|
||||||
|
|
||||||
// TODO(roasbeef): should be msat here
|
// TODO(roasbeef): should be msat here
|
||||||
update := &channeldb.ChannelEdgePolicy{
|
update := &channeldb.ChannelEdgePolicy{
|
||||||
ChannelID: chanID,
|
Signature: msg.Signature,
|
||||||
|
ChannelID: shortChanID,
|
||||||
LastUpdate: time.Unix(int64(msg.Timestamp), 0),
|
LastUpdate: time.Unix(int64(msg.Timestamp), 0),
|
||||||
Flags: msg.Flags,
|
Flags: msg.Flags,
|
||||||
TimeLockDelta: msg.TimeLockDelta,
|
TimeLockDelta: msg.TimeLockDelta,
|
||||||
@@ -522,12 +592,200 @@ func (d *Discovery) processNetworkAnnouncement(aMsg *networkMsg) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := d.cfg.Router.UpdateEdge(update); err != nil {
|
if err := d.cfg.Router.UpdateEdge(update); err != nil {
|
||||||
log.Errorf("unable to update edge: %v", err)
|
e := errors.Errorf("unable to update edge: %v", err)
|
||||||
return false
|
if routing.IsError(err,
|
||||||
}
|
routing.ErrOutdated,
|
||||||
}
|
routing.ErrIgnored) {
|
||||||
|
log.Info(e)
|
||||||
|
} else {
|
||||||
|
log.Error(e)
|
||||||
|
}
|
||||||
|
|
||||||
return true
|
nMsg.err <- e
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Channel update announcement was successfully proceeded and
|
||||||
|
// know it might be broadcasted to other connected nodes.
|
||||||
|
// We should announce the edge to rest of the network only
|
||||||
|
// if channel has the authentication proof.
|
||||||
|
if chanInfo.AuthProof != nil {
|
||||||
|
announcements = append(announcements, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
nMsg.err <- nil
|
||||||
|
return announcements
|
||||||
|
|
||||||
|
// New signature announcement received which indicates willingness
|
||||||
|
// of the parties (to exchange the channel signatures / announce newly
|
||||||
|
// created channel).
|
||||||
|
case *lnwire.AnnounceSignatures:
|
||||||
|
needBlockHeight := msg.ShortChannelID.BlockHeight + d.cfg.ProofMatureDelta
|
||||||
|
shortChanID := msg.ShortChannelID.ToUint64()
|
||||||
|
prefix := "local"
|
||||||
|
if nMsg.isRemote {
|
||||||
|
prefix = "remote"
|
||||||
|
}
|
||||||
|
|
||||||
|
// By the specification proof should be sent after some number of
|
||||||
|
// confirmations after channel was registered in bitcoin
|
||||||
|
// blockchain. So we should check that proof is premature and
|
||||||
|
// if not send it to the be proceeded again. This allows us to
|
||||||
|
// be tolerant to other clients if this constraint was changed.
|
||||||
|
if isPremature(msg.ShortChannelID, d.cfg.ProofMatureDelta) {
|
||||||
|
d.prematureAnnouncements[needBlockHeight] = append(
|
||||||
|
d.prematureAnnouncements[needBlockHeight],
|
||||||
|
nMsg,
|
||||||
|
)
|
||||||
|
log.Infof("Premature proof annoucement, "+
|
||||||
|
"current block height lower than needed: %v <"+
|
||||||
|
" %v, add announcement to reprocessing batch",
|
||||||
|
d.bestHeight, needBlockHeight)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that we have channel with such channel id in out
|
||||||
|
// lightning network topology.
|
||||||
|
chanInfo, e1, e2, err := d.cfg.Router.GetChannelByID(msg.ShortChannelID)
|
||||||
|
if err != nil {
|
||||||
|
err := errors.Errorf("unable to process channel "+
|
||||||
|
"%v proof with shortChanID=%v: %v", prefix,
|
||||||
|
shortChanID, err)
|
||||||
|
nMsg.err <- err
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
isFirstNode := bytes.Equal(nMsg.peer.SerializeCompressed(),
|
||||||
|
chanInfo.NodeKey1.SerializeCompressed())
|
||||||
|
isSecondNode := bytes.Equal(nMsg.peer.SerializeCompressed(),
|
||||||
|
chanInfo.NodeKey2.SerializeCompressed())
|
||||||
|
|
||||||
|
// Check that channel that was retrieved belongs to the peer
|
||||||
|
// which sent the proof announcement, otherwise the proof for
|
||||||
|
// might be rewritten by the any lightning network node.
|
||||||
|
if !(isFirstNode || isSecondNode) {
|
||||||
|
err := errors.Errorf("channel that was received not "+
|
||||||
|
"belongs to the peer which sent the proof, "+
|
||||||
|
"shortChanID=%v", shortChanID)
|
||||||
|
log.Error(err)
|
||||||
|
nMsg.err <- err
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that we received the opposite proof, if so, than we
|
||||||
|
// should 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.
|
||||||
|
oppositeKey := newProofKey(chanInfo.ChannelID, !nMsg.isRemote)
|
||||||
|
oppositeProof, ok := d.waitingProofs[oppositeKey]
|
||||||
|
if !ok {
|
||||||
|
key := newProofKey(chanInfo.ChannelID, nMsg.isRemote)
|
||||||
|
d.waitingProofs[key] = msg
|
||||||
|
|
||||||
|
// If proof was send from funding manager than we
|
||||||
|
// should send the announce signature message to
|
||||||
|
// remote side.
|
||||||
|
if !nMsg.isRemote {
|
||||||
|
// Check that first node of the channel info
|
||||||
|
// corresponds to us.
|
||||||
|
var remotePeer *btcec.PublicKey
|
||||||
|
if isFirstNode {
|
||||||
|
remotePeer = chanInfo.NodeKey2
|
||||||
|
} else {
|
||||||
|
remotePeer = chanInfo.NodeKey1
|
||||||
|
}
|
||||||
|
|
||||||
|
err := d.cfg.SendToPeer(remotePeer, msg)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("unable to send "+
|
||||||
|
"announcement message to "+
|
||||||
|
"peer: %x",
|
||||||
|
remotePeer.SerializeCompressed())
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("Send channel announcement proof "+
|
||||||
|
"for shortChanID=%v to remote peer: "+
|
||||||
|
"%x", shortChanID, remotePeer.SerializeCompressed())
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("Incoming %v proof announcement for "+
|
||||||
|
"shortChanID=%v have been proceeded and waiting for opposite proof",
|
||||||
|
prefix, shortChanID)
|
||||||
|
|
||||||
|
nMsg.err <- nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var dbProof channeldb.ChannelAuthProof
|
||||||
|
if isFirstNode {
|
||||||
|
dbProof.NodeSig1 = msg.NodeSignature
|
||||||
|
dbProof.NodeSig2 = oppositeProof.NodeSignature
|
||||||
|
dbProof.BitcoinSig1 = msg.BitcoinSignature
|
||||||
|
dbProof.BitcoinSig2 = oppositeProof.BitcoinSignature
|
||||||
|
} else {
|
||||||
|
dbProof.NodeSig1 = oppositeProof.NodeSignature
|
||||||
|
dbProof.NodeSig2 = msg.NodeSignature
|
||||||
|
dbProof.BitcoinSig1 = oppositeProof.BitcoinSignature
|
||||||
|
dbProof.BitcoinSig2 = msg.BitcoinSignature
|
||||||
|
}
|
||||||
|
|
||||||
|
chanAnn, e1Ann, e2Ann := createChanAnnouncement(&dbProof, chanInfo, e1, e2)
|
||||||
|
|
||||||
|
// TODO(andrew.shvv) Add validation
|
||||||
|
|
||||||
|
// 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. On this stage we
|
||||||
|
// should check that node keys are corresponds to the bitcoin
|
||||||
|
// keys by validating the signatures of announcement.
|
||||||
|
// If proof is valid than we should 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 := errors.Errorf("unable add proof to the "+
|
||||||
|
"channel chanID=%v: %v", msg.ChannelID, err)
|
||||||
|
log.Error(err)
|
||||||
|
nMsg.err <- err
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proof was successfully created and now can announce the
|
||||||
|
// channel to the remain network.
|
||||||
|
log.Infof("Incoming %v proof announcement for shortChanID=%v"+
|
||||||
|
" have been proceeded, adding channel announcement in"+
|
||||||
|
" the broadcasting batch", prefix, shortChanID)
|
||||||
|
|
||||||
|
announcements = append(announcements, chanAnn)
|
||||||
|
if e1Ann != nil {
|
||||||
|
announcements = append(announcements, e1Ann)
|
||||||
|
}
|
||||||
|
if e2Ann != nil {
|
||||||
|
announcements = append(announcements, e2Ann)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !nMsg.isRemote {
|
||||||
|
var remotePeer *btcec.PublicKey
|
||||||
|
if isFirstNode {
|
||||||
|
remotePeer = chanInfo.NodeKey2
|
||||||
|
} else {
|
||||||
|
remotePeer = chanInfo.NodeKey1
|
||||||
|
}
|
||||||
|
err = d.cfg.SendToPeer(remotePeer, msg)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("unable to send announcement "+
|
||||||
|
"message to peer: %x",
|
||||||
|
remotePeer.SerializeCompressed())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nMsg.err <- nil
|
||||||
|
return announcements
|
||||||
|
|
||||||
|
default:
|
||||||
|
nMsg.err <- errors.New("wrong type of the announcement")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// synchronize attempts to synchronize the target node in the syncReq to
|
// synchronize attempts to synchronize the target node in the syncReq to
|
||||||
@@ -555,7 +813,7 @@ func (d *Discovery) synchronize(syncReq *syncRequest) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ann := &lnwire.NodeAnnouncement{
|
ann := &lnwire.NodeAnnouncement{
|
||||||
Signature: d.fakeSig,
|
Signature: node.AuthSig,
|
||||||
Timestamp: uint32(node.LastUpdate.Unix()),
|
Timestamp: uint32(node.LastUpdate.Unix()),
|
||||||
Addresses: node.Addresses,
|
Addresses: node.Addresses,
|
||||||
NodeID: node.PubKey,
|
NodeID: node.PubKey,
|
||||||
@@ -573,71 +831,39 @@ func (d *Discovery) synchronize(syncReq *syncRequest) error {
|
|||||||
|
|
||||||
// With the vertexes gathered, we'll no retrieve the initial
|
// With the vertexes gathered, we'll no retrieve the initial
|
||||||
// announcement, as well as the latest channel update announcement for
|
// announcement, as well as the latest channel update announcement for
|
||||||
// both of the directed edges that make up the channel.
|
// both of the directed infos that make up the channel.
|
||||||
var numEdges uint32
|
var numEdges uint32
|
||||||
if err := d.cfg.Router.ForEachChannel(func(chanInfo *channeldb.ChannelEdgeInfo,
|
if err := d.cfg.Router.ForEachChannel(func(chanInfo *channeldb.ChannelEdgeInfo,
|
||||||
e1, e2 *channeldb.ChannelEdgePolicy) error {
|
e1, e2 *channeldb.ChannelEdgePolicy) error {
|
||||||
|
|
||||||
chanID := lnwire.NewShortChanIDFromInt(chanInfo.ChannelID)
|
|
||||||
|
|
||||||
// First, using the parameters of the channel, along with the
|
// First, using the parameters of the channel, along with the
|
||||||
// channel authentication proof, we'll create re-create the
|
// channel authentication proof, we'll create re-create the
|
||||||
// original authenticated channel announcement.
|
// original authenticated channel announcement.
|
||||||
// TODO(andrew.shvv) skip if proof is nil
|
if chanInfo.AuthProof != nil {
|
||||||
authProof := chanInfo.AuthProof
|
chanAnn, e1Ann, e2Ann := createChanAnnouncement(
|
||||||
chanAnn := &lnwire.ChannelAnnouncement{
|
chanInfo.AuthProof, chanInfo, e1, e2)
|
||||||
NodeSig1: authProof.NodeSig1,
|
|
||||||
NodeSig2: authProof.NodeSig2,
|
|
||||||
ShortChannelID: chanID,
|
|
||||||
BitcoinSig1: authProof.BitcoinSig1,
|
|
||||||
BitcoinSig2: authProof.BitcoinSig2,
|
|
||||||
NodeID1: chanInfo.NodeKey1,
|
|
||||||
NodeID2: chanInfo.NodeKey2,
|
|
||||||
BitcoinKey1: chanInfo.BitcoinKey1,
|
|
||||||
BitcoinKey2: chanInfo.BitcoinKey2,
|
|
||||||
}
|
|
||||||
announceMessages = append(announceMessages, chanAnn)
|
|
||||||
|
|
||||||
// Since it's up to a node's policy as to whether they
|
announceMessages = append(announceMessages, chanAnn)
|
||||||
// advertise the edge in dire direction, we don't create an
|
if e1Ann != nil {
|
||||||
// advertisement if the edge is nil.
|
announceMessages = append(announceMessages, e1Ann)
|
||||||
if e1 != nil {
|
}
|
||||||
announceMessages = append(announceMessages, &lnwire.ChannelUpdateAnnouncement{
|
if e2Ann != nil {
|
||||||
Signature: d.fakeSig,
|
announceMessages = append(announceMessages, e2Ann)
|
||||||
ShortChannelID: chanID,
|
}
|
||||||
Timestamp: uint32(e1.LastUpdate.Unix()),
|
|
||||||
Flags: 0,
|
numEdges++
|
||||||
TimeLockDelta: e1.TimeLockDelta,
|
|
||||||
HtlcMinimumMsat: uint32(e1.MinHTLC),
|
|
||||||
FeeBaseMsat: uint32(e1.FeeBaseMSat),
|
|
||||||
FeeProportionalMillionths: uint32(e1.FeeProportionalMillionths),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if e2 != nil {
|
|
||||||
announceMessages = append(announceMessages, &lnwire.ChannelUpdateAnnouncement{
|
|
||||||
Signature: d.fakeSig,
|
|
||||||
ShortChannelID: chanID,
|
|
||||||
Timestamp: uint32(e2.LastUpdate.Unix()),
|
|
||||||
Flags: 1,
|
|
||||||
TimeLockDelta: e2.TimeLockDelta,
|
|
||||||
HtlcMinimumMsat: uint32(e2.MinHTLC),
|
|
||||||
FeeBaseMsat: uint32(e2.FeeBaseMSat),
|
|
||||||
FeeProportionalMillionths: uint32(e2.FeeProportionalMillionths),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
numEdges++
|
|
||||||
return nil
|
return nil
|
||||||
}); err != nil && err != channeldb.ErrGraphNoEdgesFound {
|
}); err != nil && err != channeldb.ErrGraphNoEdgesFound {
|
||||||
log.Errorf("unable to sync edges w/ peer: %v", err)
|
log.Errorf("unable to sync infos with peer: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("Syncing channel graph state with %x, sending %v "+
|
log.Infof("Syncing channel graph state with %x, sending %v "+
|
||||||
"nodes and %v edges", targetNode.SerializeCompressed(),
|
"nodes and %v infos", targetNode.SerializeCompressed(),
|
||||||
numNodes, numEdges)
|
numNodes, numEdges)
|
||||||
|
|
||||||
// With all the announcement messages gathered, send them all in a
|
// With all the announcement messages gathered, send them all in a
|
||||||
// single batch to the target peer.
|
// single batch to the target peer.
|
||||||
return d.cfg.SendMessages(targetNode, announceMessages...)
|
return d.cfg.SendToPeer(targetNode, announceMessages...)
|
||||||
}
|
}
|
||||||
+323
-90
@@ -13,6 +13,7 @@ import (
|
|||||||
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-errors/errors"
|
||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
@@ -33,18 +34,39 @@ var (
|
|||||||
}
|
}
|
||||||
_, _ = testSig.R.SetString("63724406601629180062774974542967536251589935445068131219452686511677818569431", 10)
|
_, _ = testSig.R.SetString("63724406601629180062774974542967536251589935445068131219452686511677818569431", 10)
|
||||||
_, _ = testSig.S.SetString("18801056069249825825291287104931333862866033135609736119018462340006816851118", 10)
|
_, _ = testSig.S.SetString("18801056069249825825291287104931333862866033135609736119018462340006816851118", 10)
|
||||||
|
|
||||||
|
inputStr = "147caa76786596590baa4e98f5d9f48b86c7765e489f7a6ff3360fe5c674360b"
|
||||||
|
sha, _ = chainhash.NewHashFromStr(inputStr)
|
||||||
|
outpoint = wire.NewOutPoint(sha, 0)
|
||||||
|
|
||||||
|
bitcoinKeyPriv1, _ = btcec.NewPrivateKey(btcec.S256())
|
||||||
|
bitcoinKeyPub1 = bitcoinKeyPriv1.PubKey()
|
||||||
|
|
||||||
|
nodeKeyPriv1, _ = btcec.NewPrivateKey(btcec.S256())
|
||||||
|
nodeKeyPub1 = nodeKeyPriv1.PubKey()
|
||||||
|
|
||||||
|
bitcoinKeyPriv2, _ = btcec.NewPrivateKey(btcec.S256())
|
||||||
|
bitcoinKeyPub2 = bitcoinKeyPriv2.PubKey()
|
||||||
|
|
||||||
|
nodeKeyPriv2, _ = btcec.NewPrivateKey(btcec.S256())
|
||||||
|
nodeKeyPub2 = nodeKeyPriv2.PubKey()
|
||||||
|
|
||||||
|
trickleDelay = time.Millisecond * 300
|
||||||
|
proofMatureDelta uint32
|
||||||
)
|
)
|
||||||
|
|
||||||
type mockGraphSource struct {
|
type mockGraphSource struct {
|
||||||
nodes []*channeldb.LightningNode
|
nodes []*channeldb.LightningNode
|
||||||
edges []*channeldb.ChannelEdgeInfo
|
infos map[uint64]*channeldb.ChannelEdgeInfo
|
||||||
updates []*channeldb.ChannelEdgePolicy
|
edges map[uint64][]*channeldb.ChannelEdgePolicy
|
||||||
bestHeight uint32
|
bestHeight uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMockRouter(height uint32) *mockGraphSource {
|
func newMockRouter(height uint32) *mockGraphSource {
|
||||||
return &mockGraphSource{
|
return &mockGraphSource{
|
||||||
bestHeight: height,
|
bestHeight: height,
|
||||||
|
infos: make(map[uint64]*channeldb.ChannelEdgeInfo),
|
||||||
|
edges: make(map[uint64][]*channeldb.ChannelEdgePolicy),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,13 +77,19 @@ func (r *mockGraphSource) AddNode(node *channeldb.LightningNode) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *mockGraphSource) AddEdge(edge *channeldb.ChannelEdgeInfo) error {
|
func (r *mockGraphSource) AddEdge(info *channeldb.ChannelEdgeInfo) error {
|
||||||
r.edges = append(r.edges, edge)
|
if _, ok := r.infos[info.ChannelID]; ok {
|
||||||
|
return errors.New("info already exist")
|
||||||
|
}
|
||||||
|
r.infos[info.ChannelID] = info
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *mockGraphSource) UpdateEdge(policy *channeldb.ChannelEdgePolicy) error {
|
func (r *mockGraphSource) UpdateEdge(edge *channeldb.ChannelEdgePolicy) error {
|
||||||
r.updates = append(r.updates, policy)
|
r.edges[edge.ChannelID] = append(
|
||||||
|
r.edges[edge.ChannelID],
|
||||||
|
edge,
|
||||||
|
)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,6 +119,28 @@ func (r *mockGraphSource) ForEachChannel(func(chanInfo *channeldb.ChannelEdgeInf
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *mockGraphSource) GetChannelByID(chanID lnwire.ShortChannelID) (
|
||||||
|
*channeldb.ChannelEdgeInfo,
|
||||||
|
*channeldb.ChannelEdgePolicy,
|
||||||
|
*channeldb.ChannelEdgePolicy, error) {
|
||||||
|
|
||||||
|
chanInfo, ok := r.infos[chanID.ToUint64()]
|
||||||
|
if !ok {
|
||||||
|
return nil, nil, nil, errors.New("can't find channel info")
|
||||||
|
}
|
||||||
|
|
||||||
|
edges := r.edges[chanID.ToUint64()]
|
||||||
|
if len(edges) == 0 {
|
||||||
|
return chanInfo, nil, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(edges) == 1 {
|
||||||
|
return chanInfo, edges[0], nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return chanInfo, edges[0], edges[1], nil
|
||||||
|
}
|
||||||
|
|
||||||
type mockNotifier struct {
|
type mockNotifier struct {
|
||||||
clientCounter uint32
|
clientCounter uint32
|
||||||
epochClients map[uint32]chan *chainntnfs.BlockEpoch
|
epochClients map[uint32]chan *chainntnfs.BlockEpoch
|
||||||
@@ -149,31 +199,87 @@ func (m *mockNotifier) Stop() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createNodeAnnouncement() (*lnwire.NodeAnnouncement,
|
type annBatch struct {
|
||||||
|
nodeAnn1 *lnwire.NodeAnnouncement
|
||||||
|
nodeAnn2 *lnwire.NodeAnnouncement
|
||||||
|
localChanAnn *lnwire.ChannelAnnouncement
|
||||||
|
remoteChanAnn *lnwire.ChannelAnnouncement
|
||||||
|
chanUpdAnn *lnwire.ChannelUpdateAnnouncement
|
||||||
|
localProofAnn *lnwire.AnnounceSignatures
|
||||||
|
remoteProofAnn *lnwire.AnnounceSignatures
|
||||||
|
}
|
||||||
|
|
||||||
|
func createAnnouncements(blockHeight uint32) (*annBatch, error) {
|
||||||
|
var err error
|
||||||
|
var batch annBatch
|
||||||
|
|
||||||
|
batch.nodeAnn1, err = createNodeAnnouncement(nodeKeyPriv1)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
batch.nodeAnn2, err = createNodeAnnouncement(nodeKeyPriv2)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
batch.remoteChanAnn, err = createRemoteChannelAnnouncement(blockHeight)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
batch.localProofAnn = &lnwire.AnnounceSignatures{
|
||||||
|
NodeSignature: batch.remoteChanAnn.NodeSig1,
|
||||||
|
BitcoinSignature: batch.remoteChanAnn.BitcoinSig1,
|
||||||
|
}
|
||||||
|
|
||||||
|
batch.remoteProofAnn = &lnwire.AnnounceSignatures{
|
||||||
|
NodeSignature: batch.remoteChanAnn.NodeSig2,
|
||||||
|
BitcoinSignature: batch.remoteChanAnn.BitcoinSig2,
|
||||||
|
}
|
||||||
|
|
||||||
|
batch.localChanAnn, err = createRemoteChannelAnnouncement(blockHeight)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
batch.localChanAnn.BitcoinSig1 = nil
|
||||||
|
batch.localChanAnn.BitcoinSig2 = nil
|
||||||
|
batch.localChanAnn.NodeSig1 = nil
|
||||||
|
batch.localChanAnn.NodeSig2 = nil
|
||||||
|
|
||||||
|
batch.chanUpdAnn, err = createUpdateAnnouncement(blockHeight)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &batch, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func createNodeAnnouncement(priv *btcec.PrivateKey) (*lnwire.NodeAnnouncement,
|
||||||
error) {
|
error) {
|
||||||
priv, err := btcec.NewPrivateKey(btcec.S256())
|
|
||||||
|
alias, err := lnwire.NewAlias("kek" + string(priv.Serialize()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pub := priv.PubKey().SerializeCompressed()
|
a := &lnwire.NodeAnnouncement{
|
||||||
|
Signature: testSig,
|
||||||
alias, err := lnwire.NewAlias("kek" + string(pub[:]))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &lnwire.NodeAnnouncement{
|
|
||||||
Timestamp: uint32(prand.Int31()),
|
Timestamp: uint32(prand.Int31()),
|
||||||
Addresses: testAddrs,
|
Addresses: testAddrs,
|
||||||
NodeID: priv.PubKey(),
|
NodeID: priv.PubKey(),
|
||||||
Alias: alias,
|
Alias: alias,
|
||||||
Features: testFeatures,
|
Features: testFeatures,
|
||||||
}, nil
|
}
|
||||||
|
|
||||||
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createUpdateAnnouncement(blockHeight uint32) *lnwire.ChannelUpdateAnnouncement {
|
func createUpdateAnnouncement(blockHeight uint32) (*lnwire.ChannelUpdateAnnouncement,
|
||||||
return &lnwire.ChannelUpdateAnnouncement{
|
error) {
|
||||||
|
|
||||||
|
a := &lnwire.ChannelUpdateAnnouncement{
|
||||||
Signature: testSig,
|
Signature: testSig,
|
||||||
ShortChannelID: lnwire.ShortChannelID{
|
ShortChannelID: lnwire.ShortChannelID{
|
||||||
BlockHeight: blockHeight,
|
BlockHeight: blockHeight,
|
||||||
@@ -184,26 +290,37 @@ func createUpdateAnnouncement(blockHeight uint32) *lnwire.ChannelUpdateAnnouncem
|
|||||||
FeeBaseMsat: uint32(prand.Int31()),
|
FeeBaseMsat: uint32(prand.Int31()),
|
||||||
FeeProportionalMillionths: uint32(prand.Int31()),
|
FeeProportionalMillionths: uint32(prand.Int31()),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createChannelAnnouncement(blockHeight uint32) *lnwire.ChannelAnnouncement {
|
func createRemoteChannelAnnouncement(blockHeight uint32) (*lnwire.ChannelAnnouncement,
|
||||||
// Our fake channel will be "confirmed" at height 101.
|
error) {
|
||||||
chanID := lnwire.ShortChannelID{
|
|
||||||
BlockHeight: blockHeight,
|
a := &lnwire.ChannelAnnouncement{
|
||||||
TxIndex: 0,
|
ShortChannelID: lnwire.ShortChannelID{
|
||||||
TxPosition: 0,
|
BlockHeight: blockHeight,
|
||||||
|
TxIndex: 0,
|
||||||
|
TxPosition: 0,
|
||||||
|
},
|
||||||
|
NodeID1: nodeKeyPub1,
|
||||||
|
NodeID2: nodeKeyPub2,
|
||||||
|
BitcoinKey1: bitcoinKeyPub1,
|
||||||
|
BitcoinKey2: bitcoinKeyPub2,
|
||||||
|
|
||||||
|
NodeSig1: testSig,
|
||||||
|
NodeSig2: testSig,
|
||||||
|
BitcoinSig1: testSig,
|
||||||
|
BitcoinSig2: testSig,
|
||||||
}
|
}
|
||||||
|
|
||||||
return &lnwire.ChannelAnnouncement{
|
return a, nil
|
||||||
ShortChannelID: chanID,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type testCtx struct {
|
type testCtx struct {
|
||||||
discovery *Discovery
|
discovery *Discovery
|
||||||
router *mockGraphSource
|
router *mockGraphSource
|
||||||
notifier *mockNotifier
|
notifier *mockNotifier
|
||||||
|
|
||||||
broadcastedMessage chan lnwire.Message
|
broadcastedMessage chan lnwire.Message
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,7 +332,7 @@ func createTestCtx(startHeight uint32) (*testCtx, func(), error) {
|
|||||||
notifier := newMockNotifier()
|
notifier := newMockNotifier()
|
||||||
router := newMockRouter(startHeight)
|
router := newMockRouter(startHeight)
|
||||||
|
|
||||||
broadcastedMessage := make(chan lnwire.Message)
|
broadcastedMessage := make(chan lnwire.Message, 10)
|
||||||
discovery, err := New(Config{
|
discovery, err := New(Config{
|
||||||
Notifier: notifier,
|
Notifier: notifier,
|
||||||
Broadcast: func(_ *btcec.PublicKey, msgs ...lnwire.Message) error {
|
Broadcast: func(_ *btcec.PublicKey, msgs ...lnwire.Message) error {
|
||||||
@@ -224,8 +341,12 @@ func createTestCtx(startHeight uint32) (*testCtx, func(), error) {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
SendMessages: nil,
|
SendToPeer: func(target *btcec.PublicKey, msg ...lnwire.Message) error {
|
||||||
Router: router,
|
return nil
|
||||||
|
},
|
||||||
|
Router: router,
|
||||||
|
TrickleDelay: trickleDelay,
|
||||||
|
ProofMatureDelta: proofMatureDelta,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("unable to create router %v", err)
|
return nil, nil, fmt.Errorf("unable to create router %v", err)
|
||||||
@@ -255,21 +376,23 @@ func TestProcessAnnouncement(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
priv, err := btcec.NewPrivateKey(btcec.S256())
|
// Create node valid, signed announcement, process it with with
|
||||||
if err != nil {
|
// discovery service, check that valid announcement have been
|
||||||
t.Fatalf("can't create node pub key: %v", err)
|
// propagated farther into the lightning network, and check that we
|
||||||
}
|
// added new node into router.
|
||||||
nodePub := priv.PubKey()
|
na, err := createNodeAnnouncement(nodeKeyPriv1)
|
||||||
|
|
||||||
na, err := createNodeAnnouncement()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("can't create node announcement: %v", err)
|
t.Fatalf("can't create node announcement: %v", err)
|
||||||
}
|
}
|
||||||
ctx.discovery.ProcessRemoteAnnouncement(na, nodePub)
|
|
||||||
|
err = <-ctx.discovery.ProcessRemoteAnnouncement(na, na.NodeID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("can't process remote announcement: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-ctx.broadcastedMessage:
|
case <-ctx.broadcastedMessage:
|
||||||
case <-time.After(time.Second):
|
case <-time.After(2 * trickleDelay):
|
||||||
t.Fatal("announcememt wasn't proceeded")
|
t.Fatal("announcememt wasn't proceeded")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,32 +400,54 @@ func TestProcessAnnouncement(t *testing.T) {
|
|||||||
t.Fatalf("node wasn't added to router: %v", err)
|
t.Fatalf("node wasn't added to router: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ca := createChannelAnnouncement(0)
|
// Pretending that we receive the valid channel announcement from
|
||||||
ctx.discovery.ProcessRemoteAnnouncement(ca, nodePub)
|
// remote side, and check that we broadcasted it to the our network,
|
||||||
|
// and added channel info in the router.
|
||||||
|
ca, err := createRemoteChannelAnnouncement(0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("can't create channel announcement: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = <-ctx.discovery.ProcessRemoteAnnouncement(ca, na.NodeID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("can't process remote announcement: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-ctx.broadcastedMessage:
|
case <-ctx.broadcastedMessage:
|
||||||
case <-time.After(time.Second):
|
case <-time.After(2 * trickleDelay):
|
||||||
|
t.Fatal("announcememt wasn't proceeded")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ctx.router.infos) != 1 {
|
||||||
|
t.Fatalf("edge wasn't added to router: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pretending that we received valid channel policy update from remote
|
||||||
|
// side, and check that we broadcasted it to the other network, and
|
||||||
|
// added updates to the router.
|
||||||
|
ua, err := createUpdateAnnouncement(0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("can't create update announcement: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = <-ctx.discovery.ProcessRemoteAnnouncement(ua, na.NodeID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("can't process remote announcement: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.broadcastedMessage:
|
||||||
|
case <-time.After(2 * trickleDelay):
|
||||||
t.Fatal("announcememt wasn't proceeded")
|
t.Fatal("announcememt wasn't proceeded")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(ctx.router.edges) != 1 {
|
if len(ctx.router.edges) != 1 {
|
||||||
t.Fatalf("edge wasn't added to router: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ua := createUpdateAnnouncement(0)
|
|
||||||
ctx.discovery.ProcessRemoteAnnouncement(ua, nodePub)
|
|
||||||
select {
|
|
||||||
case <-ctx.broadcastedMessage:
|
|
||||||
case <-time.After(time.Second):
|
|
||||||
t.Fatal("announcememt wasn't proceeded")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(ctx.router.updates) != 1 {
|
|
||||||
t.Fatalf("edge update wasn't added to router: %v", err)
|
t.Fatalf("edge update wasn't added to router: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestPrematureAnnouncement checks that premature networkMsgs are
|
// TestPrematureAnnouncement checks that premature announcements are
|
||||||
// not propagated to the router subsystem until block with according
|
// not propagated to the router subsystem until block with according
|
||||||
// block height received.
|
// block height received.
|
||||||
func TestPrematureAnnouncement(t *testing.T) {
|
func TestPrematureAnnouncement(t *testing.T) {
|
||||||
@@ -312,62 +457,150 @@ func TestPrematureAnnouncement(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
priv, err := btcec.NewPrivateKey(btcec.S256())
|
na, err := createNodeAnnouncement(nodeKeyPriv1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("can't create node pub key: %v", err)
|
t.Fatalf("can't create node announcement: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pretending that we receive the valid channel announcement from
|
||||||
|
// remote side, but block height of this announcement is greater than
|
||||||
|
// highest know to us, for that reason it should be added to the
|
||||||
|
// repeat/premature batch.
|
||||||
|
ca, err := createRemoteChannelAnnouncement(1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("can't create channel announcement: %v", err)
|
||||||
}
|
}
|
||||||
nodePub := priv.PubKey()
|
|
||||||
|
|
||||||
ca := createChannelAnnouncement(1)
|
|
||||||
ctx.discovery.ProcessRemoteAnnouncement(ca, nodePub)
|
|
||||||
select {
|
select {
|
||||||
case <-ctx.broadcastedMessage:
|
case <-ctx.discovery.ProcessRemoteAnnouncement(ca, na.NodeID):
|
||||||
|
t.Fatal("announcement was proceeded")
|
||||||
|
case <-time.After(100 * time.Millisecond):
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ctx.router.infos) != 0 {
|
||||||
|
t.Fatal("edge was added to router")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pretending that we receive the valid channel update announcement from
|
||||||
|
// remote side, but block height of this announcement is greater than
|
||||||
|
// highest know to us, for that reason it should be added to the
|
||||||
|
// repeat/premature batch.
|
||||||
|
ua, err := createUpdateAnnouncement(1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("can't create update announcement: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.discovery.ProcessRemoteAnnouncement(ua, na.NodeID):
|
||||||
t.Fatal("announcement was proceeded")
|
t.Fatal("announcement was proceeded")
|
||||||
case <-time.After(100 * time.Millisecond):
|
case <-time.After(100 * time.Millisecond):
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(ctx.router.edges) != 0 {
|
if len(ctx.router.edges) != 0 {
|
||||||
t.Fatal("edge was added to router")
|
|
||||||
}
|
|
||||||
|
|
||||||
ua := createUpdateAnnouncement(1)
|
|
||||||
ctx.discovery.ProcessRemoteAnnouncement(ua, nodePub)
|
|
||||||
select {
|
|
||||||
case <-ctx.broadcastedMessage:
|
|
||||||
t.Fatal("announcement was proceeded")
|
|
||||||
case <-time.After(100 * time.Millisecond):
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(ctx.router.updates) != 0 {
|
|
||||||
t.Fatal("edge update was added to router")
|
t.Fatal("edge update was added to router")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate new block and waiting the previously added announcements
|
||||||
|
// to be proceeded.
|
||||||
newBlock := &wire.MsgBlock{}
|
newBlock := &wire.MsgBlock{}
|
||||||
ctx.notifier.notifyBlock(newBlock.Header.BlockHash(), 1)
|
ctx.notifier.notifyBlock(newBlock.Header.BlockHash(), 1)
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-ctx.broadcastedMessage:
|
case <-ctx.broadcastedMessage:
|
||||||
if err != nil {
|
case <-time.After(2 * trickleDelay):
|
||||||
t.Fatalf("announcememt was proceeded with err: %v", err)
|
t.Fatal("announcememt wasn't broadcasted")
|
||||||
}
|
|
||||||
case <-time.After(time.Second):
|
|
||||||
t.Fatal("announcememt wasn't proceeded")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(ctx.router.edges) != 1 {
|
if len(ctx.router.infos) != 1 {
|
||||||
t.Fatalf("edge was't added to router: %v", err)
|
t.Fatalf("edge was't added to router: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-ctx.broadcastedMessage:
|
case <-ctx.broadcastedMessage:
|
||||||
if err != nil {
|
case <-time.After(2 * trickleDelay):
|
||||||
t.Fatalf("announcememt was proceeded with err: %v", err)
|
t.Fatal("announcememt wasn't broadcasted")
|
||||||
}
|
|
||||||
case <-time.After(time.Second):
|
|
||||||
t.Fatal("announcememt wasn't proceeded")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(ctx.router.updates) != 1 {
|
if len(ctx.router.edges) != 1 {
|
||||||
t.Fatalf("edge update wasn't added to router: %v", err)
|
t.Fatalf("edge update wasn't added to router: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestSignatureAnnouncement....
|
||||||
|
func TestSignatureAnnouncement(t *testing.T) {
|
||||||
|
ctx, cleanup, err := createTestCtx(proofMatureDelta)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("can't create context: %v", err)
|
||||||
|
}
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
batch, err := createAnnouncements(0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("can't generate announcements: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
localKey := batch.nodeAnn1.NodeID
|
||||||
|
remoteKey := batch.nodeAnn2.NodeID
|
||||||
|
|
||||||
|
// Recreate lightning network topology. Initialize router with
|
||||||
|
// channel between two nodes.
|
||||||
|
err = <-ctx.discovery.ProcessLocalAnnouncement(batch.localChanAnn, localKey)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to process :%v", err)
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-ctx.broadcastedMessage:
|
||||||
|
t.Fatal("channel announcement was broadcasted")
|
||||||
|
case <-time.After(2 * trickleDelay):
|
||||||
|
}
|
||||||
|
|
||||||
|
err = <-ctx.discovery.ProcessLocalAnnouncement(batch.chanUpdAnn, localKey)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to process :%v", err)
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-ctx.broadcastedMessage:
|
||||||
|
t.Fatal("channel update announcement was broadcasted")
|
||||||
|
case <-time.After(2 * trickleDelay):
|
||||||
|
}
|
||||||
|
|
||||||
|
err = <-ctx.discovery.ProcessRemoteAnnouncement(batch.chanUpdAnn, remoteKey)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to process :%v", err)
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-ctx.broadcastedMessage:
|
||||||
|
t.Fatal("channel update announcement was broadcasted")
|
||||||
|
case <-time.After(2 * trickleDelay):
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pretending that we receive local channel announcement from funding
|
||||||
|
// manager, thereby kick off the announcement exchange process.
|
||||||
|
err = <-ctx.discovery.ProcessLocalAnnouncement(batch.localProofAnn, localKey)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to process :%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.broadcastedMessage:
|
||||||
|
t.Fatal("announcements were broadcasted")
|
||||||
|
case <-time.After(2 * trickleDelay):
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ctx.discovery.waitingProofs) != 1 {
|
||||||
|
t.Fatal("local proof annoucement should be stored")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = <-ctx.discovery.ProcessRemoteAnnouncement(batch.remoteProofAnn, remoteKey)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to process :%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
select {
|
||||||
|
case <-ctx.broadcastedMessage:
|
||||||
|
case <-time.After(time.Second):
|
||||||
|
t.Fatal("announcement wasn't broadcasted")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
package discovery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// newProofKey constructs new announcement signature message key.
|
||||||
|
func newProofKey(chanID uint64, isRemote bool) waitingProofKey {
|
||||||
|
return waitingProofKey{
|
||||||
|
chanID: chanID,
|
||||||
|
isRemote: isRemote,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToBytes represents the key in the byte format.
|
||||||
|
func (k waitingProofKey) ToBytes() []byte {
|
||||||
|
var key [10]byte
|
||||||
|
|
||||||
|
var b uint8
|
||||||
|
if k.isRemote {
|
||||||
|
b = 0
|
||||||
|
} else {
|
||||||
|
b = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
binary.BigEndian.PutUint64(key[:], k.chanID)
|
||||||
|
key[9] = b
|
||||||
|
|
||||||
|
return key[:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// createChanAnnouncement helper function which creates the channel announcement
|
||||||
|
// by the given channeldb objects.
|
||||||
|
func createChanAnnouncement(chanProof *channeldb.ChannelAuthProof,
|
||||||
|
chanInfo *channeldb.ChannelEdgeInfo,
|
||||||
|
e1, e2 *channeldb.ChannelEdgePolicy) (
|
||||||
|
*lnwire.ChannelAnnouncement,
|
||||||
|
*lnwire.ChannelUpdateAnnouncement,
|
||||||
|
*lnwire.ChannelUpdateAnnouncement) {
|
||||||
|
// First, using the parameters of the channel, along with the
|
||||||
|
// channel authentication chanProof, we'll create re-create the
|
||||||
|
// original authenticated channel announcement.
|
||||||
|
chanID := lnwire.NewShortChanIDFromInt(chanInfo.ChannelID)
|
||||||
|
chanAnn := &lnwire.ChannelAnnouncement{
|
||||||
|
NodeSig1: chanProof.NodeSig1,
|
||||||
|
NodeSig2: chanProof.NodeSig2,
|
||||||
|
ShortChannelID: chanID,
|
||||||
|
BitcoinSig1: chanProof.BitcoinSig1,
|
||||||
|
BitcoinSig2: chanProof.BitcoinSig2,
|
||||||
|
NodeID1: chanInfo.NodeKey1,
|
||||||
|
NodeID2: chanInfo.NodeKey2,
|
||||||
|
BitcoinKey1: chanInfo.BitcoinKey1,
|
||||||
|
BitcoinKey2: chanInfo.BitcoinKey2,
|
||||||
|
}
|
||||||
|
|
||||||
|
// We'll unconditionally queue the channel's existence chanProof as
|
||||||
|
// it will need to be processed before either of the channel
|
||||||
|
// update networkMsgs.
|
||||||
|
|
||||||
|
// Since it's up to a node's policy as to whether they
|
||||||
|
// advertise the edge in dire direction, we don't create an
|
||||||
|
// advertisement if the edge is nil.
|
||||||
|
var edge1Ann, edge2Ann *lnwire.ChannelUpdateAnnouncement
|
||||||
|
if e1 != nil {
|
||||||
|
edge1Ann = &lnwire.ChannelUpdateAnnouncement{
|
||||||
|
Signature: e1.Signature,
|
||||||
|
ShortChannelID: chanID,
|
||||||
|
Timestamp: uint32(e1.LastUpdate.Unix()),
|
||||||
|
Flags: 0,
|
||||||
|
TimeLockDelta: e1.TimeLockDelta,
|
||||||
|
HtlcMinimumMsat: uint32(e1.MinHTLC),
|
||||||
|
FeeBaseMsat: uint32(e1.FeeBaseMSat),
|
||||||
|
FeeProportionalMillionths: uint32(e1.FeeProportionalMillionths),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if e2 != nil {
|
||||||
|
edge2Ann = &lnwire.ChannelUpdateAnnouncement{
|
||||||
|
Signature: e2.Signature,
|
||||||
|
ShortChannelID: chanID,
|
||||||
|
Timestamp: uint32(e2.LastUpdate.Unix()),
|
||||||
|
Flags: 1,
|
||||||
|
TimeLockDelta: e2.TimeLockDelta,
|
||||||
|
HtlcMinimumMsat: uint32(e2.MinHTLC),
|
||||||
|
FeeBaseMsat: uint32(e2.FeeBaseMSat),
|
||||||
|
FeeProportionalMillionths: uint32(e2.FeeProportionalMillionths),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return chanAnn, edge1Ann, edge2Ann
|
||||||
|
}
|
||||||
+80
-58
@@ -2,7 +2,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
@@ -141,9 +140,18 @@ type fundingConfig struct {
|
|||||||
// so that the channel creation process can be completed.
|
// so that the channel creation process can be completed.
|
||||||
Notifier chainntnfs.ChainNotifier
|
Notifier chainntnfs.ChainNotifier
|
||||||
|
|
||||||
|
// SignNodeKey is used to generate signature for node public key with
|
||||||
|
// funding keys.
|
||||||
|
SignNodeKey func(nodeKey, fundingKey *btcec.PublicKey) (*btcec.Signature, error)
|
||||||
|
|
||||||
|
// SignAnnouncement is used to generate the signatures for channel
|
||||||
|
// update, and node announcements, and also to generate the proof for
|
||||||
|
// the channel announcement.
|
||||||
|
SignAnnouncement func(msg lnwire.Message) (*btcec.Signature, error)
|
||||||
|
|
||||||
// SendToDiscovery is used by the FundingManager to announce newly created
|
// SendToDiscovery is used by the FundingManager to announce newly created
|
||||||
// channels to the rest of the Lightning Network.
|
// channels to the rest of the Lightning Network.
|
||||||
SendToDiscovery func(msg lnwire.Message)
|
SendToDiscovery func(msg lnwire.Message) error
|
||||||
|
|
||||||
// SendToPeer allows the FundingManager to send messages to the peer
|
// SendToPeer allows the FundingManager to send messages to the peer
|
||||||
// node during the multiple steps involved in the creation of the
|
// node during the multiple steps involved in the creation of the
|
||||||
@@ -202,8 +210,6 @@ type fundingManager struct {
|
|||||||
barrierMtx sync.RWMutex
|
barrierMtx sync.RWMutex
|
||||||
newChanBarriers map[wire.OutPoint]chan struct{}
|
newChanBarriers map[wire.OutPoint]chan struct{}
|
||||||
|
|
||||||
fakeProof *channelProof
|
|
||||||
|
|
||||||
quit chan struct{}
|
quit chan struct{}
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
}
|
}
|
||||||
@@ -211,22 +217,8 @@ type fundingManager struct {
|
|||||||
// newFundingManager creates and initializes a new instance of the
|
// newFundingManager creates and initializes a new instance of the
|
||||||
// fundingManager.
|
// fundingManager.
|
||||||
func newFundingManager(cfg fundingConfig) (*fundingManager, error) {
|
func newFundingManager(cfg fundingConfig) (*fundingManager, error) {
|
||||||
// TODO(roasbeef): remove once we actually sign the funding_locked
|
|
||||||
// stuffs
|
|
||||||
s := "30450221008ce2bc69281ce27da07e6683571319d18e949ddfa2965fb6caa" +
|
|
||||||
"1bf0314f882d70220299105481d63e0f4bc2a88121167221b6700d72a0e" +
|
|
||||||
"ad154c03be696a292d24ae"
|
|
||||||
fakeSigHex, _ := hex.DecodeString(s)
|
|
||||||
fakeSig, _ := btcec.ParseSignature(fakeSigHex, btcec.S256())
|
|
||||||
|
|
||||||
return &fundingManager{
|
return &fundingManager{
|
||||||
cfg: &cfg,
|
cfg: &cfg,
|
||||||
|
|
||||||
fakeProof: &channelProof{
|
|
||||||
nodeSig: fakeSig,
|
|
||||||
bitcoinSig: fakeSig,
|
|
||||||
},
|
|
||||||
|
|
||||||
activeReservations: make(map[serializedPubKey]pendingChannels),
|
activeReservations: make(map[serializedPubKey]pendingChannels),
|
||||||
newChanBarriers: make(map[wire.OutPoint]chan struct{}),
|
newChanBarriers: make(map[wire.OutPoint]chan struct{}),
|
||||||
fundingMsgs: make(chan interface{}, msgBufferSize),
|
fundingMsgs: make(chan interface{}, msgBufferSize),
|
||||||
@@ -998,8 +990,9 @@ func (f *fundingManager) handleFundingLocked(fmsg *fundingLockedMsg) {
|
|||||||
// Register the new link with the L3 routing manager so this
|
// Register the new link with the L3 routing manager so this
|
||||||
// new channel can be utilized during path
|
// new channel can be utilized during path
|
||||||
// finding.
|
// finding.
|
||||||
go f.announceChannel(f.cfg.IDKey, fmsg.peerAddress.IdentityKey, channel,
|
go f.announceChannel(f.cfg.IDKey, fmsg.peerAddress.IdentityKey,
|
||||||
fmsg.msg.ChannelID, f.fakeProof, f.fakeProof)
|
channel.LocalFundingKey, channel.RemoteFundingKey,
|
||||||
|
fmsg.msg.ChannelID, fundingPoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
// channelProof is one half of the proof necessary to create an authenticated
|
// channelProof is one half of the proof necessary to create an authenticated
|
||||||
@@ -1013,8 +1006,9 @@ type channelProof struct {
|
|||||||
// chanAnnouncement encapsulates the two authenticated announcements that we
|
// chanAnnouncement encapsulates the two authenticated announcements that we
|
||||||
// send out to the network after a new channel has been created locally.
|
// send out to the network after a new channel has been created locally.
|
||||||
type chanAnnouncement struct {
|
type chanAnnouncement struct {
|
||||||
chanAnn *lnwire.ChannelAnnouncement
|
chanAnn *lnwire.ChannelAnnouncement
|
||||||
edgeUpdate *lnwire.ChannelUpdateAnnouncement
|
chanUpdateAnn *lnwire.ChannelUpdateAnnouncement
|
||||||
|
chanProof *lnwire.AnnounceSignatures
|
||||||
}
|
}
|
||||||
|
|
||||||
// newChanAnnouncement creates the authenticated channel announcement messages
|
// newChanAnnouncement creates the authenticated channel announcement messages
|
||||||
@@ -1024,11 +1018,12 @@ type chanAnnouncement struct {
|
|||||||
// identity pub keys of both parties to the channel, and the second segment is
|
// identity pub keys of both parties to the channel, and the second segment is
|
||||||
// authenticated only by us and contains our directional routing policy for the
|
// authenticated only by us and contains our directional routing policy for the
|
||||||
// channel.
|
// channel.
|
||||||
func newChanAnnouncement(localIdentity, remotePub *btcec.PublicKey,
|
func (f *fundingManager) newChanAnnouncement(localPubKey, remotePubKey *btcec.PublicKey,
|
||||||
channel *lnwallet.LightningChannel, chanID lnwire.ShortChannelID,
|
localFundingKey, remoteFundingKey *btcec.PublicKey, chanID lnwire.ShortChannelID,
|
||||||
localProof, remoteProof *channelProof) *chanAnnouncement {
|
chanPoint wire.OutPoint) (*chanAnnouncement, error) {
|
||||||
|
var err error
|
||||||
|
|
||||||
// The unconditional section of the announcement is the ChannelID
|
// The unconditional section of the announcement is the ShortChannelID
|
||||||
// itself which compactly encodes the location of the funding output
|
// itself which compactly encodes the location of the funding output
|
||||||
// within the blockchain.
|
// within the blockchain.
|
||||||
chanAnn := &lnwire.ChannelAnnouncement{
|
chanAnn := &lnwire.ChannelAnnouncement{
|
||||||
@@ -1045,30 +1040,22 @@ func newChanAnnouncement(localIdentity, remotePub *btcec.PublicKey,
|
|||||||
// nodes indicates which of the nodes is "first". If our serialized
|
// nodes indicates which of the nodes is "first". If our serialized
|
||||||
// identity key is lower than theirs then we're the "first" node and
|
// identity key is lower than theirs then we're the "first" node and
|
||||||
// second otherwise.
|
// second otherwise.
|
||||||
selfBytes := localIdentity.SerializeCompressed()
|
selfBytes := localPubKey.SerializeCompressed()
|
||||||
remoteBytes := remotePub.SerializeCompressed()
|
remoteBytes := remotePubKey.SerializeCompressed()
|
||||||
if bytes.Compare(selfBytes, remoteBytes) == -1 {
|
if bytes.Compare(selfBytes, remoteBytes) == -1 {
|
||||||
chanAnn.NodeID1 = localIdentity
|
chanAnn.NodeID1 = localPubKey
|
||||||
chanAnn.NodeID2 = remotePub
|
chanAnn.NodeID2 = remotePubKey
|
||||||
chanAnn.NodeSig1 = localProof.nodeSig
|
chanAnn.BitcoinKey1 = localFundingKey
|
||||||
chanAnn.NodeSig2 = remoteProof.nodeSig
|
chanAnn.BitcoinKey2 = remoteFundingKey
|
||||||
chanAnn.BitcoinSig1 = localProof.nodeSig
|
|
||||||
chanAnn.BitcoinSig2 = remoteProof.nodeSig
|
|
||||||
chanAnn.BitcoinKey1 = channel.LocalFundingKey
|
|
||||||
chanAnn.BitcoinKey2 = channel.RemoteFundingKey
|
|
||||||
|
|
||||||
// If we're the first node then update the chanFlags to
|
// If we're the first node then update the chanFlags to
|
||||||
// indicate the "direction" of the update.
|
// indicate the "direction" of the update.
|
||||||
chanFlags = 0
|
chanFlags = 0
|
||||||
} else {
|
} else {
|
||||||
chanAnn.NodeID1 = remotePub
|
chanAnn.NodeID1 = remotePubKey
|
||||||
chanAnn.NodeID2 = localIdentity
|
chanAnn.NodeID2 = localPubKey
|
||||||
chanAnn.NodeSig1 = remoteProof.nodeSig
|
chanAnn.BitcoinKey1 = remoteFundingKey
|
||||||
chanAnn.NodeSig2 = localProof.nodeSig
|
chanAnn.BitcoinKey2 = localFundingKey
|
||||||
chanAnn.BitcoinSig1 = remoteProof.nodeSig
|
|
||||||
chanAnn.BitcoinSig2 = localProof.nodeSig
|
|
||||||
chanAnn.BitcoinKey1 = channel.RemoteFundingKey
|
|
||||||
chanAnn.BitcoinKey2 = channel.LocalFundingKey
|
|
||||||
|
|
||||||
// If we're the second node then update the chanFlags to
|
// If we're the second node then update the chanFlags to
|
||||||
// indicate the "direction" of the update.
|
// indicate the "direction" of the update.
|
||||||
@@ -1077,7 +1064,6 @@ func newChanAnnouncement(localIdentity, remotePub *btcec.PublicKey,
|
|||||||
|
|
||||||
// TODO(roasbeef): add real sig, populate proper FeeSchema
|
// TODO(roasbeef): add real sig, populate proper FeeSchema
|
||||||
chanUpdateAnn := &lnwire.ChannelUpdateAnnouncement{
|
chanUpdateAnn := &lnwire.ChannelUpdateAnnouncement{
|
||||||
Signature: localProof.nodeSig,
|
|
||||||
ShortChannelID: chanID,
|
ShortChannelID: chanID,
|
||||||
Timestamp: uint32(time.Now().Unix()),
|
Timestamp: uint32(time.Now().Unix()),
|
||||||
Flags: chanFlags,
|
Flags: chanFlags,
|
||||||
@@ -1087,10 +1073,40 @@ func newChanAnnouncement(localIdentity, remotePub *btcec.PublicKey,
|
|||||||
FeeProportionalMillionths: 0,
|
FeeProportionalMillionths: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
return &chanAnnouncement{
|
chanUpdateAnn.Signature, err = f.cfg.SignAnnouncement(chanUpdateAnn)
|
||||||
chanAnn: chanAnn,
|
if err != nil {
|
||||||
edgeUpdate: chanUpdateAnn,
|
return nil, errors.Errorf("unable to generate channel "+
|
||||||
|
"update announcement signature: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Channel proof should be announced in the separate message, so we
|
||||||
|
// already have the bitcoin signature but in order to construct
|
||||||
|
// the proof we also need node signature. Use message signer in order
|
||||||
|
// to sign the message with node private key.
|
||||||
|
nodeSig, err := f.cfg.SignAnnouncement(chanAnn)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Errorf("unable to generate node "+
|
||||||
|
"signature for channel announcement: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
bitcoinSig, err := f.cfg.SignNodeKey(localPubKey, localFundingKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Errorf("unable to generate bitcoin "+
|
||||||
|
"signature for node public key: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
proof := &lnwire.AnnounceSignatures{
|
||||||
|
ChannelID: chanPoint,
|
||||||
|
ShortChannelID: chanID,
|
||||||
|
NodeSignature: nodeSig,
|
||||||
|
BitcoinSignature: bitcoinSig,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &chanAnnouncement{
|
||||||
|
chanAnn: chanAnn,
|
||||||
|
chanUpdateAnn: chanUpdateAnn,
|
||||||
|
chanProof: proof,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// announceChannel announces a newly created channel to the rest of the network
|
// announceChannel announces a newly created channel to the rest of the network
|
||||||
@@ -1098,17 +1114,23 @@ func newChanAnnouncement(localIdentity, remotePub *btcec.PublicKey,
|
|||||||
// network to recognize the legitimacy of the channel. The crafted
|
// network to recognize the legitimacy of the channel. The crafted
|
||||||
// announcements are then send to the channel router to handle broadcasting to
|
// announcements are then send to the channel router to handle broadcasting to
|
||||||
// the network during its next trickle.
|
// the network during its next trickle.
|
||||||
func (f *fundingManager) announceChannel(idKey, remoteIDKey *btcec.PublicKey,
|
func (f *fundingManager) announceChannel(localIDKey, remoteIDKey *btcec.PublicKey,
|
||||||
channel *lnwallet.LightningChannel, chanID lnwire.ShortChannelID, localProof,
|
localFundingKey, remoteFundingKey *btcec.PublicKey, chanID lnwire.ShortChannelID,
|
||||||
remoteProof *channelProof) {
|
chanPoint wire.OutPoint) {
|
||||||
|
|
||||||
// TODO(roasbeef): need a Signer.SignMessage method to finalize
|
ann, err := f.newChanAnnouncement(localIDKey, remoteIDKey, localFundingKey,
|
||||||
// advertisements
|
remoteFundingKey, chanID, chanPoint)
|
||||||
chanAnnouncement := newChanAnnouncement(idKey, remoteIDKey, channel, chanID,
|
if err != nil {
|
||||||
localProof, remoteProof)
|
fndgLog.Errorf("can't generate channel announcement: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
f.cfg.SendToDiscovery(chanAnnouncement.chanAnn)
|
fndgLog.Infof("Send channel, channel update, and proof announcements"+
|
||||||
f.cfg.SendToDiscovery(chanAnnouncement.edgeUpdate)
|
" for chanID=%v, shortChannelID=%v to discovery service",
|
||||||
|
chanPoint, chanID.ToUint64())
|
||||||
|
f.cfg.SendToDiscovery(ann.chanAnn)
|
||||||
|
f.cfg.SendToDiscovery(ann.chanUpdateAnn)
|
||||||
|
f.cfg.SendToDiscovery(ann.chanProof)
|
||||||
}
|
}
|
||||||
|
|
||||||
// initFundingWorkflow sends a message to the funding manager instructing it
|
// initFundingWorkflow sends a message to the funding manager instructing it
|
||||||
|
|||||||
@@ -494,12 +494,15 @@ out:
|
|||||||
isChanUpdate = true
|
isChanUpdate = true
|
||||||
targetChan = msg.ChannelPoint
|
targetChan = msg.ChannelPoint
|
||||||
|
|
||||||
case *lnwire.NodeAnnouncement,
|
case *lnwire.ChannelUpdateAnnouncement,
|
||||||
*lnwire.ChannelAnnouncement,
|
*lnwire.ChannelAnnouncement,
|
||||||
*lnwire.ChannelUpdateAnnouncement:
|
*lnwire.NodeAnnouncement,
|
||||||
|
*lnwire.AnnounceSignatures:
|
||||||
|
|
||||||
p.server.discoverSrv.ProcessRemoteAnnouncement(msg,
|
p.server.discoverSrv.ProcessRemoteAnnouncement(msg,
|
||||||
p.addr.IdentityKey)
|
p.addr.IdentityKey)
|
||||||
|
default:
|
||||||
|
peerLog.Errorf("unknown message received from peer "+"%v", p)
|
||||||
}
|
}
|
||||||
|
|
||||||
if isChanUpdate {
|
if isChanUpdate {
|
||||||
|
|||||||
@@ -168,8 +168,23 @@ func newServer(listenAddrs []string, notifier chainntnfs.ChainNotifier,
|
|||||||
selfAddrs = append(selfAddrs, addr)
|
selfAddrs = append(selfAddrs, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(roasbeef): remove once we actually sign the funding_locked
|
||||||
|
// stuffs
|
||||||
|
fakeSigHex, err := hex.DecodeString("30450221008ce2bc69281ce27da07e66" +
|
||||||
|
"83571319d18e949ddfa2965fb6caa1bf0314f882d70220299105481d63e0f" +
|
||||||
|
"4bc2a88121167221b6700d72a0ead154c03be696a292d24ae")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fakeSig, err := btcec.ParseSignature(fakeSigHex, btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
chanGraph := chanDB.ChannelGraph()
|
chanGraph := chanDB.ChannelGraph()
|
||||||
self := &channeldb.LightningNode{
|
self := &channeldb.LightningNode{
|
||||||
|
AuthSig: fakeSig,
|
||||||
LastUpdate: time.Now(),
|
LastUpdate: time.Now(),
|
||||||
Addresses: selfAddrs,
|
Addresses: selfAddrs,
|
||||||
PubKey: privKey.PubKey(),
|
PubKey: privKey.PubKey(),
|
||||||
@@ -202,10 +217,12 @@ func newServer(listenAddrs []string, notifier chainntnfs.ChainNotifier,
|
|||||||
}
|
}
|
||||||
|
|
||||||
s.discoverSrv, err = discovery.New(discovery.Config{
|
s.discoverSrv, err = discovery.New(discovery.Config{
|
||||||
Broadcast: s.broadcastMessage,
|
Broadcast: s.broadcastMessage,
|
||||||
Notifier: s.chainNotifier,
|
Notifier: s.chainNotifier,
|
||||||
Router: s.chanRouter,
|
Router: s.chanRouter,
|
||||||
SendMessages: s.sendToPeer,
|
SendToPeer: s.sendToPeer,
|
||||||
|
TrickleDelay: time.Millisecond * 300,
|
||||||
|
ProofMatureDelta: 0,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -218,8 +235,16 @@ func newServer(listenAddrs []string, notifier chainntnfs.ChainNotifier,
|
|||||||
IDKey: s.identityPriv.PubKey(),
|
IDKey: s.identityPriv.PubKey(),
|
||||||
Wallet: wallet,
|
Wallet: wallet,
|
||||||
Notifier: s.chainNotifier,
|
Notifier: s.chainNotifier,
|
||||||
SendToDiscovery: func(msg lnwire.Message) {
|
SignNodeKey: func(nodeKey, fundingKey *btcec.PublicKey) (*btcec.Signature,
|
||||||
s.discoverSrv.ProcessLocalAnnouncement(msg,
|
error) {
|
||||||
|
return fakeSig, nil
|
||||||
|
},
|
||||||
|
SignAnnouncement: func(msg lnwire.Message) (*btcec.Signature,
|
||||||
|
error) {
|
||||||
|
return fakeSig, nil
|
||||||
|
},
|
||||||
|
SendToDiscovery: func(msg lnwire.Message) chan error {
|
||||||
|
return s.discoverSrv.ProcessLocalAnnouncement(msg,
|
||||||
s.identityPriv.PubKey())
|
s.identityPriv.PubKey())
|
||||||
},
|
},
|
||||||
ArbiterChan: s.breachArbiter.newContracts,
|
ArbiterChan: s.breachArbiter.newContracts,
|
||||||
|
|||||||
Reference in new issue
Block a user