77 "sync"
88 "time"
99
10+ "github.com/btcsuite/btcd/btcec/v2/schnorr"
1011 "github.com/davecgh/go-spew/spew"
1112 "github.com/lightninglabs/lndclient"
1213 "github.com/lightninglabs/taproot-assets/asset"
@@ -58,7 +59,8 @@ type SerialisedScid = rfqmsg.SerialisedScid
5859type Policy interface {
5960 // CheckHtlcCompliance returns an error if the given HTLC intercept
6061 // descriptor does not satisfy the subject policy.
61- CheckHtlcCompliance (htlc lndclient.InterceptedHtlc ) error
62+ CheckHtlcCompliance (ctx context.Context , htlc lndclient.InterceptedHtlc ,
63+ specifierChecker rfqmsg.SpecifierChecker ) error
6264
6365 // Expiry returns the policy's expiry time as a unix timestamp.
6466 Expiry () uint64
@@ -145,8 +147,8 @@ func NewAssetSalePolicy(quote rfqmsg.BuyAccept) *AssetSalePolicy {
145147// included as a hop hint within the invoice. The SCID is the only piece of
146148// information used to determine the policy applicable to the HTLC. As a result,
147149// HTLC custom records are not expected to be present.
148- func (c * AssetSalePolicy ) CheckHtlcCompliance (
149- htlc lndclient.InterceptedHtlc ) error {
150+ func (c * AssetSalePolicy ) CheckHtlcCompliance (_ context. Context ,
151+ htlc lndclient.InterceptedHtlc , _ rfqmsg. SpecifierChecker ) error {
150152
151153 // Since we will be reading CurrentAmountMsat value we acquire a read
152154 // lock.
@@ -248,11 +250,23 @@ func (c *AssetSalePolicy) GenerateInterceptorResponse(
248250
249251 outgoingAmt := rfqmath .DefaultOnChainHtlcMSat
250252
251- // Unpack asset ID.
252- assetID , err := c .AssetSpecifier .UnwrapIdOrErr ()
253- if err != nil {
254- return nil , fmt .Errorf ("asset sale policy has no asset ID: %w" ,
255- err )
253+ var assetID asset.ID
254+
255+ // We have performed checks for the asset IDs inside the HTLC against
256+ // the specifier's group key in a previous step. Here we just need to
257+ // provide a dummy value as the asset ID. The real asset IDs will be
258+ // carefully picked in a later step in the process. What really matters
259+ // now is the total amount.
260+ switch {
261+ case c .AssetSpecifier .HasGroupPubKey ():
262+ groupKey := c .AssetSpecifier .UnwrapGroupKeyToPtr ()
263+ groupKeyX := schnorr .SerializePubKey (groupKey )
264+
265+ assetID = asset .ID (groupKeyX )
266+
267+ case c .AssetSpecifier .HasId ():
268+ specifierID := * c .AssetSpecifier .UnwrapIdToPtr ()
269+ copy (assetID [:], specifierID [:])
256270 }
257271
258272 // Compute the outgoing asset amount given the msat outgoing amount and
@@ -341,8 +355,9 @@ func NewAssetPurchasePolicy(quote rfqmsg.SellAccept) *AssetPurchasePolicy {
341355
342356// CheckHtlcCompliance returns an error if the given HTLC intercept descriptor
343357// does not satisfy the subject policy.
344- func (c * AssetPurchasePolicy ) CheckHtlcCompliance (
345- htlc lndclient.InterceptedHtlc ) error {
358+ func (c * AssetPurchasePolicy ) CheckHtlcCompliance (ctx context.Context ,
359+ htlc lndclient.InterceptedHtlc ,
360+ specifierChecker rfqmsg.SpecifierChecker ) error {
346361
347362 // Since we will be reading CurrentAmountMsat value we acquire a read
348363 // lock.
@@ -368,7 +383,9 @@ func (c *AssetPurchasePolicy) CheckHtlcCompliance(
368383 }
369384
370385 // Sum the asset balance in the HTLC record.
371- assetAmt , err := htlcRecord .SumAssetBalance (c .AssetSpecifier )
386+ assetAmt , err := htlcRecord .SumAssetBalance (
387+ ctx , c .AssetSpecifier , specifierChecker ,
388+ )
372389 if err != nil {
373390 return fmt .Errorf ("error summing asset balance: %w" , err )
374391 }
@@ -523,15 +540,19 @@ func NewAssetForwardPolicy(incoming, outgoing Policy) (*AssetForwardPolicy,
523540
524541// CheckHtlcCompliance returns an error if the given HTLC intercept descriptor
525542// does not satisfy the subject policy.
526- func (a * AssetForwardPolicy ) CheckHtlcCompliance (
527- htlc lndclient.InterceptedHtlc ) error {
543+ func (a * AssetForwardPolicy ) CheckHtlcCompliance (ctx context. Context ,
544+ htlc lndclient.InterceptedHtlc , sChk rfqmsg. SpecifierChecker ) error {
528545
529- if err := a .incomingPolicy .CheckHtlcCompliance (htlc ); err != nil {
546+ if err := a .incomingPolicy .CheckHtlcCompliance (
547+ ctx , htlc , sChk ,
548+ ); err != nil {
530549 return fmt .Errorf ("error checking forward policy, inbound " +
531550 "HTLC does not comply with policy: %w" , err )
532551 }
533552
534- if err := a .outgoingPolicy .CheckHtlcCompliance (htlc ); err != nil {
553+ if err := a .outgoingPolicy .CheckHtlcCompliance (
554+ ctx , htlc , sChk ,
555+ ); err != nil {
535556 return fmt .Errorf ("error checking forward policy, outbound " +
536557 "HTLC does not comply with policy: %w" , err )
537558 }
@@ -642,6 +663,10 @@ type OrderHandlerCfg struct {
642663 // HtlcSubscriber is a subscriber that is used to retrieve live HTLC
643664 // event updates.
644665 HtlcSubscriber HtlcSubscriber
666+
667+ // SpecifierChecker is an interface that contains methods for
668+ // checking certain properties related to asset specifiers.
669+ SpecifierChecker rfqmsg.SpecifierChecker
645670}
646671
647672// OrderHandler orchestrates management of accepted quote bundles. It monitors
@@ -684,7 +709,7 @@ func NewOrderHandler(cfg OrderHandlerCfg) (*OrderHandler, error) {
684709//
685710// NOTE: This function must be thread safe. It is used by an external
686711// interceptor service.
687- func (h * OrderHandler ) handleIncomingHtlc (_ context.Context ,
712+ func (h * OrderHandler ) handleIncomingHtlc (ctx context.Context ,
688713 htlc lndclient.InterceptedHtlc ) (* lndclient.InterceptedHtlcResponse ,
689714 error ) {
690715
@@ -716,7 +741,7 @@ func (h *OrderHandler) handleIncomingHtlc(_ context.Context,
716741 // At this point, we know that a policy exists and has not expired
717742 // whilst sitting in the local cache. We can now check that the HTLC
718743 // complies with the policy.
719- err = policy .CheckHtlcCompliance (htlc )
744+ err = policy .CheckHtlcCompliance (ctx , htlc , h . cfg . SpecifierChecker )
720745 if err != nil {
721746 log .Warnf ("HTLC does not comply with policy: %v " +
722747 "(HTLC=%v, policy=%v)" , err , htlc , policy )
0 commit comments