diff --git a/server.go b/server.go index c38ebb69e..caefe4a50 100644 --- a/server.go +++ b/server.go @@ -1523,12 +1523,37 @@ func newServer(cfg *Config, listenAddrs []net.Addr, ) } + // buildBreachRetribution is a call-back that can be used to + // query the BreachRetribution info and channel type given a + // channel ID and commitment height. + buildBreachRetribution := func(chanID lnwire.ChannelID, + commitHeight uint64) (*lnwallet.BreachRetribution, + channeldb.ChannelType, error) { + + channel, err := s.chanStateDB.FetchChannelByID( + nil, chanID, + ) + if err != nil { + return nil, 0, err + } + + br, err := lnwallet.NewBreachRetribution( + channel, commitHeight, 0, nil, + ) + if err != nil { + return nil, 0, err + } + + return br, channel.ChanType, nil + } + fetchClosedChannel := s.chanStateDB.FetchClosedChannelForID s.towerClient, err = wtclient.New(&wtclient.Config{ - FetchClosedChannel: fetchClosedChannel, - SessionCloseRange: sessionCloseRange, - ChainNotifier: s.cc.ChainNotifier, + FetchClosedChannel: fetchClosedChannel, + BuildBreachRetribution: buildBreachRetribution, + SessionCloseRange: sessionCloseRange, + ChainNotifier: s.cc.ChainNotifier, SubscribeChannelEvents: func() (subscribe.Subscription, error) { @@ -1558,9 +1583,10 @@ func newServer(cfg *Config, listenAddrs []net.Addr, blob.Type(blob.FlagAnchorChannel) s.anchorTowerClient, err = wtclient.New(&wtclient.Config{ - FetchClosedChannel: fetchClosedChannel, - SessionCloseRange: sessionCloseRange, - ChainNotifier: s.cc.ChainNotifier, + FetchClosedChannel: fetchClosedChannel, + BuildBreachRetribution: buildBreachRetribution, + SessionCloseRange: sessionCloseRange, + ChainNotifier: s.cc.ChainNotifier, SubscribeChannelEvents: func() (subscribe.Subscription, error) { diff --git a/watchtower/wtclient/client.go b/watchtower/wtclient/client.go index 96dcaa866..6a45a5c02 100644 --- a/watchtower/wtclient/client.go +++ b/watchtower/wtclient/client.go @@ -178,6 +178,11 @@ type Config struct { // ChainNotifier can be used to subscribe to block notifications. ChainNotifier chainntnfs.ChainNotifier + // BuildBreachRetribution is a function closure that allows the client + // fetch the breach retribution info for a certain channel at a certain + // revoked commitment height. + BuildBreachRetribution BreachRetributionBuilder + // NewAddress generates a new on-chain sweep pkscript. NewAddress func() ([]byte, error) @@ -240,6 +245,12 @@ type Config struct { SessionCloseRange uint32 } +// BreachRetributionBuilder is a function that can be used to construct a +// BreachRetribution from a channel ID and a commitment height. +type BreachRetributionBuilder func(id lnwire.ChannelID, + commitHeight uint64) (*lnwallet.BreachRetribution, + channeldb.ChannelType, error) + // newTowerMsg is an internal message we'll use within the TowerClient to signal // that a new tower can be considered. type newTowerMsg struct { diff --git a/watchtower/wtclient/client_test.go b/watchtower/wtclient/client_test.go index 741443f49..37300f66a 100644 --- a/watchtower/wtclient/client_test.go +++ b/watchtower/wtclient/client_test.go @@ -517,6 +517,15 @@ func newHarness(t *testing.T, cfg harnessCfg) *testHarness { SessionCloseRange: 1, } + h.clientCfg.BuildBreachRetribution = func(id lnwire.ChannelID, + commitHeight uint64) (*lnwallet.BreachRetribution, + channeldb.ChannelType, error) { + + _, retribution := h.channelFromID(id).getState(commitHeight) + + return retribution, channeldb.SingleFunderBit, nil + } + if !cfg.noServerStart { h.startServer() t.Cleanup(h.stopServer) @@ -627,6 +636,21 @@ func (h *testHarness) channel(id uint64) *mockChannel { return c } +// channelFromID retrieves the channel corresponding to id. +// +// NOTE: The method fails if a channel for id does not exist. +func (h *testHarness) channelFromID(chanID lnwire.ChannelID) *mockChannel { + h.t.Helper() + + h.mu.Lock() + defer h.mu.Unlock() + + c, ok := h.channels[chanID] + require.Truef(h.t, ok, "unable to fetch channel %s", chanID) + + return c +} + // closeChannel marks a channel as closed. // // NOTE: The method fails if a channel for id does not exist.