diff --git a/chanacceptor/chainedacceptor.go b/chanacceptor/chainedacceptor.go new file mode 100644 index 00000000..1c12a499 --- /dev/null +++ b/chanacceptor/chainedacceptor.go @@ -0,0 +1,65 @@ +package chanacceptor + +import ( + "sync" + "sync/atomic" +) + +// ChainedAcceptor represents a conjunction of ChannelAcceptor results. +type ChainedAcceptor struct { + // acceptors is a map of ChannelAcceptors that will be evaluated when + // the ChainedAcceptor's Accept method is called. + acceptors map[uint64]ChannelAcceptor + acceptorsMtx sync.RWMutex + + acceptorID uint64 // To be used atomically. +} + +// NewChainedAcceptor initializes a ChainedAcceptor. +func NewChainedAcceptor() *ChainedAcceptor { + return &ChainedAcceptor{ + acceptors: make(map[uint64]ChannelAcceptor), + } +} + +// AddAcceptor adds a ChannelAcceptor to this ChainedAcceptor. +func (c *ChainedAcceptor) AddAcceptor(acceptor ChannelAcceptor) uint64 { + id := atomic.AddUint64(&c.acceptorID, 1) + + c.acceptorsMtx.Lock() + c.acceptors[id] = acceptor + c.acceptorsMtx.Unlock() + + // Return the id so that a caller can call RemoveAcceptor. + return id +} + +// RemoveAcceptor removes a ChannelAcceptor from this ChainedAcceptor given +// an ID. +func (c *ChainedAcceptor) RemoveAcceptor(id uint64) { + c.acceptorsMtx.Lock() + delete(c.acceptors, id) + c.acceptorsMtx.Unlock() +} + +// Accept evaluates the results of all ChannelAcceptors in the acceptors map +// and returns the conjunction of all these predicates. +// +// NOTE: Part of the ChannelAcceptor interface. +func (c *ChainedAcceptor) Accept(req *ChannelAcceptRequest) bool { + result := true + + c.acceptorsMtx.RLock() + for _, acceptor := range c.acceptors { + // We call Accept first in case any acceptor (perhaps an RPCAcceptor) + // wishes to be notified about ChannelAcceptRequest. + result = acceptor.Accept(req) && result + } + c.acceptorsMtx.RUnlock() + + return result +} + +// A compile-time constraint to ensure ChainedAcceptor implements the +// ChannelAcceptor interface. +var _ ChannelAcceptor = (*ChainedAcceptor)(nil) diff --git a/chanacceptor/interface.go b/chanacceptor/interface.go new file mode 100644 index 00000000..c0a3981c --- /dev/null +++ b/chanacceptor/interface.go @@ -0,0 +1,25 @@ +package chanacceptor + +import ( + "github.com/btcsuite/btcd/btcec" + "github.com/lightningnetwork/lnd/lnwire" +) + +// ChannelAcceptRequest is a struct containing the requesting node's public key +// along with the lnwire.OpenChannel message that they sent when requesting an +// inbound channel. This information is provided to each acceptor so that they +// can each leverage their own decision-making with this information. +type ChannelAcceptRequest struct { + // Node is the public key of the node requesting to open a channel. + Node *btcec.PublicKey + + // OpenChanMsg is the actual OpenChannel protocol message that the peer + // sent to us. + OpenChanMsg *lnwire.OpenChannel +} + +// ChannelAcceptor is an interface that represents a predicate on the data +// contained in ChannelAcceptRequest. +type ChannelAcceptor interface { + Accept(req *ChannelAcceptRequest) bool +} diff --git a/chanacceptor/rpcacceptor.go b/chanacceptor/rpcacceptor.go new file mode 100644 index 00000000..9c4401d7 --- /dev/null +++ b/chanacceptor/rpcacceptor.go @@ -0,0 +1,27 @@ +package chanacceptor + +// RPCAcceptor represents the RPC-controlled variant of the ChannelAcceptor. +// One RPCAcceptor allows one RPC client. +type RPCAcceptor struct { + acceptClosure func(req *ChannelAcceptRequest) bool +} + +// Accept is a predicate on the ChannelAcceptRequest which is sent to the RPC +// client who will respond with the ultimate decision. This assumes an accept +// closure has been specified during creation. +// +// NOTE: Part of the ChannelAcceptor interface. +func (r *RPCAcceptor) Accept(req *ChannelAcceptRequest) bool { + return r.acceptClosure(req) +} + +// NewRPCAcceptor creates and returns an instance of the RPCAcceptor. +func NewRPCAcceptor(closure func(*ChannelAcceptRequest) bool) *RPCAcceptor { + return &RPCAcceptor{ + acceptClosure: closure, + } +} + +// A compile-time constraint to ensure RPCAcceptor implements the ChannelAcceptor +// interface. +var _ ChannelAcceptor = (*RPCAcceptor)(nil)