fundingmanager: preserve custom remoteCsvDelay

This commit fixes a bug that would cause the local and remote commitment
to be incompatible when using custom remote CSV delay when opening a
channel. This would happen because we wouldn't store the CSV value
before we received the FundingAccept message, and here we would use the
default value.

This commit fixes this by making the csv value part of the
reservationWithCtx struct, such that it can be recorded for use when the
FundingAccept msg comes back.
This commit is contained in:
Johan T. Halseth 2018-04-05 19:14:26 +02:00
parent b7875fce4c
commit 7a4817b066
No known key found for this signature in database
GPG Key ID: 15BAADA29DA20D26

@ -79,7 +79,8 @@ type reservationWithCtx struct {
reservation *lnwallet.ChannelReservation reservation *lnwallet.ChannelReservation
peerAddress *lnwire.NetAddress peerAddress *lnwire.NetAddress
chanAmt btcutil.Amount chanAmt btcutil.Amount
remoteCsvDelay uint16
updateMtx sync.RWMutex updateMtx sync.RWMutex
lastUpdated time.Time lastUpdated time.Time
@ -995,8 +996,8 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) {
// We'll also validate and apply all the constraints the initiating // We'll also validate and apply all the constraints the initiating
// party is attempting to dictate for our commitment transaction. // party is attempting to dictate for our commitment transaction.
err = reservation.CommitConstraints( err = reservation.CommitConstraints(
uint16(msg.CsvDelay), msg.MaxAcceptedHTLCs, msg.CsvDelay, msg.MaxAcceptedHTLCs, msg.MaxValueInFlight,
msg.MaxValueInFlight, msg.HtlcMinimum, msg.ChannelReserve, msg.HtlcMinimum, msg.ChannelReserve,
) )
if err != nil { if err != nil {
fndgLog.Errorf("Unaccaptable channel constraints: %v", err) fndgLog.Errorf("Unaccaptable channel constraints: %v", err)
@ -1011,6 +1012,10 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) {
"amt=%v, push_amt=%v", numConfsReq, fmsg.msg.PendingChannelID, "amt=%v, push_amt=%v", numConfsReq, fmsg.msg.PendingChannelID,
amt, msg.PushAmount) amt, msg.PushAmount)
// Using the RequiredRemoteDelay closure, we'll compute the remote CSV
// delay we require given the total amount of funds within the channel.
remoteCsvDelay := f.cfg.RequiredRemoteDelay(amt)
// Once the reservation has been created successfully, we add it to // Once the reservation has been created successfully, we add it to
// this peer's map of pending reservations to track this particular // this peer's map of pending reservations to track this particular
// reservation until either abort or completion. // reservation until either abort or completion.
@ -1019,10 +1024,11 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) {
f.activeReservations[peerIDKey] = make(pendingChannels) f.activeReservations[peerIDKey] = make(pendingChannels)
} }
resCtx := &reservationWithCtx{ resCtx := &reservationWithCtx{
reservation: reservation, reservation: reservation,
chanAmt: amt, chanAmt: amt,
err: make(chan error, 1), remoteCsvDelay: remoteCsvDelay,
peerAddress: fmsg.peerAddress, err: make(chan error, 1),
peerAddress: fmsg.peerAddress,
} }
f.activeReservations[peerIDKey][msg.PendingChannelID] = resCtx f.activeReservations[peerIDKey][msg.PendingChannelID] = resCtx
f.resMtx.Unlock() f.resMtx.Unlock()
@ -1030,10 +1036,6 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) {
// Update the timestamp once the fundingOpenMsg has been handled. // Update the timestamp once the fundingOpenMsg has been handled.
defer resCtx.updateTimestamp() defer resCtx.updateTimestamp()
// Using the RequiredRemoteDelay closure, we'll compute the remote CSV
// delay we require given the total amount of funds within the channel.
remoteCsvDelay := f.cfg.RequiredRemoteDelay(amt)
// We'll also generate our required constraints for the remote party, // We'll also generate our required constraints for the remote party,
chanReserve := f.cfg.RequiredRemoteChanReserve(amt) chanReserve := f.cfg.RequiredRemoteChanReserve(amt)
maxValue := f.cfg.RequiredRemoteMaxValue(amt) maxValue := f.cfg.RequiredRemoteMaxValue(amt)
@ -1148,8 +1150,8 @@ func (f *fundingManager) handleFundingAccept(fmsg *fundingAcceptMsg) {
// they've specified for commitment states we can create. // they've specified for commitment states we can create.
resCtx.reservation.SetNumConfsRequired(uint16(msg.MinAcceptDepth)) resCtx.reservation.SetNumConfsRequired(uint16(msg.MinAcceptDepth))
err = resCtx.reservation.CommitConstraints( err = resCtx.reservation.CommitConstraints(
uint16(msg.CsvDelay), msg.MaxAcceptedHTLCs, msg.CsvDelay, msg.MaxAcceptedHTLCs, msg.MaxValueInFlight,
msg.MaxValueInFlight, msg.HtlcMinimum, msg.ChannelReserve, msg.HtlcMinimum, msg.ChannelReserve,
) )
if err != nil { if err != nil {
fndgLog.Warnf("Unacceptable channel constraints: %v", err) fndgLog.Warnf("Unacceptable channel constraints: %v", err)
@ -1179,6 +1181,7 @@ func (f *fundingManager) handleFundingAccept(fmsg *fundingAcceptMsg) {
MinHTLC: msg.HtlcMinimum, MinHTLC: msg.HtlcMinimum,
MaxAcceptedHtlcs: maxHtlcs, MaxAcceptedHtlcs: maxHtlcs,
}, },
CsvDelay: resCtx.remoteCsvDelay,
MultiSigKey: keychain.KeyDescriptor{ MultiSigKey: keychain.KeyDescriptor{
PubKey: copyPubKey(msg.FundingKey), PubKey: copyPubKey(msg.FundingKey),
}, },
@ -1196,7 +1199,6 @@ func (f *fundingManager) handleFundingAccept(fmsg *fundingAcceptMsg) {
}, },
}, },
} }
remoteContribution.CsvDelay = f.cfg.RequiredRemoteDelay(resCtx.chanAmt)
err = resCtx.reservation.ProcessContribution(remoteContribution) err = resCtx.reservation.ProcessContribution(remoteContribution)
if err != nil { if err != nil {
fndgLog.Errorf("Unable to process contribution from %v: %v", fndgLog.Errorf("Unable to process contribution from %v: %v",
@ -2538,6 +2540,13 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
fndgLog.Infof("Target commit tx sat/kw for pendingID(%x): %v", chanID, fndgLog.Infof("Target commit tx sat/kw for pendingID(%x): %v", chanID,
int64(commitFeePerKw)) int64(commitFeePerKw))
// If the remote CSV delay was not set in the open channel request,
// we'll use the RequiredRemoteDelay closure to compute the delay we
// require given the total amount of funds within the channel.
if remoteCsvDelay == 0 {
remoteCsvDelay = f.cfg.RequiredRemoteDelay(capacity)
}
// If a pending channel map for this peer isn't already created, then // If a pending channel map for this peer isn't already created, then
// we create one, ultimately allowing us to track this pending // we create one, ultimately allowing us to track this pending
// reservation within the target peer. // reservation within the target peer.
@ -2548,11 +2557,12 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
} }
resCtx := &reservationWithCtx{ resCtx := &reservationWithCtx{
chanAmt: capacity, chanAmt: capacity,
reservation: reservation, remoteCsvDelay: remoteCsvDelay,
peerAddress: msg.peerAddress, reservation: reservation,
updates: msg.updates, peerAddress: msg.peerAddress,
err: msg.err, updates: msg.updates,
err: msg.err,
} }
f.activeReservations[peerIDKey][chanID] = resCtx f.activeReservations[peerIDKey][chanID] = resCtx
f.resMtx.Unlock() f.resMtx.Unlock()
@ -2560,13 +2570,6 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
// Update the timestamp once the initFundingMsg has been handled. // Update the timestamp once the initFundingMsg has been handled.
defer resCtx.updateTimestamp() defer resCtx.updateTimestamp()
// If the remote CSV delay was not set in the open channel request,
// we'll use the RequiredRemoteDelay closure to compute the delay we
// require given the total amount of funds within the channel.
if remoteCsvDelay == 0 {
remoteCsvDelay = f.cfg.RequiredRemoteDelay(capacity)
}
// If no minimum HTLC value was specified, use the default one. // If no minimum HTLC value was specified, use the default one.
if minHtlc == 0 { if minHtlc == 0 {
minHtlc = f.cfg.DefaultRoutingPolicy.MinHTLC minHtlc = f.cfg.DefaultRoutingPolicy.MinHTLC