From 7252dbd934417acf4353fa6df5fad90a9bda35db Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 28 Feb 2018 23:29:49 +0100 Subject: [PATCH 1/5] funding: add missing mutex around activeReservations --- fundingmanager.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fundingmanager.go b/fundingmanager.go index 7c17fb3a..e1e98872 100644 --- a/fundingmanager.go +++ b/fundingmanager.go @@ -835,12 +835,15 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) { // TODO(roasbeef): modify to only accept a _single_ pending channel per // block unless white listed + f.resMtx.RLock() if len(f.activeReservations[peerIDKey]) >= cfg.MaxPendingChannels { + f.resMtx.RUnlock() f.failFundingFlow( fmsg.peerAddress.IdentityKey, fmsg.msg.PendingChannelID, lnwire.ErrMaxPendingChannels) return } + f.resMtx.RUnlock() // We'll also reject any requests to create channels until we're fully // synced to the network as we won't be able to properly validate the From f1f1a38663c1c8d4f3288f2fd131884dd5609d91 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 28 Feb 2018 23:35:03 +0100 Subject: [PATCH 2/5] funding: add method IsPendingChannel --- fundingmanager.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/fundingmanager.go b/fundingmanager.go index e1e98872..a9784f0a 100644 --- a/fundingmanager.go +++ b/fundingmanager.go @@ -2639,6 +2639,22 @@ func (f *fundingManager) getReservationCtx(peerKey *btcec.PublicKey, return resCtx, nil } +// IsPendingChannel returns a boolean indicating whether the channel identified +// by the pendingChanID and given peer is pending, meaning it is in the process +// of being funded. After the funding transaction has been confirmed, the +// channel will receive a new, permanent channel ID, and will no longer be +// considered pending. +func (f *fundingManager) IsPendingChannel(pendingChanID [32]byte, + peerAddress *lnwire.NetAddress) bool { + + peerIDKey := newSerializedKey(peerAddress.IdentityKey) + f.resMtx.RLock() + _, ok := f.activeReservations[peerIDKey][pendingChanID] + f.resMtx.RUnlock() + + return ok +} + func copyPubKey(pub *btcec.PublicKey) *btcec.PublicKey { return &btcec.PublicKey{ Curve: btcec.S256(), From 33762e0f81b8d8b4017ffd58fe3f79764be4615a Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Thu, 1 Mar 2018 00:39:26 +0100 Subject: [PATCH 3/5] htlcswitch/link: fail channel on lnwire.Error --- htlcswitch/link.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 528dd353..e84d43b1 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -1319,7 +1319,21 @@ func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) { l.fail("error receiving fee update: %v", err) return } + case *lnwire.Error: + // Error received from remote, MUST fail channel, but should + // only print the contents of the error message if all + // characters are printable ASCII. + errMsg := "non-ascii data" + if isASCII(msg.Data) { + errMsg = string(msg.Data) + } + l.fail("ChannelPoint(%v): recieved error from peer: %v", + l.channel.ChannelPoint(), errMsg) + default: + log.Warnf("ChannelPoint(%v): received unknown message of type %T", + l.channel.ChannelPoint(), msg) } + } // ackDownStreamPackets is responsible for removing htlcs from a link's @@ -2407,3 +2421,16 @@ func (l *channelLink) tracef(format string, a ...interface{}) { msg := fmt.Sprintf(format, a...) log.Tracef("ChannelLink(%s) %s", l.ShortChanID(), msg) } + +// isASCII is a helper method that checks whether all bytes in `data` would be +// printable ASCII characters if interpreted as a string. +func isASCII(data []byte) bool { + isASCII := true + for _, c := range data { + if c < 32 || c > 126 { + isASCII = false + break + } + } + return isASCII +} From 80ef16e8538a80111e62e2d43ba2f089d71ddef6 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Thu, 1 Mar 2018 00:40:32 +0100 Subject: [PATCH 4/5] peer: hand lnwire.Error to fndgMngr or link depending on chanID --- peer.go | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/peer.go b/peer.go index a0a5cc8b..cca99733 100644 --- a/peer.go +++ b/peer.go @@ -748,7 +748,27 @@ out: } case *lnwire.Error: - p.server.fundingMgr.processFundingError(msg, p.addr) + switch { + + // In the case of an all-zero channel ID we want to + // forward the error to all channels with this peer. + case msg.ChanID == lnwire.ConnectionWideID: + for _, chanStream := range chanMsgStreams { + chanStream.AddMsg(nextMsg) + } + + // If the channel ID for the error message corresponds + // to a pending channel, then the funding manager will + // handle the error. + case p.server.fundingMgr.IsPendingChannel(msg.ChanID, p.addr): + p.server.fundingMgr.processFundingError(msg, p.addr) + + // If not we hand the error to the channel link for + // this channel. + default: + isChanUpdate = true + targetChan = msg.ChanID + } // TODO(roasbeef): create ChanUpdater interface for the below case *lnwire.UpdateAddHTLC: From 300fb1af4ac13b8f754bfce17745865e5ed16162 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Sun, 11 Mar 2018 17:12:23 +0100 Subject: [PATCH 5/5] lnwire: define ConnectionWideID --- lnwire/channel_id.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lnwire/channel_id.go b/lnwire/channel_id.go index 827efbaa..3033f401 100644 --- a/lnwire/channel_id.go +++ b/lnwire/channel_id.go @@ -24,6 +24,10 @@ const ( // ChannelID can be calculated by XOR'ing the big-endian serialization of the type ChannelID [32]byte +// ConnectionWideID is an all-zero ChannelID, which is used to represent a +// message intended for all channels to to specific peer. +var ConnectionWideID = ChannelID{} + // String returns the string representation of the ChannelID. This is just the // hex string encoding of the ChannelID itself. func (c ChannelID) String() string {