Merge pull request #790 from halseth/wire-error-handoff

Wire error handoff
This commit is contained in:
Olaoluwa Osuntokun 2018-03-12 18:56:35 -07:00 committed by GitHub
commit f2b676e93c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 71 additions and 1 deletions

@ -855,12 +855,15 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) {
// TODO(roasbeef): modify to only accept a _single_ pending channel per // TODO(roasbeef): modify to only accept a _single_ pending channel per
// block unless white listed // block unless white listed
f.resMtx.RLock()
if len(f.activeReservations[peerIDKey]) >= cfg.MaxPendingChannels { if len(f.activeReservations[peerIDKey]) >= cfg.MaxPendingChannels {
f.resMtx.RUnlock()
f.failFundingFlow( f.failFundingFlow(
fmsg.peerAddress.IdentityKey, fmsg.msg.PendingChannelID, fmsg.peerAddress.IdentityKey, fmsg.msg.PendingChannelID,
lnwire.ErrMaxPendingChannels) lnwire.ErrMaxPendingChannels)
return return
} }
f.resMtx.RUnlock()
// We'll also reject any requests to create channels until we're fully // 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 // synced to the network as we won't be able to properly validate the
@ -2656,6 +2659,22 @@ func (f *fundingManager) getReservationCtx(peerKey *btcec.PublicKey,
return resCtx, nil 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 { func copyPubKey(pub *btcec.PublicKey) *btcec.PublicKey {
return &btcec.PublicKey{ return &btcec.PublicKey{
Curve: btcec.S256(), Curve: btcec.S256(),

@ -1319,7 +1319,21 @@ func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) {
l.fail("error receiving fee update: %v", err) l.fail("error receiving fee update: %v", err)
return 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 // 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...) msg := fmt.Sprintf(format, a...)
log.Tracef("ChannelLink(%s) %s", l.ShortChanID(), msg) 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
}

@ -24,6 +24,10 @@ const (
// ChannelID can be calculated by XOR'ing the big-endian serialization of the // ChannelID can be calculated by XOR'ing the big-endian serialization of the
type ChannelID [32]byte 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 // String returns the string representation of the ChannelID. This is just the
// hex string encoding of the ChannelID itself. // hex string encoding of the ChannelID itself.
func (c ChannelID) String() string { func (c ChannelID) String() string {

20
peer.go

@ -748,8 +748,28 @@ out:
} }
case *lnwire.Error: case *lnwire.Error:
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) 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 // TODO(roasbeef): create ChanUpdater interface for the below
case *lnwire.UpdateAddHTLC: case *lnwire.UpdateAddHTLC:
isChanUpdate = true isChanUpdate = true