chanacceptor: Adding Chained and RPC acceptors

This commit introduces the chanacceptor package which is used
to determine, by a set of heuristics, which open channel messages
to accept and reject. Currently, two acceptors are implemented
via the ChannelAcceptor interface: ChainedAcceptor and RPCAcceptor.
The RPCAcceptor allows the RPC client to respond to the open channel
request, and the ChainedAcceptor allows a conjunction of acceptors
to be used.
This commit is contained in:
nsa 2019-08-07 22:15:14 -04:00
parent 7c6cee7c4f
commit 2bd2e2e5ce
No known key found for this signature in database
GPG Key ID: 118759E83439A9B1
3 changed files with 117 additions and 0 deletions

View File

@ -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)

25
chanacceptor/interface.go Normal file
View File

@ -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
}

View File

@ -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)