Files
electronwall/htlcInterceptor.go
callebtc f55b101151 clean
2022-07-08 12:38:18 +02:00

108 lines
2.7 KiB
Go

package main
import (
"context"
"math/rand"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
log "github.com/sirupsen/logrus"
"google.golang.org/grpc"
)
func dispatchHTLCAcceptor(ctx context.Context, conn *grpc.ClientConn, client lnrpc.LightningClient) {
router := routerrpc.NewRouterClient(conn)
// htlc event subscriber, reports on incoming htlc events
stream, err := router.SubscribeHtlcEvents(ctx, &routerrpc.SubscribeHtlcEventsRequest{})
if err != nil {
return
}
go func() {
err := logHtlcEvents(stream)
if err != nil {
log.Error("htlc events error",
"err", err)
}
}()
// interceptor, decide whether to accept or reject
interceptor, err := router.HtlcInterceptor(ctx)
if err != nil {
return
}
go func() {
err := interceptHtlcEvents(interceptor)
if err != nil {
log.Error("interceptor error",
"err", err)
}
}()
log.Info("Listening for incoming HTLCs")
}
func logHtlcEvents(stream routerrpc.Router_SubscribeHtlcEventsClient) error {
for {
event, err := stream.Recv()
if err != nil {
return err
}
// we only care about HTLC forward events
if event.EventType != routerrpc.HtlcEvent_FORWARD {
continue
}
switch event.Event.(type) {
case *routerrpc.HtlcEvent_SettleEvent:
log.Infof("HTLC SettleEvent (chan_id:%d htlc_id:%d)", event.IncomingChannelId, event.IncomingHtlcId)
case *routerrpc.HtlcEvent_ForwardFailEvent:
log.Infof("HTLC ForwardFailEvent (chan_id:%d htlc_id:%d)", event.IncomingChannelId, event.IncomingHtlcId)
case *routerrpc.HtlcEvent_ForwardEvent:
log.Infof("HTLC ForwardEvent (chan_id:%d htlc_id:%d)", event.IncomingChannelId, event.IncomingHtlcId)
case *routerrpc.HtlcEvent_LinkFailEvent:
log.Infof("HTLC LinkFailEvent (chan_id:%d htlc_id:%d)", event.IncomingChannelId, event.IncomingHtlcId)
}
}
}
func interceptHtlcEvents(interceptor routerrpc.Router_HtlcInterceptorClient) error {
for {
event, err := interceptor.Recv()
if err != nil {
return err
}
// decision for routing
log.Infof("Received HTLC. Making random 50/50 decision...")
accept := true
if rand.Intn(2) == 0 {
accept = false
}
response := &routerrpc.ForwardHtlcInterceptResponse{
IncomingCircuitKey: event.IncomingCircuitKey,
}
if accept {
log.Infof("✅ Accept HTLC (%d sat, %s)", event.IncomingAmountMsat/1000, event.IncomingCircuitKey.String())
response.Action = routerrpc.ResolveHoldForwardAction_RESUME
} else {
log.Infof("❌ Reject HTLC (%d sat, %s)", event.IncomingAmountMsat/1000, event.IncomingCircuitKey.String())
response.Action = routerrpc.ResolveHoldForwardAction_FAIL
}
err = interceptor.Send(response)
if err != nil {
return err
}
}
}