forked from lightningnetwork/lnd
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request lightningnetwork#6716 from Crypt-iQ/zeroconfacceptor
multi: add zeroconfacceptor to default reject incoming channels
- Loading branch information
Showing
17 changed files
with
2,998 additions
and
2,571 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package chanacceptor | ||
|
||
import "github.com/lightningnetwork/lnd/lnwire" | ||
|
||
// ZeroConfAcceptor wraps a regular ChainedAcceptor. If no acceptors are in the | ||
// ChainedAcceptor, then Accept will reject all channel open requests. This | ||
// should only be enabled when the zero-conf feature bit is set and is used to | ||
// protect users from a malicious counter-party double-spending the zero-conf | ||
// funding tx. | ||
type ZeroConfAcceptor struct { | ||
chainedAcceptor *ChainedAcceptor | ||
} | ||
|
||
// NewZeroConfAcceptor initializes a ZeroConfAcceptor. | ||
func NewZeroConfAcceptor() *ZeroConfAcceptor { | ||
return &ZeroConfAcceptor{ | ||
chainedAcceptor: NewChainedAcceptor(), | ||
} | ||
} | ||
|
||
// AddAcceptor adds a sub-ChannelAcceptor to the internal ChainedAcceptor. | ||
func (z *ZeroConfAcceptor) AddAcceptor(acceptor ChannelAcceptor) uint64 { | ||
return z.chainedAcceptor.AddAcceptor(acceptor) | ||
} | ||
|
||
// RemoveAcceptor removes a sub-ChannelAcceptor from the internal | ||
// ChainedAcceptor. | ||
func (z *ZeroConfAcceptor) RemoveAcceptor(id uint64) { | ||
z.chainedAcceptor.RemoveAcceptor(id) | ||
} | ||
|
||
// Accept will deny the channel open request if the internal ChainedAcceptor is | ||
// empty. If the internal ChainedAcceptor has any acceptors, then Accept will | ||
// instead be called on it. | ||
// | ||
// NOTE: Part of the ChannelAcceptor interface. | ||
func (z *ZeroConfAcceptor) Accept( | ||
req *ChannelAcceptRequest) *ChannelAcceptResponse { | ||
|
||
// Alias for less verbosity. | ||
channelType := req.OpenChanMsg.ChannelType | ||
|
||
// Check if the channel type sets the zero-conf bit. | ||
var zeroConfSet bool | ||
|
||
if channelType != nil { | ||
channelFeatures := lnwire.RawFeatureVector(*channelType) | ||
zeroConfSet = channelFeatures.IsSet(lnwire.ZeroConfRequired) | ||
} | ||
|
||
// If there are no acceptors and the counter-party is requesting a zero | ||
// conf channel, reject the attempt. | ||
if z.chainedAcceptor.numAcceptors() == 0 && zeroConfSet { | ||
// Deny the channel open request. | ||
rejectChannel := NewChannelAcceptResponse( | ||
false, nil, nil, 0, 0, 0, 0, 0, 0, false, | ||
) | ||
return rejectChannel | ||
} | ||
|
||
// Otherwise, the ChainedAcceptor has sub-acceptors, so call Accept on | ||
// it. | ||
return z.chainedAcceptor.Accept(req) | ||
} | ||
|
||
// A compile-time constraint to ensure ZeroConfAcceptor implements the | ||
// MultiplexAcceptor interface. | ||
var _ MultiplexAcceptor = (*ZeroConfAcceptor)(nil) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package chanacceptor | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/lightningnetwork/lnd/lnwire" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
// dummyAcceptor is a ChannelAcceptor that will never return a failure. | ||
type dummyAcceptor struct{} | ||
|
||
func (d *dummyAcceptor) Accept( | ||
req *ChannelAcceptRequest) *ChannelAcceptResponse { | ||
|
||
return &ChannelAcceptResponse{} | ||
} | ||
|
||
// TestZeroConfAcceptorNormal verifies that the ZeroConfAcceptor will let | ||
// requests go through for non-zero-conf channels if there are no | ||
// sub-acceptors. | ||
func TestZeroConfAcceptorNormal(t *testing.T) { | ||
t.Parallel() | ||
|
||
// Create the zero-conf acceptor. | ||
zeroAcceptor := NewZeroConfAcceptor() | ||
|
||
// Assert that calling Accept won't return a failure. | ||
req := &ChannelAcceptRequest{ | ||
OpenChanMsg: &lnwire.OpenChannel{}, | ||
} | ||
resp := zeroAcceptor.Accept(req) | ||
require.False(t, resp.RejectChannel()) | ||
|
||
// Add a dummyAcceptor to the zero-conf acceptor. Assert that Accept | ||
// does not return a failure. | ||
dummy := &dummyAcceptor{} | ||
dummyID := zeroAcceptor.AddAcceptor(dummy) | ||
resp = zeroAcceptor.Accept(req) | ||
require.False(t, resp.RejectChannel()) | ||
|
||
// Remove the dummyAcceptor from the zero-conf acceptor and assert that | ||
// Accept doesn't return a failure. | ||
zeroAcceptor.RemoveAcceptor(dummyID) | ||
resp = zeroAcceptor.Accept(req) | ||
require.False(t, resp.RejectChannel()) | ||
} | ||
|
||
// TestZeroConfAcceptorZC verifies that the ZeroConfAcceptor will fail | ||
// zero-conf channel opens unless a sub-acceptor exists. | ||
func TestZeroConfAcceptorZC(t *testing.T) { | ||
t.Parallel() | ||
|
||
// Create the zero-conf acceptor. | ||
zeroAcceptor := NewZeroConfAcceptor() | ||
|
||
channelType := new(lnwire.ChannelType) | ||
*channelType = lnwire.ChannelType(*lnwire.NewRawFeatureVector( | ||
lnwire.ZeroConfRequired, | ||
)) | ||
|
||
// Assert that calling Accept results in failure. | ||
req := &ChannelAcceptRequest{ | ||
OpenChanMsg: &lnwire.OpenChannel{ | ||
ChannelType: channelType, | ||
}, | ||
} | ||
resp := zeroAcceptor.Accept(req) | ||
require.True(t, resp.RejectChannel()) | ||
|
||
// Add a dummyAcceptor to the zero-conf acceptor. Assert that Accept | ||
// does not return a failure. | ||
dummy := &dummyAcceptor{} | ||
dummyID := zeroAcceptor.AddAcceptor(dummy) | ||
resp = zeroAcceptor.Accept(req) | ||
require.False(t, resp.RejectChannel()) | ||
|
||
// Remove the dummyAcceptor from the zero-conf acceptor and assert that | ||
// Accept returns a failure. | ||
zeroAcceptor.RemoveAcceptor(dummyID) | ||
resp = zeroAcceptor.Accept(req) | ||
require.True(t, resp.RejectChannel()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.