@@ -88,6 +88,9 @@ type Policy interface {
8888 GenerateInterceptorResponse (
8989 lndclient.InterceptedHtlc ) (* lndclient.InterceptedHtlcResponse ,
9090 error )
91+
92+ // QuoteID returns the RFQ ID if it exists, otherwise false.
93+ QuoteID () (rfqmsg.ID , bool )
9194}
9295
9396// AssetSalePolicy is a struct that holds the terms which determine whether an
@@ -325,6 +328,11 @@ func (c *AssetSalePolicy) GenerateInterceptorResponse(
325328 }, nil
326329}
327330
331+ // QuoteID returns the RFQ identifier that originated this policy.
332+ func (c * AssetSalePolicy ) QuoteID () (rfqmsg.ID , bool ) {
333+ return c .AcceptedQuoteId , true
334+ }
335+
328336// Ensure that AssetSalePolicy implements the Policy interface.
329337var _ Policy = (* AssetSalePolicy )(nil )
330338
@@ -537,6 +545,11 @@ func (c *AssetPurchasePolicy) GenerateInterceptorResponse(
537545 }, nil
538546}
539547
548+ // QuoteID returns the RFQ identifier that originated this policy.
549+ func (c * AssetPurchasePolicy ) QuoteID () (rfqmsg.ID , bool ) {
550+ return c .AcceptedQuoteId , true
551+ }
552+
540553// Ensure that AssetPurchasePolicy implements the Policy interface.
541554var _ Policy = (* AssetPurchasePolicy )(nil )
542555
@@ -674,6 +687,13 @@ func (a *AssetForwardPolicy) GenerateInterceptorResponse(
674687 }, nil
675688}
676689
690+ // QuoteID returns the RFQ identifier that originated this policy.
691+ //
692+ // Forward policies do not map to a single quote, hence we return false.
693+ func (a * AssetForwardPolicy ) QuoteID () (rfqmsg.ID , bool ) {
694+ return rfqmsg.ID {}, false
695+ }
696+
677697// Ensure that AssetForwardPolicy implements the Policy interface.
678698var _ Policy = (* AssetForwardPolicy )(nil )
679699
@@ -707,6 +727,9 @@ type OrderHandlerCfg struct {
707727 // that is encapsulated in the init and reestablish peer messages. This
708728 // helps us communicate custom feature bits with our peer.
709729 AuxChanNegotiator * tapfeatures.AuxChannelNegotiator
730+
731+ // PolicyStore persists agreed RFQ policies.
732+ PolicyStore PolicyStore
710733}
711734
712735// OrderHandler orchestrates management of accepted quote bundles. It monitors
@@ -719,6 +742,9 @@ type OrderHandler struct {
719742 // cfg holds the configuration parameters for the RFQ order handler.
720743 cfg OrderHandlerCfg
721744
745+ // policyStore provides persistence for agreed policies.
746+ policyStore PolicyStore
747+
722748 // policies is a map of serialised short channel IDs (SCIDs) to
723749 // associated asset transaction policies.
724750 policies lnutils.SyncMap [SerialisedScid , Policy ]
@@ -736,8 +762,9 @@ type OrderHandler struct {
736762// NewOrderHandler creates a new struct instance.
737763func NewOrderHandler (cfg OrderHandlerCfg ) (* OrderHandler , error ) {
738764 return & OrderHandler {
739- cfg : cfg ,
740- policies : lnutils.SyncMap [SerialisedScid , Policy ]{},
765+ cfg : cfg ,
766+ policyStore : cfg .PolicyStore ,
767+ policies : lnutils.SyncMap [SerialisedScid , Policy ]{},
741768 ContextGuard : & fn.ContextGuard {
742769 DefaultTimeout : DefaultTimeout ,
743770 Quit : make (chan struct {}),
@@ -965,6 +992,11 @@ func (h *OrderHandler) RegisterAssetSalePolicy(buyAccept rfqmsg.BuyAccept) {
965992 buyAccept , h .cfg .NoOpHTLCs , h .cfg .AuxChanNegotiator ,
966993 )
967994
995+ if err := h .storeSalePolicy (buyAccept ); err != nil {
996+ log .Errorf ("Unable to persist asset sale policy (id=%x): %v" ,
997+ buyAccept .ID [:], err )
998+ }
999+
9681000 h .policies .Store (policy .AcceptedQuoteId .Scid (), policy )
9691001}
9701002
@@ -978,9 +1010,72 @@ func (h *OrderHandler) RegisterAssetPurchasePolicy(
9781010 "sell accept message: %s" , sellAccept .String ())
9791011
9801012 policy := NewAssetPurchasePolicy (sellAccept )
1013+
1014+ if err := h .storePurchasePolicy (sellAccept ); err != nil {
1015+ log .Errorf ("Unable to persist asset purchase policy " +
1016+ "(id=%x): %v" , sellAccept .ID [:], err )
1017+ }
1018+
9811019 h .policies .Store (policy .scid , policy )
9821020}
9831021
1022+ func (h * OrderHandler ) storeSalePolicy (buyAccept rfqmsg.BuyAccept ) error {
1023+ ctx , cancel := h .WithCtxQuit ()
1024+ defer cancel ()
1025+
1026+ return h .policyStore .StoreSalePolicy (ctx , buyAccept )
1027+ }
1028+
1029+ func (h * OrderHandler ) storePurchasePolicy (
1030+ sellAccept rfqmsg.SellAccept ) error {
1031+
1032+ ctx , cancel := h .WithCtxQuit ()
1033+ defer cancel ()
1034+
1035+ return h .policyStore .StorePurchasePolicy (ctx , sellAccept )
1036+ }
1037+
1038+ func (h * OrderHandler ) restorePersistedPolicies (buyAccepts []rfqmsg.BuyAccept ,
1039+ sellAccepts []rfqmsg.SellAccept ) {
1040+
1041+ for _ , accept := range buyAccepts {
1042+ policy := NewAssetSalePolicy (
1043+ accept , h .cfg .NoOpHTLCs , h .cfg .AuxChanNegotiator ,
1044+ )
1045+ h .policies .Store (policy .AcceptedQuoteId .Scid (), policy )
1046+ }
1047+
1048+ for _ , accept := range sellAccepts {
1049+ policy := NewAssetPurchasePolicy (accept )
1050+ h .policies .Store (policy .scid , policy )
1051+ }
1052+ }
1053+
1054+ func (h * OrderHandler ) removePolicy (scid SerialisedScid ,
1055+ policy Policy ) {
1056+
1057+ h .policies .Delete (scid )
1058+ h .deactivatePersistedPolicy (policy )
1059+ }
1060+
1061+ func (h * OrderHandler ) deactivatePersistedPolicy (policy Policy ) {
1062+ id , ok := policy .QuoteID ()
1063+ if ! ok {
1064+ return
1065+ }
1066+
1067+ ctx , cancel := h .WithCtxQuit ()
1068+ defer cancel ()
1069+
1070+ err := h .policyStore .DeactivatePolicy (
1071+ ctx , id , time .Now ().UTC (),
1072+ )
1073+ if err != nil {
1074+ log .Errorf ("Unable to deactivate persisted policy id=%x: %v" ,
1075+ id [:], err )
1076+ }
1077+ }
1078+
9841079// fetchPolicy fetches a policy which is relevant to a given HTLC. If a policy
9851080// is not found, false is returned. Expired policies are not returned and are
9861081// removed from the cache.
@@ -1049,12 +1144,12 @@ func (h *OrderHandler) fetchPolicy(htlc lndclient.InterceptedHtlc) (Policy,
10491144 outgoingPolicy := outPolicy
10501145
10511146 if incomingPolicy .HasExpired () {
1052- scid := incomingPolicy .Scid ()
1053- h .policies . Delete ( SerialisedScid ( scid ) )
1147+ inScid := SerialisedScid ( incomingPolicy .Scid () )
1148+ h .removePolicy ( inScid , incomingPolicy )
10541149 }
10551150 if outgoingPolicy .HasExpired () {
1056- scid := outgoingPolicy .Scid ()
1057- h .policies . Delete ( SerialisedScid ( scid ) )
1151+ outScid := SerialisedScid ( outgoingPolicy .Scid () )
1152+ h .removePolicy ( outScid , outgoingPolicy )
10581153 }
10591154
10601155 // If either the incoming or outgoing policy has expired, we
@@ -1098,7 +1193,7 @@ func (h *OrderHandler) fetchPolicy(htlc lndclient.InterceptedHtlc) (Policy,
10981193 scid := * foundScid
10991194
11001195 if policy .HasExpired () {
1101- h .policies . Delete (scid )
1196+ h .removePolicy (scid , policy )
11021197 return nil , false , nil
11031198 }
11041199
@@ -1114,7 +1209,7 @@ func (h *OrderHandler) cleanupStalePolicies() {
11141209 func (scid SerialisedScid , policy Policy ) error {
11151210 if policy .HasExpired () {
11161211 staleCounter ++
1117- h .policies . Delete (scid )
1212+ h .removePolicy (scid , policy )
11181213 }
11191214
11201215 return nil
0 commit comments