lnwallet+fundingmanager: enforce max MinAcceptDepth within funding proposals
This commit is contained in:
parent
71410f6a08
commit
4f953afeee
@ -1230,6 +1230,18 @@ func (f *fundingManager) handleFundingAccept(fmsg *fundingAcceptMsg) {
|
|||||||
|
|
||||||
fndgLog.Infof("Recv'd fundingResponse for pendingID(%x)", pendingChanID[:])
|
fndgLog.Infof("Recv'd fundingResponse for pendingID(%x)", pendingChanID[:])
|
||||||
|
|
||||||
|
// The required number of confirmations should not be greater than the
|
||||||
|
// maximum number of confirmations required by the ChainNotifier to
|
||||||
|
// properly dispatch confirmations.
|
||||||
|
if msg.MinAcceptDepth > chainntnfs.MaxNumConfs {
|
||||||
|
err := lnwallet.ErrNumConfsTooLarge(
|
||||||
|
msg.MinAcceptDepth, chainntnfs.MaxNumConfs,
|
||||||
|
)
|
||||||
|
fndgLog.Warnf("Unacceptable channel constraints: %v", err)
|
||||||
|
f.failFundingFlow(fmsg.peer, fmsg.msg.PendingChannelID, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// We'll also specify the responder's preference for the number of
|
// We'll also specify the responder's preference for the number of
|
||||||
// required confirmations, and also the set of channel constraints
|
// required confirmations, and also the set of channel constraints
|
||||||
// they've specified for commitment states we can create.
|
// they've specified for commitment states we can create.
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -2539,3 +2540,72 @@ func TestFundingManagerRejectPush(t *testing.T) {
|
|||||||
string(err.Data))
|
string(err.Data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestFundingManagerMaxConfs ensures that we don't accept a funding proposal
|
||||||
|
// that proposes a MinAcceptDepth greater than the maximum number of
|
||||||
|
// confirmations we're willing to accept.
|
||||||
|
func TestFundingManagerMaxConfs(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
alice, bob := setupFundingManagers(t, defaultMaxPendingChannels)
|
||||||
|
defer tearDownFundingManagers(t, alice, bob)
|
||||||
|
|
||||||
|
// Create a funding request and start the workflow.
|
||||||
|
updateChan := make(chan *lnrpc.OpenStatusUpdate)
|
||||||
|
errChan := make(chan error, 1)
|
||||||
|
initReq := &openChanReq{
|
||||||
|
targetPubkey: bob.privKey.PubKey(),
|
||||||
|
chainHash: *activeNetParams.GenesisHash,
|
||||||
|
localFundingAmt: 500000,
|
||||||
|
pushAmt: lnwire.NewMSatFromSatoshis(10),
|
||||||
|
private: false,
|
||||||
|
updates: updateChan,
|
||||||
|
err: errChan,
|
||||||
|
}
|
||||||
|
|
||||||
|
alice.fundingMgr.initFundingWorkflow(bob, initReq)
|
||||||
|
|
||||||
|
// Alice should have sent the OpenChannel message to Bob.
|
||||||
|
var aliceMsg lnwire.Message
|
||||||
|
select {
|
||||||
|
case aliceMsg = <-alice.msgChan:
|
||||||
|
case err := <-initReq.err:
|
||||||
|
t.Fatalf("error init funding workflow: %v", err)
|
||||||
|
case <-time.After(time.Second * 5):
|
||||||
|
t.Fatalf("alice did not send OpenChannel message")
|
||||||
|
}
|
||||||
|
|
||||||
|
openChannelReq, ok := aliceMsg.(*lnwire.OpenChannel)
|
||||||
|
if !ok {
|
||||||
|
errorMsg, gotError := aliceMsg.(*lnwire.Error)
|
||||||
|
if gotError {
|
||||||
|
t.Fatalf("expected OpenChannel to be sent "+
|
||||||
|
"from bob, instead got error: %v",
|
||||||
|
lnwire.ErrorCode(errorMsg.Data[0]))
|
||||||
|
}
|
||||||
|
t.Fatalf("expected OpenChannel to be sent from "+
|
||||||
|
"alice, instead got %T", aliceMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let Bob handle the init message.
|
||||||
|
bob.fundingMgr.processFundingOpen(openChannelReq, alice)
|
||||||
|
|
||||||
|
// Bob should answer with an AcceptChannel message.
|
||||||
|
acceptChannelResponse := assertFundingMsgSent(
|
||||||
|
t, bob.msgChan, "AcceptChannel",
|
||||||
|
).(*lnwire.AcceptChannel)
|
||||||
|
|
||||||
|
// Modify the AcceptChannel message Bob is proposing to including a
|
||||||
|
// MinAcceptDepth Alice won't be willing to accept.
|
||||||
|
acceptChannelResponse.MinAcceptDepth = chainntnfs.MaxNumConfs + 1
|
||||||
|
|
||||||
|
alice.fundingMgr.processFundingAccept(acceptChannelResponse, bob)
|
||||||
|
|
||||||
|
// Alice should respond back with an error indicating MinAcceptDepth is
|
||||||
|
// too large.
|
||||||
|
err := assertFundingMsgSent(t, alice.msgChan, "Error").(*lnwire.Error)
|
||||||
|
if !strings.Contains(string(err.Data), "minimum depth") {
|
||||||
|
t.Fatalf("expected ErrNumConfsTooLarge, got \"%v\"",
|
||||||
|
string(err.Data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -123,6 +123,15 @@ func ErrMaxValueInFlightTooSmall(maxValInFlight,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ErrNumConfsTooLarge returns an error indicating that the number of
|
||||||
|
// confirmations required for a channel is too large.
|
||||||
|
func ErrNumConfsTooLarge(numConfs, maxNumConfs uint32) error {
|
||||||
|
return ReservationError{
|
||||||
|
fmt.Errorf("minimum depth of %d is too large, max is %d",
|
||||||
|
numConfs, maxNumConfs),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ErrChanTooSmall returns an error indicating that an incoming channel request
|
// ErrChanTooSmall returns an error indicating that an incoming channel request
|
||||||
// was too small. We'll reject any incoming channels if they're below our
|
// was too small. We'll reject any incoming channels if they're below our
|
||||||
// configured value for the min channel size we'll accept.
|
// configured value for the min channel size we'll accept.
|
||||||
|
Loading…
Reference in New Issue
Block a user