Refactor to parse at allocation creation time. - #8
Conversation
Needs tests updated, they were reusing a few functions and a few of the metadata key names have changed to match the design doc.
meiersi-da
left a comment
There was a problem hiding this comment.
Thanks. This looks like the right direction.
|
|
||
| -- | Key used to provide an effective time to a choice execution, to avoid getTime | ||
| effectiveAtKey : Text | ||
| effectiveAtKey = "effective-at" |
There was a problem hiding this comment.
Isn't that a metadata key? I'd suggest we scope that to cip-105/
There was a problem hiding this comment.
I was feeding it in as a context key, actually - it should be constrained to an appropriately tight bound - did I hear right that the normal one is one day? - so I figured it might as well be part of the context package from the API instead of part of the user-set metadata. I actually checked here first to see whether we already had a conventional key for "now, but with the more loose time bound" and was somewhat surprised not to find one. We can certainly scope it to cip-105, of course.
There was a problem hiding this comment.
This value should be chosen by the client not the off-ledger API server. Let's discuss this evening.
| endDate : Time | ||
| initialAmount : Decimal | ||
| -- ^ The initial amount represents the total that was locked initially when thrown into vesting state | ||
| substituteControllers : Optional ControllerSets |
There was a problem hiding this comment.
don't we also need withdraw controllers? I suspect we also need them on the AggregatedLock.
There was a problem hiding this comment.
Discussed, and agreed; the case where we have non-joint auth from apps is clear motivation.
There was a problem hiding this comment.
Withdraw on AggregatedLock is controlled by unlockControllers, though. I think the next state is that both are "withdrawControllers".
There was a problem hiding this comment.
there might a confusion here:
- we are using
V2.Allocation_Withdrawfor multiple purposes - when unlocking the actors should be constrained by the unlock controllers from https://docs.google.com/document/d/13zl8ILEWq6CvSALk2LA79I2rE1PHfni1EFf5ywr-Aik/edit?tab=t.0#heading=h.imk0o4qckssp
- when withdrawing from a vesting lock they must be scoped to the "withdraw" controllers from https://docs.google.com/document/d/13zl8ILEWq6CvSALk2LA79I2rE1PHfni1EFf5ywr-Aik/edit?tab=t.0#heading=h.ddev3dkzc1vd
There was a problem hiding this comment.
Needed on the SvLock to pass to the created VestedLock - sorry, I didn't fully remember a bit of the context. Agreed.
| @@ -1,148 +1,138 @@ | |||
| module Splice.AggregateLock where | |||
There was a problem hiding this comment.
| module Splice.GovernanceLock where |
There was a problem hiding this comment.
Reasonable. I'm not sure whether this module persists separately or gets folded into AmuletAllocationV2 and ExternalPartyAmuletRules, but having it segregated like this is somewhat nice. A bit of a pain with a few bits being close to circular.
There was a problem hiding this comment.
Let's keep at least a separate module for the types and the core functions implementing the logic. If needed, we can then inline the functions that assemble the logic into the modules you mentioned.
There was a problem hiding this comment.
That's certainly reasonable. I'm just mildly annoyed at the newEmptyAllocation arguments and generic 'a' argument where this is still relying on specifically AmuletAllocationV2 rules and behavior.
| unlockControllers : Optional ControllerSets | ||
| substituteControllers : Optional ControllerSets |
There was a problem hiding this comment.
consider grouping into a GovernanceLockControllers record jointly with withdraw
There was a problem hiding this comment.
I'll put that back; the main fuss was trying to use different terminology for SvLock and VestingLock, but really, they can probably both use "withdraw" as a key.
There was a problem hiding this comment.
I'd replied without recovering the full context; having a type with unlock, substitute, and withdraw controllers is certainly appropriate for SvLock and not bad for VestingLock.
| substituteControllers : Optional ControllerSets | ||
| deriving (Eq, Show) | ||
|
|
||
| parseGovernanceLock : CanAssert m => Metadata -> m (Optional GovernanceLock) |
There was a problem hiding this comment.
I would have probably organized this using a type-class FromMetadata a, so that each sub-types parser is defined on its own; and reuse is simplified.
There was a problem hiding this comment.
Will do; I usually try to balance direct and local code against type-class and prettier, with smaller amounts leaning towards direct. I'll certainly not say no to splitting it into the type-class.
There was a problem hiding this comment.
I usually do the same, but found that for this kind of codec case the overhead on naming and testing becomes significantly lower with a kind of local helper typeclass. For example, this AnyValue codec:
|
|
||
|
|
||
| data GovernanceLock | ||
| = GovernanceLock_SVLocked AggregatedLock |
There was a problem hiding this comment.
| = GovernanceLock_SVLocked AggregatedLock | |
| = GL_SvLock SvLock | |
| | GL_FeaturedAppLock FeaturedAppLock | |
| | GL_VestingLock VestingLock |
| | GovernanceLock_VestingLocked VestingLock | ||
| deriving (Eq, Show) | ||
|
|
||
| data AggregatedLock = |
There was a problem hiding this comment.
| data AggregatedLock = | |
| data SvLock = |
| data AggregatedLock = | ||
| AggregatedLock with | ||
| lockBeneficiary : Text | ||
| unlockControllers : Optional ControllerSets |
There was a problem hiding this comment.
| unlockControllers : Optional ControllerSets | |
| unlockControllers : Optional ControllerSpecification | |
| -- ^ If set, specifies non-default controllers for unlocking the SV lock. |
| checkControllerSpecification : TM.TextMap Party -> [Party] -> ControllerSpecification -> Update () | ||
| checkControllerSpecification svRightsParties actors set = | ||
| require "Controllers must be one of the listed options" $ | ||
| any actorsMatch set | ||
| where | ||
| controllerSetFromMetaMap key = fromOptional [[acctParty]] $ controllerSetFromMeta =<< key `TM.lookup` meta.values | ||
| actorsMatch : [SvLockController] -> Bool | ||
| actorsMatch set | ||
| = all (\s -> any (`checkParty` s) actors) set | ||
| && all (\a -> any (a `checkParty`) set) actors |
There was a problem hiding this comment.
consider converting to [[Party]] and then using TokenStandardUtils.checkActors
There was a problem hiding this comment.
I'll keep checkControllerSpecification as the name and contract as a bit of cheap future-proofing, but no good reason to keep the more complex match if SvLockController always maps one-to-one to parties at an instant; I don't think we see that changing.
Needs tests updated, they were reusing a few functions and a few of the metadata key names have changed to match the design doc.
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