WIP: FA underlock automation DAML - #16
Conversation
| nextScheduledLogicalSynchronizerUpgrade: Optional LogicalSynchronizerUpgradeSchedule | ||
| faDefaultRequiredLockAmount : Optional Decimal -- ^ The amount of amulet required to be locked by an FA to maintain their FeaturedAppRight if its requiredLockAmount is None. | ||
| faUnderlockGracePeriod : Optional RelTime -- ^ The amount of time after which automatic enforcement will withdraw a FeaturedAppRight if its provider remains underlocked. | ||
| faUnderlockEnforcementEnabled : Optional Bool -- ^ Whether automatic FA underlock enforcement may now occur, used to support a transitionary period. |
There was a problem hiding this comment.
This could be a timestamp instead to announce a ledger time
There was a problem hiding this comment.
this is coming in 0.8.0: canton-network#6968
There was a problem hiding this comment.
Ah, yeah, I was also thinking about that TextMap from my design doc, but just wanted to put something provisional in place for this exploration.
|
|
||
| -- | This is an enumeration of the transitions in underlocking state that can be caused by DsoRules_UpdateFeaturedAppUnderlock | ||
| data FaUnderlockTransition = | ||
| FaUnderlockTransition_Open -- ^ Transition to underlocked state |
There was a problem hiding this comment.
Not sure if we want to put a dummy field here to futureproof against SCU
There was a problem hiding this comment.
Depends on what kind of changes we expect. It seems though that we might not need this type at all.
meiersi-da
left a comment
There was a problem hiding this comment.
Thanks. I agree with the direction. For details see my comments.
| firstUnderlockObservedAt : Optional Time | ||
| -- ^ Ledger time at which the DSO first observed this provider underlocked. | ||
| -- Some t means suspended since time t, and archivable from t + grace period. | ||
| -- None means compliant. Never set before enforcement is activated. |
There was a problem hiding this comment.
Never set before enforcement is activated.
why is that?
There was a problem hiding this comment.
I'm thinking here of the transitional period where we begin to allow FAs to properly re-lock their funds (begins as soon as the DARs go out), but before we begin actually starting the timers. Maybe we could say the grace period is all you get, but my impression was that it ought to be a bit longer.
There was a problem hiding this comment.
OK, I see. I would probably not note that in the Daml code. The Impl. CIP has this two stage nature built in: https://docs.google.com/document/d/1VGtgNSNHrHnSLggqxlvhCTFrMPgaeCs2OLEJ8Fq9Ar4/edit?tab=t.753u8f9hx8hv#bookmark=id.ck925sjr9rre
| featuredAppRightCid <- create this with | ||
| firstUnderlockObservedAt = newObservedAt | ||
| return FeaturedAppRight_UpdateUnderlockResult with | ||
| featuredAppRightCid |
There was a problem hiding this comment.
Missing: the immediate loss of the ability to create featured app markers if they are underlocked
| requiredLockAmount : Optional Decimal | ||
| -- ^ Override of the network-wide minimum lock threshold. | ||
| -- None means that the default in DsoRulesConfig applies. | ||
| firstUnderlockObservedAt : Optional Time |
There was a problem hiding this comment.
I'm inclined to do the join with the grace period at the time where the underlock is observed and not when it is enforced. Something like:
underlockRecoveryDeadline : Optional Time
It has the advantage that an app right can be understood on its own, and we can just add a choice FeaturedApp_EnforceUnderlock that archives the app right.
This also solves the confusion that "first" could refer to the first of all the underlocks, or the first one of the non-recovered underlocks, which actually is the case.
| controller provider | ||
| do return FeaturedAppRight_CancelResult | ||
|
|
||
| choice FeaturedAppRight_UpdateUnderlock : FeaturedAppRight_UpdateUnderlockResult |
There was a problem hiding this comment.
| choice FeaturedAppRight_UpdateUnderlock : FeaturedAppRight_UpdateUnderlockResult | |
| choice FeaturedAppRight_UpdateUnderlockStatus : FeaturedAppRight_UpdateUnderlockResult |
There was a problem hiding this comment.
Given that you anyways call withdraw directly from DsoRules, I'm wondering whether we shouldn't implement the whole underlock logic in DsoRules, and thus save code.
There was a problem hiding this comment.
Also consider introducing a data FeaturedAppUnderlockState to make future changes to the underlock logic easy.
| nextScheduledLogicalSynchronizerUpgrade: Optional LogicalSynchronizerUpgradeSchedule | ||
| faDefaultRequiredLockAmount : Optional Decimal -- ^ The amount of amulet required to be locked by an FA to maintain their FeaturedAppRight if its requiredLockAmount is None. | ||
| faUnderlockGracePeriod : Optional RelTime -- ^ The amount of time after which automatic enforcement will withdraw a FeaturedAppRight if its provider remains underlocked. | ||
| faUnderlockEnforcementEnabled : Optional Bool -- ^ Whether automatic FA underlock enforcement may now occur, used to support a transitionary period. |
There was a problem hiding this comment.
this is coming in 0.8.0: canton-network#6968
| case transition of | ||
| FaUnderlockTransition_Open -> void $ exercise rightCid FeaturedAppRight_UpdateUnderlock with underlocked = True | ||
| FaUnderlockTransition_Close -> void $ exercise rightCid FeaturedAppRight_UpdateUnderlock with underlocked = False | ||
| FaUnderlockTransition_Enforce -> do |
There was a problem hiding this comment.
This one doesn't require off-ledger validation. wdyt about moving it into its own choice?
| -- ^ Weight of the this provider's app activity in the computation of traffic-based app rewards. | ||
| -- | ||
| -- If not set, the default weight of 1.0 is used. | ||
| requiredLockAmount : Optional Decimal |
There was a problem hiding this comment.
missing: choice to update this amount
I actually realize that we missed an opportunity to make it easy to store additional config parameters on an FA right when we added featured app rights.
Given that we anyways need to add support for instruction contracts to change a featured app right, I suggest to do the following:
-- 1. introduce two new types
data FeaturedAppConfig = FeaturedAppConfig with
activityWeight : Decimal
requiredLockAmount : Optional Decimal
data FeaturedAppConfigInternal = FeaturedAppConfigInternal with
requiredLockAmount : Optional Decimal
-- and use the latter to store a field `config : FeaturedAppConfigInternal` on `FeaturedAppRight`
-- 2. introduce choice to update the current config using `patchable`. The trick is to store the config in an exploded form
choice FeaturedAppRight_UpdateConfig with
baseConfig : FeaturedAppConfig
newConfig : FeaturedAppConfig
-- 3. introduce an instruction for config changes in DsoRules to solve the stable references problem; and prepare for more config being stored on FeaturedAppRights
|
|
||
| nonconsuming choice DsoRules_UpdateFeaturedAppUnderlock : DsoRules_UpdateFeaturedAppUnderlockResult | ||
| with | ||
| rightCid : ContractId FeaturedAppRight |
There was a problem hiding this comment.
There's a bit of a problem brewing with the approach we are choosing here: the featured app right is referenced by contract-id in DsoRules_UpdateFeaturedAppRight, which in turn is used to execute votes. This only works if concurrent changes to app rights are very seldom.
That will no longer be the case with underlock updates. We have handled this in the past by creating "instruction"-contracts that can then be executed by an SV operator party. See for example https://github.com/canton-network/splice/blob/6e96647fc53583fd3b515c0fb17c1e253364e89e/daml/splice-dso-governance/daml/Splice/DsoRules.daml#L2012-L2020
I suspect that we have to do the same for the featured app rights for both its existing FeaturedAppRight_Update and the new FeaturedAppRight_UpdateUnderlock choice.
| (observedAt `addRelTime` getFaUnderlockGracePeriod this.config <= now) | ||
| void $ exercise rightCid FeaturedAppRight_Withdraw with | ||
| reason = "CIP-XXX underlock enforcement" | ||
| return DsoRules_UpdateFeaturedAppUnderlockResult |
There was a problem hiding this comment.
Generally logic that affects amulet users (e.g., app providers) is captured in AmuletRules and DsoRules only forwards to these choices. It's mostly a code organization principle that we use to ensure that one can reason about amulet related guarantees w/o looking at DsoRules.
I do though have a hard time judging how much extra code that introduces if any at all. If it is a lot, we need to judge whether the change is worth it.
So what I'd suggest is that you first implement the full logic with instructions, and the check how much effort the moving would be.
|
|
||
| -- | This is an enumeration of the transitions in underlocking state that can be caused by DsoRules_UpdateFeaturedAppUnderlock | ||
| data FaUnderlockTransition = | ||
| FaUnderlockTransition_Open -- ^ Transition to underlocked state |
There was a problem hiding this comment.
Depends on what kind of changes we expect. It seems though that we might not need this type at all.
Pull Request Checklist
Cluster Testing
/cluster_teston this PR to request it, and ping someone with access to the DA-internal system to approve it./upgrade_teston this PR to request it, and ping someone with access to the DA-internal system to approve it./hdm_teston this PR to request it, and ping someone with access to the DA-internal system to approve it./lsu_teston this PR to request it, and ping someone with access to the DA-internal system to approve it.PR Guidelines
Fixes #n, and mention issues worked on using#nMerge Guidelines