Skip to content

WIP: cip 0105 externally implemented governance locks - #6427

Draft
jonored wants to merge 26 commits into
canton-network:mainfrom
obsidiansystems:jg/cip-0105-externally-implemented-governance-locks
Draft

WIP: cip 0105 externally implemented governance locks#6427
jonored wants to merge 26 commits into
canton-network:mainfrom
obsidiansystems:jg/cip-0105-externally-implemented-governance-locks

Conversation

@jonored

@jonored jonored commented Jul 15, 2026

Copy link
Copy Markdown

WIP code for possible direction for CIP-0105 locking implementation using the existing AmuletAllocationV2 unmodified, for reference only. Do not merge.

Pull Request Checklist

Cluster Testing

  • If a cluster test is required, comment /cluster_test on this PR to request it, and ping someone with access to the DA-internal system to approve it.
  • If an upgrade test is required, comment /upgrade_test on this PR to request it, and ping someone with access to the DA-internal system to approve it.
  • If a hard-migration test is required (from the latest release), comment /hdm_test on this PR to request it, and ping someone with access to the DA-internal system to approve it.
  • If a logical synchronizer upgrade test is required (from canton-3.5), comment /lsu_test on this PR to request it, and ping someone with access to the DA-internal system to approve it.

PR Guidelines

  • Include any change that might be observable by our partners or affect their deployment in the release notes.
  • Specify fixed issues with Fixes #n, and mention issues worked on using #n
  • Include a screenshot for frontend-related PRs - see README or use your favorite screenshot tool

Merge Guidelines

  • Make the git commit message look sensible when squash-merging on GitHub (most likely: just copy your PR description).

-- vesting to be in a separate dar from amulet only needed for SVs and
-- interested observers.

template AggregateLock

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unclear to me why this is a separate template, ideally this would be done through the withdraw choice. If that is not an option, it seems like this could just be a choice on ExternalPartyAmuletRules

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment still applies

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current in-progress plan is to remove at least the choices (moving to allocation withdraw), and probably the whole template. The remaining pieces that need to land somewhere else are early unlock support (which may be it's own tiny "allow early unlock" template provided as context to withdraw) and producing an appropriate key to group lock allocations with.

Comment thread daml/splice-amulet/daml/Splice/AggregateLock.daml Outdated
Comment thread daml/splice-amulet/daml/Splice/AggregateLock.daml Outdated
Comment thread daml/splice-amulet/daml/Splice/AggregateLock.daml
Comment thread daml/splice-amulet/daml/Splice/AggregateLock.daml Outdated
Comment on lines +67 to +68
lockedCid : ContractId Allocation
withdrawToCid : ContractId Allocation

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add some comments on how you expect the two allocations to be used? it's not clear to me. Or even better add the test script.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment still applies, add some comments on what the allocations are supposed to represent

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lockedCid was the active lock and withdrawTo was a fresh allocation to hold the withdrawn-to-vesting funds. Removed with the move to integrate into allocation withdraw, where the contract operates explicitly with the holder's authority as well as whatever is in the flexible controller lists.


type ControllerSets = [[Party]]

partiesFromText : Text -> Optional [Party]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are a bunch of utilities already e.g. parseCommaSeparated, let's reuse those instead of reimplementing half of them.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment still applies

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed below. Do we want to do the same with controllerSetFromMeta and make a helper utility function for semi-colons?

Comment thread daml/splice-amulet/daml/Splice/AggregateLock.daml Outdated
Comment thread daml/splice-amulet/daml/Splice/AggregateLock.daml Outdated
Comment thread daml/splice-amulet/daml/Splice/AggregateLock.daml Outdated
Comment thread daml/splice-amulet/daml/Splice/AggregateLock.daml Outdated
Comment thread daml/splice-amulet-test/daml/Splice/Scripts/TestAggregateLocks.daml Outdated
Comment thread daml/splice-amulet-test/daml/Splice/Scripts/TestAggregateLocks.daml Outdated
…evelopment cycles by allowing the LSP to work cross-package when working on code.
partiesToMeta,
dropMeta,
validateNoMeta,
-- TODO: Is exporting the below cool?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes that's ok

-- Lock some funds for the aggregate
AllocationInstructionResult { output = AllocationInstructionResult_Completed locked } <- lockForAggregate env 1000.0 bob aggLock

-- Check total for the aggregate; needs to be implemented.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's actually add that

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Total check in the test is on the way.


type ControllerSets = [[Party]]

partiesFromText : Text -> Optional [Party]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment still applies

-- vesting to be in a separate dar from amulet only needed for SVs and
-- interested observers.

template AggregateLock

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment still applies

-- "the settlement" for the allocations locked to it, and use iterated
-- settlement to execute updates on the committed allocations as needed.
-- This approach would permit most of the specific governance locking and
-- vesting to be in a separate dar from amulet only needed for SVs and

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

separate dar comment doesn't make much sense imho

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed and agreed given the additional context, removal of most or all is in progress.


-- We should have one result from settleBatch
require "VestingUnlock_Withdraw should result in one allocation result. " $
L.length batchResults.allocationSettleResults == 1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similar as above with the isNone + fromSome, don't first do an assertion and then a partial match but instead just pattern match directly

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


assert $ length allocations == 2

-- Need to check other than via inspection that the two allocations actually exist with correct values.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's add it


now <- getTime
let initialAmountToUnlock = 365.25
AllocationInstructionResult { output = AllocationInstructionResult_Completed vestingInput } <- lockForVesting initialAmountToUnlock (addRelTime now $ minutes 5) env bob aggLock

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why + 5 min

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was a condition in validateVestingSchedule which said now < start which would not be satisfied unless there was a strict time difference there. Unless there's a good reason, that maybe ought to be now <= start, and I don't see any reason in our design doc, but perhaps @jonored knows better?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<= seems fine

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

authorizers = [ bob ]
vestingLockCid = toInterfaceContractId vestingLockAllocationCid
extraArgs = enriched.arg.extraArgs
debug vestingAllocResult

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's remove all these random debugs

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

let [(_, (Some unlockedHolding))] = filter (\(hcid, (Some h)) -> isNone h.lock && hcid `elem` holdingCids) holdings
debug unlockedHolding

let tolerance = 0.01

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the tolerance for? I don't see why you can't do an exact computation in your test

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This tolerance is because the actual number is extremely close to, but not exactly 10. However, it might be best just to copy the computed number into the test, given that Decimal is fixed point, an exact equality comparison is not as bad as it might otherwise be for floating point. To get a nice round number of tokens here, we'd need to very precisely compute the time interval we waited for (there is presumably some number of microseconds at which the value is exactly 10).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -0,0 +1,29 @@
#!/usr/bin/env bash

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change is merged, please rebase and remove from this pr

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that was an accident because I'd previously cherry-picked it onto the branch. Sorry!

…ing up development cycles by allowing the LSP to work cross-package when working on code."

This reverts commit 15dfa70.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants