From 6942e1479d3ef4dbe48986c9cfa9f2a9b3121e72 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Tue, 27 Feb 2018 18:37:21 +0100 Subject: [PATCH] funding: only send know errors across wire This commit changes the failFundingFlow to accept an error, which will only be sent to the remote the peer if it is among the ReservationErrors or ErrorCode. This is done to ensure we don't send errors that contain information we don't want to leak. --- fundingmanager.go | 84 +++++++++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 35 deletions(-) diff --git a/fundingmanager.go b/fundingmanager.go index 4614c18b0..d3440b699 100644 --- a/fundingmanager.go +++ b/fundingmanager.go @@ -689,21 +689,40 @@ func (f *fundingManager) CancelPeerReservations(nodePub [33]byte) { } // failFundingFlow will fail the active funding flow with the target peer, -// identified by its unique temporary channel ID. This method is send an error -// to the remote peer, and also remove the reservation from our set of pending -// reservations. +// identified by its unique temporary channel ID. This method will send an +// error to the remote peer, and also remove the reservation from our set of +// pending reservations. // // TODO(roasbeef): if peer disconnects, and haven't yet broadcast funding // transaction, then all reservations should be cleared. func (f *fundingManager) failFundingFlow(peer *btcec.PublicKey, - tempChanID [32]byte, msg []byte) { + tempChanID [32]byte, fundingErr error) { + + // We only send the exact error if it is part of out whitelisted set of + // errors (lnwire.ErrorCode or lnwallet.ReservationError). + var msg lnwire.ErrorData + switch e := fundingErr.(type) { + + // Let the actual error message be sent to the remote. + case lnwallet.ReservationError: + msg = lnwire.ErrorData(e.Error()) + + // Send the status code. + case lnwire.ErrorCode: + msg = lnwire.ErrorData{byte(e)} + + // We just send a generic error. + default: + msg = lnwire.ErrorData("funding failed due to internal error") + } errMsg := &lnwire.Error{ ChanID: tempChanID, Data: msg, } - fndgLog.Errorf("Failing funding flow: %v", spew.Sdump(errMsg)) + fndgLog.Errorf("Failing funding flow: %v (%v)", fundingErr, + spew.Sdump(errMsg)) if _, err := f.cancelReservationCtx(peer, tempChanID); err != nil { fndgLog.Errorf("unable to cancel reservation: %v", err) @@ -819,8 +838,7 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) { if len(f.activeReservations[peerIDKey]) >= cfg.MaxPendingChannels { f.failFundingFlow( fmsg.peerAddress.IdentityKey, fmsg.msg.PendingChannelID, - lnwire.ErrorData{byte(lnwire.ErrMaxPendingChannels)}, - ) + lnwire.ErrMaxPendingChannels) return } @@ -834,8 +852,7 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) { } f.failFundingFlow( fmsg.peerAddress.IdentityKey, fmsg.msg.PendingChannelID, - lnwire.ErrorData{byte(lnwire.ErrSynchronizingChain)}, - ) + lnwire.ErrSynchronizingChain) return } @@ -844,8 +861,7 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) { if msg.FundingAmount > maxFundingAmount { f.failFundingFlow( fmsg.peerAddress.IdentityKey, fmsg.msg.PendingChannelID, - lnwire.ErrorData{byte(lnwire.ErrChanTooLarge)}, - ) + lnwire.ErrChanTooLarge) return } @@ -871,7 +887,7 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) { if err != nil { fndgLog.Errorf("Unable to initialize reservation: %v", err) f.failFundingFlow(fmsg.peerAddress.IdentityKey, - msg.PendingChannelID, []byte(err.Error())) + msg.PendingChannelID, err) return } @@ -890,10 +906,9 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) { msg.MaxValueInFlight, msg.HtlcMinimum, msg.ChannelReserve, ) if err != nil { - f.failFundingFlow( - fmsg.peerAddress.IdentityKey, fmsg.msg.PendingChannelID, - []byte(fmt.Sprintf("Unacceptable channel "+ - "constraints: %v", err)), + fndgLog.Errorf("Unaccaptable channel constraints: %v", err) + f.failFundingFlow(fmsg.peerAddress.IdentityKey, + fmsg.msg.PendingChannelID, err, ) return } @@ -951,9 +966,8 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) { err = reservation.ProcessSingleContribution(remoteContribution) if err != nil { fndgLog.Errorf("unable to add contribution reservation: %v", err) - // TODO(roasbeef): verify only sending sane info over f.failFundingFlow(fmsg.peerAddress.IdentityKey, - msg.PendingChannelID, []byte(err.Error())) + msg.PendingChannelID, err) return } @@ -985,7 +999,7 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) { if err != nil { fndgLog.Errorf("unable to send funding response to peer: %v", err) f.failFundingFlow(fmsg.peerAddress.IdentityKey, - msg.PendingChannelID, []byte(err.Error())) + msg.PendingChannelID, err) return } } @@ -1028,11 +1042,9 @@ func (f *fundingManager) handleFundingAccept(fmsg *fundingAcceptMsg) { msg.MaxValueInFlight, msg.HtlcMinimum, msg.ChannelReserve, ) if err != nil { - f.failFundingFlow( - fmsg.peerAddress.IdentityKey, fmsg.msg.PendingChannelID, - []byte(fmt.Sprintf("Unacceptable channel "+ - "constraints: %v", err)), - ) + fndgLog.Warnf("Unacceptable channel constraints: %v", err) + f.failFundingFlow(fmsg.peerAddress.IdentityKey, + fmsg.msg.PendingChannelID, err) return } @@ -1070,7 +1082,7 @@ func (f *fundingManager) handleFundingAccept(fmsg *fundingAcceptMsg) { fndgLog.Errorf("Unable to process contribution from %v: %v", fmsg.peerAddress.IdentityKey, err) f.failFundingFlow(fmsg.peerAddress.IdentityKey, - msg.PendingChannelID, []byte(err.Error())) + msg.PendingChannelID, err) resCtx.err <- err return } @@ -1115,7 +1127,7 @@ func (f *fundingManager) handleFundingAccept(fmsg *fundingAcceptMsg) { if err != nil { fndgLog.Errorf("Unable to parse signature: %v", err) f.failFundingFlow(fmsg.peerAddress.IdentityKey, - msg.PendingChannelID, []byte(err.Error())) + msg.PendingChannelID, err) resCtx.err <- err return } @@ -1123,7 +1135,7 @@ func (f *fundingManager) handleFundingAccept(fmsg *fundingAcceptMsg) { if err != nil { fndgLog.Errorf("Unable to send funding complete message: %v", err) f.failFundingFlow(fmsg.peerAddress.IdentityKey, - msg.PendingChannelID, []byte(err.Error())) + msg.PendingChannelID, err) resCtx.err <- err return } @@ -1177,7 +1189,7 @@ func (f *fundingManager) handleFundingCreated(fmsg *fundingCreatedMsg) { // TODO(roasbeef): better error logging: peerID, channelID, etc. fndgLog.Errorf("unable to complete single reservation: %v", err) f.failFundingFlow(fmsg.peerAddress.IdentityKey, - pendingChanID, []byte(err.Error())) + pendingChanID, err) return } @@ -1218,7 +1230,7 @@ func (f *fundingManager) handleFundingCreated(fmsg *fundingCreatedMsg) { if err != nil { fndgLog.Errorf("unable to parse signature: %v", err) f.failFundingFlow(fmsg.peerAddress.IdentityKey, - pendingChanID, []byte(err.Error())) + pendingChanID, err) deleteFromDatabase() return } @@ -1230,7 +1242,7 @@ func (f *fundingManager) handleFundingCreated(fmsg *fundingCreatedMsg) { if err := f.cfg.SendToPeer(peerKey, fundingSigned); err != nil { fndgLog.Errorf("unable to send FundingSigned message: %v", err) f.failFundingFlow(fmsg.peerAddress.IdentityKey, - pendingChanID, []byte(err.Error())) + pendingChanID, err) deleteFromDatabase() return } @@ -1332,11 +1344,12 @@ func (f *fundingManager) handleFundingSigned(fmsg *fundingSignedMsg) { delete(f.signedReservations, fmsg.msg.ChanID) f.resMtx.Unlock() if !ok { - err := fmt.Sprintf("Unable to find signed reservation for "+ + err := fmt.Errorf("Unable to find signed reservation for "+ "chan_id=%x", fmsg.msg.ChanID) - fndgLog.Warnf(err) + fndgLog.Warnf(err.Error()) + // TODO: add ErrChanNotFound? f.failFundingFlow(fmsg.peerAddress.IdentityKey, - pendingChanID, []byte(err)) + pendingChanID, err) return } @@ -1346,8 +1359,9 @@ func (f *fundingManager) handleFundingSigned(fmsg *fundingSignedMsg) { if err != nil { fndgLog.Warnf("Unable to find reservation (peerID:%v, chanID:%x)", peerKey, pendingChanID[:]) + // TODO: add ErrChanNotFound? f.failFundingFlow(fmsg.peerAddress.IdentityKey, - pendingChanID, []byte(err.Error())) + pendingChanID, err) return } @@ -1369,7 +1383,7 @@ func (f *fundingManager) handleFundingSigned(fmsg *fundingSignedMsg) { fndgLog.Errorf("Unable to complete reservation sign complete: %v", err) resCtx.err <- err f.failFundingFlow(fmsg.peerAddress.IdentityKey, - pendingChanID, []byte(err.Error())) + pendingChanID, err) return }