Channel Acceptor
The channel acceptor API allows you to enforce custom logic on whether an incoming channel should be accepted or not.
Code examples:
Pool:
lndclient:
Last updated
Was this helpful?
The channel acceptor API allows you to enforce custom logic on whether an incoming channel should be accepted or not.
Last updated
Was this helpful?
Was this helpful?
// acceptChannel is the callback that is invoked each time a new incoming
// channel message is received in lnd. We inspect it here and if it corresponds
// to a pending channel ID that we have an expectation for, we check whether the
// self chan balance (=push amount) is correct.
func (s *ChannelAcceptor) acceptChannel(_ context.Context,
req *lndclient.AcceptorRequest) (*lndclient.AcceptorResponse, error) {
s.expectedChansMtx.Lock()
defer s.expectedChansMtx.Unlock()
expectedChanBid, ok := s.expectedChans[req.PendingChanID]
// It's not a channel we've registered within the funding manager so we
// just accept it to not interfere with the normal node operation.
if !ok {
return &lndclient.AcceptorResponse{Accept: true}, nil
}
// The push amount in the acceptor request is in milli sats, we need to
// convert it first.
pushAmtSat := lnwire.MilliSatoshi(req.PushAmt).ToSatoshis()
// Push amount must be exactly what we expect. Otherwise the asker could
// be trying to cheat.
if expectedChanBid.SelfChanBalance != pushAmtSat {
return &lndclient.AcceptorResponse{
Accept: false,
Error: fmt.Sprintf("invalid push amount %v",
req.PushAmt),
}, nil
}
switch expectedChanBid.ChannelType {
// The bid doesn't have specific requirements for the channel type.
case order.ChannelTypePeerDependent:
break
// The bid expects a channel type that enforces the channel lease
// maturity in its output scripts.
case order.ChannelTypeScriptEnforced:
if req.CommitmentType == nil {
return &lndclient.AcceptorResponse{
Accept: false,
Error: "expected explicit channel negotiation",
}, nil
}
switch *req.CommitmentType {
case lnwallet.CommitmentTypeScriptEnforcedLease:
default:
return &lndclient.AcceptorResponse{
Accept: false,
Error: "expected script enforced channel " +
"lease commitment type",
}, nil
}
default:
log.Warnf("Unhandled channel type %v for bid %v",
expectedChanBid.ChannelType, expectedChanBid.Nonce())
return &lndclient.AcceptorResponse{
Accept: false,
Error: "internal error",
}, nil
}
fundingFlags := lnwire.FundingFlag(req.ChannelFlags)
isPrivateChan := fundingFlags&lnwire.FFAnnounceChannel == 0
// Check that the new channel is announced/unannounced as expected.
if isPrivateChan != expectedChanBid.UnannouncedChannel {
var errMsg string
errTemplate := "expected an %s channel but received an %s one"
if expectedChanBid.UnannouncedChannel {
errMsg = fmt.Sprintf(errTemplate, "unannounced",
"announced")
} else {
errMsg = fmt.Sprintf(errTemplate, "announced",
"unannounced")
}
return &lndclient.AcceptorResponse{
Accept: false,
Error: errMsg,
}, nil
}
// Check that the channel is a zero conf channel if we were expecting
// one.
if expectedChanBid.ZeroConfChannel {
if !req.WantsZeroConf {
return &lndclient.AcceptorResponse{
Accept: false,
Error: "expected zero conf channel",
}, nil
}
return &lndclient.AcceptorResponse{
Accept: true,
MinAcceptDepth: 0,
ZeroConf: true,
}, nil
}
return &lndclient.AcceptorResponse{
Accept: true,
}, nil
} // ChannelAcceptor create a channel acceptor using the accept function
// passed in. The timeout provided will be used to timeout the passed
// accept closure when it exceeds the amount of time we allow. Note that
// this amount should be strictly less than lnd's chanacceptor timeout
// parameter.
ChannelAcceptor(ctx context.Context, timeout time.Duration,
accept AcceptorFunction) (chan error, error)
// FundingStateStep is a funding related call that allows the execution
// of some preparatory steps for a funding workflow or manual
// progression of a funding workflow.
FundingStateStep(ctx context.Context, req *lnrpc.FundingTransitionMsg) (
*lnrpc.FundingStateStepResp, error)
// QueryRoutes can query LND to return a route (with fees) between two
// vertices.
QueryRoutes(ctx context.Context, req QueryRoutesRequest) (
*QueryRoutesResponse, error)
// CheckMacaroonPermissions allows a client to check the validity of a
// macaroon.
CheckMacaroonPermissions(ctx context.Context, macaroon []byte,
permissions []MacaroonPermission, fullMethod string) (bool,
error)
// RegisterRPCMiddleware adds a new gRPC middleware to the interceptor
// chain. A gRPC middleware is software component external to lnd that
// aims to add additional business logic to lnd by observing/
// intercepting/validating incoming gRPC client requests and (if needed)
// replacing/overwriting outgoing messages before they're sent to the
// client.
RegisterRPCMiddleware(ctx context.Context, middlewareName,
customCaveatName string, readOnly bool, timeout time.Duration,
intercept InterceptFunction) (chan error, error)
// SendCustomMessage sends a custom message to a peer.
SendCustomMessage(ctx context.Context, msg CustomMessage) error
// SubscribeCustomMessages creates a subscription to custom messages
// received from our peers.
SubscribeCustomMessages(ctx context.Context) (<-chan CustomMessage,
<-chan error, error)
}