2019-08-08 04:15:14 +02:00
|
|
|
package chanacceptor
|
|
|
|
|
|
|
|
import (
|
|
|
|
"sync"
|
|
|
|
"sync/atomic"
|
|
|
|
)
|
|
|
|
|
|
|
|
// ChainedAcceptor represents a conjunction of ChannelAcceptor results.
|
|
|
|
type ChainedAcceptor struct {
|
2020-12-28 17:04:13 +01:00
|
|
|
acceptorID uint64 // To be used atomically.
|
|
|
|
|
2019-08-08 04:15:14 +02:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewChainedAcceptor initializes a ChainedAcceptor.
|
|
|
|
func NewChainedAcceptor() *ChainedAcceptor {
|
|
|
|
return &ChainedAcceptor{
|
|
|
|
acceptors: make(map[uint64]ChannelAcceptor),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// AddAcceptor adds a ChannelAcceptor to this ChainedAcceptor.
|
2022-07-08 23:18:14 +02:00
|
|
|
//
|
|
|
|
// NOTE: Part of the MultiplexAcceptor interface.
|
2019-08-08 04:15:14 +02:00
|
|
|
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.
|
2022-07-08 23:18:14 +02:00
|
|
|
//
|
|
|
|
// NOTE: Part of the MultiplexAcceptor interface.
|
2019-08-08 04:15:14 +02:00
|
|
|
func (c *ChainedAcceptor) RemoveAcceptor(id uint64) {
|
|
|
|
c.acceptorsMtx.Lock()
|
|
|
|
delete(c.acceptors, id)
|
|
|
|
c.acceptorsMtx.Unlock()
|
|
|
|
}
|
|
|
|
|
2022-07-08 23:18:14 +02:00
|
|
|
// numAcceptors returns the number of acceptors contained in the
|
|
|
|
// ChainedAcceptor.
|
|
|
|
func (c *ChainedAcceptor) numAcceptors() int {
|
|
|
|
c.acceptorsMtx.RLock()
|
|
|
|
defer c.acceptorsMtx.RUnlock()
|
|
|
|
return len(c.acceptors)
|
|
|
|
}
|
|
|
|
|
2019-08-08 04:15:14 +02:00
|
|
|
// 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.
|
2020-11-09 08:34:50 +01:00
|
|
|
func (c *ChainedAcceptor) Accept(req *ChannelAcceptRequest) *ChannelAcceptResponse {
|
2019-08-08 04:15:14 +02:00
|
|
|
c.acceptorsMtx.RLock()
|
2020-11-09 08:34:50 +01:00
|
|
|
defer c.acceptorsMtx.RUnlock()
|
|
|
|
|
2020-11-09 08:34:52 +01:00
|
|
|
var finalResp ChannelAcceptResponse
|
|
|
|
|
2019-08-08 04:15:14 +02:00
|
|
|
for _, acceptor := range c.acceptors {
|
2020-11-09 08:34:50 +01:00
|
|
|
// Call our acceptor to determine whether we want to accept this
|
|
|
|
// channel.
|
|
|
|
acceptorResponse := acceptor.Accept(req)
|
|
|
|
|
|
|
|
// If we should reject the channel, we can just exit early. This
|
|
|
|
// has the effect of returning the error belonging to our first
|
|
|
|
// failed acceptor.
|
|
|
|
if acceptorResponse.RejectChannel() {
|
|
|
|
return acceptorResponse
|
|
|
|
}
|
2020-11-09 08:34:52 +01:00
|
|
|
|
|
|
|
// If we have accepted the channel, we need to set the other
|
|
|
|
// fields that were set in the response. However, since we are
|
|
|
|
// dealing with multiple responses, we need to make sure that we
|
|
|
|
// have not received inconsistent values (eg a csv delay of 1
|
|
|
|
// from one acceptor, and a delay of 120 from another). We
|
|
|
|
// set each value on our final response if it has not been set
|
|
|
|
// yet, and allow duplicate sets if the value is the same. If
|
|
|
|
// we cannot set a field, we return an error response.
|
|
|
|
var err error
|
|
|
|
finalResp, err = mergeResponse(finalResp, *acceptorResponse)
|
|
|
|
if err != nil {
|
|
|
|
log.Errorf("response for: %x has inconsistent values: %v",
|
|
|
|
req.OpenChanMsg.PendingChannelID, err)
|
|
|
|
|
|
|
|
return NewChannelAcceptResponse(
|
|
|
|
false, errChannelRejected, nil, 0, 0,
|
server+funding: allow scid-alias, zero-conf chantypes, scid-alias
feature-bit channels
This allows opening zero-conf chan-type, scid-alias chan-type, and
scid-alias feature-bit channels. scid-alias chan-type channels are
required to be private. Two paths are available for opening a zero-conf
channel:
* explicit chan-type negotiation
* LDK carve-out where chan-types are not used, LND is on the
receiving end, and a ChannelAcceptor is used to enable zero-conf
When a zero-conf channel is negotiated, the funding manager:
* sends a FundingLocked with an alias
* waits for a FundingLocked from the remote peer
* calls addToRouterGraph to persist the channel using our alias in
the graph. The peer's alias is used to send them a ChannelUpdate.
* wait for six confirmations. If public, the alias edge in the
graph is deleted and replaced (not atomically) with the confirmed
edge. Our policy is also read-and-replaced, but the counterparty's
policy won't exist until they send it to us.
When a scid-alias-feature channel is negotiated, the funding manager:
* sends a FundingLocked with an alias:
* calls addToRouterGraph, sends ChannelUpdate with the confirmed SCID
since it exists.
* when six confirmations occurs, the edge is deleted and re-inserted
since the peer may have sent us an alias ChannelUpdate that we are
storing in the graph.
Since it is possible for a user to toggle the scid-alias-feature-bit
to on while channels exist in the funding manager, care has been taken
to ensure that an alias is ALWAYS sent in the funding_locked message
if this happens.
2022-04-04 22:47:05 +02:00
|
|
|
0, 0, 0, 0, false,
|
2020-11-09 08:34:52 +01:00
|
|
|
)
|
|
|
|
}
|
2019-08-08 04:15:14 +02:00
|
|
|
}
|
|
|
|
|
2020-11-09 08:34:50 +01:00
|
|
|
// If we have gone through all of our acceptors with no objections, we
|
|
|
|
// can return an acceptor with a nil error.
|
2020-11-09 08:34:52 +01:00
|
|
|
return &finalResp
|
2019-08-08 04:15:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// A compile-time constraint to ensure ChainedAcceptor implements the
|
2022-07-08 23:18:14 +02:00
|
|
|
// MultiplexAcceptor interface.
|
|
|
|
var _ MultiplexAcceptor = (*ChainedAcceptor)(nil)
|