Is it possible to have circular references in Daml?

By this I mean something like

template A with ref : ContractId A ...

Such that we have ledger instance for A like this:

cid ref
1 2
2 1

If so , what would a program to create these look like?

Even if such a program can’t be written, could such a ledger still exist, and could you write a valid Daml program to access it?

ContractIds are just tagged strings to your ability to create a circular reference is dependent on being able to predict contractIds.

ContractIds on a production ledger are generally not predictable. If you could get a predict contractIds, you could generate a contractId clash which is bad. So in practice you will never get a circular dependency like you are hoping for.

If you did, it would not really be a problem though. Again, ContractIds are just tagged strings. You have a trivial “circular” dependency by having the. Implicit self available in the context of a contract anyway.

You can get circular dependencies through Contract Keys, which is my recommended way of referencing other contracts.

@bernhard Does this capture the idea?

import Daml.Script
import DA.Assert

template Person with
    owner : Party
    name : Text
    fullname : Text
    spouse : Text
  where
    signatory owner
    key (owner, name) : (Party, Text)
    maintainer key._1

    nonconsuming choice Invite : Text
      with
        controller owner
        do
          (_, s) <- fetchByKey @Person (owner, spouse)
          pure $ fullname <> " and " <> s.fullname

test = script do

  -- arrange
  owner <- allocateParty "Owner"
  johnny <- submit owner do
    createCmd Person with
      name = "Johnny", fullname = "Johnny Cash"
      spouse = "June", ..
  june <- submit owner do
    createCmd Person with
      name = "June", fullname = "June Carter"
      spouse = "Johnny", ..
  
  -- act
  invite <- submit owner do exerciseCmd johnny Invite

  -- assert
  invite === "Johnny Cash and June Carter"
2 Likes

Yes, exactly.

Thanks both for your insights.

@bernhard, from your response, I’ll infer that creating circular deps using contract IDs is not possible.

I suppose what I really want to ask is whether the ‘abstract ledger model’ says anything that would disallow these kind of relationships?

The abstract ledger model has no notion of one contract referencing another. Only exercise nodes reference contracts, and there the causality is clear. Exercise nodes referencing contracts as input come strictly after the create of the contract.