From 6b90254fd3b40a721154168da6c05517cf67b06d Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 31 Jan 2024 19:24:08 -0800 Subject: [PATCH] lnwallet/chancloser: create a MsgMapper for the protofsm rbf close This'll allow us to treat the state machine as a MsgEndpoint, and have the readHandler in the peer automatically send new messages to it. --- lnwallet/chancloser/rbf_coop_msg_mapper.go | 77 ++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 lnwallet/chancloser/rbf_coop_msg_mapper.go diff --git a/lnwallet/chancloser/rbf_coop_msg_mapper.go b/lnwallet/chancloser/rbf_coop_msg_mapper.go new file mode 100644 index 000000000..96c855686 --- /dev/null +++ b/lnwallet/chancloser/rbf_coop_msg_mapper.go @@ -0,0 +1,77 @@ +package chancloser + +import ( + "github.com/lightningnetwork/lnd/fn/v2" + "github.com/lightningnetwork/lnd/lnwire" +) + +// RbfMsgMapper is a struct that implements the MsgMapper interface for the +// rbf-coop close state machine. This enables the state machine to be used with +// protofsm. +type RbfMsgMapper struct { + // blockHeight is the height of the block when the co-op close request + // was initiated. This is used to validate conditions related to the + // thaw height. + blockHeight uint32 + + // chanID is the channel ID of the channel being closed. + chanID lnwire.ChannelID +} + +// NewRbfMsgMapper creates a new RbfMsgMapper instance given the current block +// height when the co-op close request was initiated. +func NewRbfMsgMapper(blockHeight uint32, + chanID lnwire.ChannelID) *RbfMsgMapper { + + return &RbfMsgMapper{ + blockHeight: blockHeight, + chanID: chanID, + } +} + +// someEvent returns the target type as a protocol event option. +func someEvent[T ProtocolEvent](m T) fn.Option[ProtocolEvent] { + return fn.Some(ProtocolEvent(m)) +} + +// isExpectedChanID returns true if the channel ID of the message matches the +// bound instance. +func (r *RbfMsgMapper) isExpectedChanID(chanID lnwire.ChannelID) bool { + return r.chanID == chanID +} + +// MapMsg maps a wire message into a FSM event. If the message is not mappable, +// then an error is returned. +func (r *RbfMsgMapper) MapMsg(wireMsg lnwire.Message) fn.Option[ProtocolEvent] { + switch msg := wireMsg.(type) { + case *lnwire.Shutdown: + if !r.isExpectedChanID(msg.ChannelID) { + return fn.None[ProtocolEvent]() + } + + return someEvent(&ShutdownReceived{ + BlockHeight: r.blockHeight, + ShutdownScript: msg.Address, + }) + + case *lnwire.ClosingComplete: + if !r.isExpectedChanID(msg.ChannelID) { + return fn.None[ProtocolEvent]() + } + + return someEvent(&OfferReceivedEvent{ + SigMsg: *msg, + }) + + case *lnwire.ClosingSig: + if !r.isExpectedChanID(msg.ChannelID) { + return fn.None[ProtocolEvent]() + } + + return someEvent(&LocalSigReceived{ + SigMsg: *msg, + }) + } + + return fn.None[ProtocolEvent]() +}