`RegisteredTemplates [ ]` behaves as `AllInDar`

Apparently if a trigger specification has registeredTemplates = RegisteredTemplates [ ], it behaves as if registeredTemplates = AllInDar was specified. Is this always the case?

MWE:

-- Usage:
-- daml start
-- daml trigger --wall-clock-time --dar .daml/dist/*.dar --trigger-name RegisteredTemplates:trigger --ledger-host localhost --ledger-port 6865 --ledger-party Alice

module RegisteredTemplates where

import Daml.Trigger as Trigger
import DA.Foldable (forA_)

template A
  with
    p : Party
  where
    signatory p

template B
  with
    p : Party
  where
    signatory p

trigger: Trigger ()
trigger = Trigger
  { initialize = pure ()
  , updateState = \_ -> pure ()
  , rule = triggerImpl
  , registeredTemplates = RegisteredTemplates [
      -- registeredTemplate @A -- Uncomment this line, then the trigger will not find B, only A
    ]
  , heartbeat = None
  }

triggerImpl: Party -> TriggerA () ()
triggerImpl party = do
  as <- Trigger.query @A
  forA_ as (\(cid, _) -> cid `Trigger.dedupExercise` Archive)
  bs <- Trigger.query @B
  forA_ bs (\(cid, _) -> cid `Trigger.dedupExercise` Archive)
1 Like

Good question! This was definitely not intentional. However, ignoring triggers for a minute and looking at the ledger behavior, I am a bit confused:

The docs for the filter are as follows:

message Filters {

  // If not set, no filters will be applied.
  // Optional
  InclusiveFilters inclusive = 1;
}

// If no internal fields are set, no data will be returned.
message InclusiveFilters {

  // A collection of templates.
  // SHOULD NOT contain duplicates.
  // Required
  repeated Identifier template_ids = 1;
}

However, I tried the following 3 examples and they seem to apply no filtering:

  1. No filter, this is fine according to the docs this should apply no filters.
grpcurl 
 -d '{"ledger_id": "l", "filter": {"filtersByParty": {"Alice": {}}}, "begin": {"boundary": "LEDGER_BEGIN"}, "end": {"boundary": "LEDGER_END"}}' 
 -plaintext localhost:6865
 com.daml.ledger.api.v1.TransactionService/GetTransactions
  1. Set inclusive with no template ids, this seems wrong to me. I didn’t set any inner fields so I would expect to get back no data but I still get back everything.
grpcurl
   -d '{"ledger_id": "l", "filter": {"filtersByParty": {"Alice": {"inclusive": {}}}}, "begin": {"boundary": "LEDGER_BEGIN"}, "end": {"boundary": "LEDGER_END"}}' 
  -plaintext localhost:6865 
  com.daml.ledger.api.v1.TransactionService/GetTransactions
  1. Just to sanity check, I also tried an empty list of template ids. This should be equivalent to not setting the field in protobuf but :woman_shrugging:
grpcurl
  -d '{"ledger_id": "l", "filter": {"filtersByParty": {"Alice": {"inclusive": {"template_ids": []}}}}, "begin": {"boundary": "LEDGER_BEGIN"}, "end": {"boundary": "LEDGER_END"}}'
  -plaintext localhost:6865
  com.daml.ledger.api.v1.TransactionService/GetTransactions

So I’m struggling a bit to figure out how you are supposed to send a request that filters out all data.

1 Like

An empty list of inclusive filters is treated the same way as a missing filter definition (see LedgerBackedIndexService.scala#L156).

I think it would be sensible to reject a request with an empty inclusive filter with INVALID_ARGUMENT.

What’s the use case for sending a request that filters out all data?

@gerolf I don’t have a usecase, I mainly got confused because the docs atm claim // If no internal fields are set, no data will be returned.. Updating docs is perfectly fine with me.

Oh, sorry, I missed that bit. Yeah, I think instead of rejecting the request we should rather change the documentation.

The documentation has now been updated to reflect the current behavior.

Going back to the original question, triggers are at least consistent with how filters work on the ledger API and the docs. Maybe still worth emitting a warning if you specify an empty list of registered templates in triggers since it doesn’t seem very useful.