diff --git a/daml/dars.lock b/daml/dars.lock index bbcd90ddf7..63a1ab6cf1 100644 --- a/daml/dars.lock +++ b/daml/dars.lock @@ -68,6 +68,7 @@ splice-dso-governance 0.1.21 2d306cfe8cdb3daf2d21f84dfecc3e2f26a41504e58fe25cb7f splice-dso-governance 0.1.22 5c28530209b9ab37c5f187132cd826709bb18b0efe28411488ab750870414738 splice-dso-governance 0.1.23 0c94a036ac5168a1dee26b435838e062f0d2f47d6eac49303978228ae559edb9 splice-dso-governance 0.1.24 4974c654485d4ecaa6b5caf8ef3c2679efa8195c4b50d4965a8fff1b72e8efa4 +splice-dso-governance 0.1.25 b41ffa8aadafc8ae78eeb39b201eca9bc96470267d36553badd5df2a0587b16f splice-dso-governance 0.1.3 b0ae3cc03e418790305a3c15f761fe495572de5827f8d322fb8b96996b783c13 splice-dso-governance 0.1.4 dc24fd18b4d151cd1e0ff6bfb7438bafb2f50fe076d0f16f50565e60b153a0be splice-dso-governance 0.1.5 9e3ca1d22ad495dfabf3d61acae3dc1a7718f527f02092280b58cf69edfdc84c @@ -75,7 +76,7 @@ splice-dso-governance 0.1.6 4e7653cfbf7ca249de4507aca9cd3b91060e5489042a522c589d splice-dso-governance 0.1.7 d406eba1132d464605f4dae3edf8cf5ecbbb34bd8edef0e047e7e526d328718c splice-dso-governance 0.1.8 1790a114f83d5f290261fae1e7e46fba75a861a3dd603c6b4ef6b67b49053948 splice-dso-governance 0.1.9 9ee83bfd872f91e659b8a8439c5b4eaf240bcf6f19698f884d7d7993ab48c401 -splice-dso-governance-test 0.1.30 13e5d00f8e2874f2d7480a1df1e622a97733dfa97406a9a04ff293823ab942b3 +splice-dso-governance-test 0.1.31 96128520faebb74a7d11fcc80026d323d73e9d3c690e1b17f5cc86cd36e5e678 splice-token-standard-test 1.0.13 a556574314ab5ecbfa04b04a6b6c9259cf90388461fe307ba712257ad5993a6b splice-token-test-dummy-holding 0.0.1 1cd171c6c42ab46dc9cf12d80c6111369e00cea5cdf054924b4f26ce94b1ef5b splice-token-test-dummy-holding 0.0.2 4f40fb033ef3db89623642c1b494e846097fa32af138b3864a63aa15937a323d diff --git a/daml/dars/splice-dso-governance-0.1.25.dar b/daml/dars/splice-dso-governance-0.1.25.dar new file mode 100644 index 0000000000..70799af0e3 Binary files /dev/null and b/daml/dars/splice-dso-governance-0.1.25.dar differ diff --git a/daml/splice-dso-governance-test/daml.yaml b/daml/splice-dso-governance-test/daml.yaml index 7521aa2e98..abc5bd9354 100644 --- a/daml/splice-dso-governance-test/daml.yaml +++ b/daml/splice-dso-governance-test/daml.yaml @@ -1,7 +1,7 @@ sdk-version: 3.4.11 name: splice-dso-governance-test source: daml -version: 0.1.30 +version: 0.1.31 dependencies: - daml-prim - daml-stdlib diff --git a/daml/splice-dso-governance-test/daml/Splice/Scripts/TestGovernance.daml b/daml/splice-dso-governance-test/daml/Splice/Scripts/TestGovernance.daml index 0231fd5f23..1ecd8306f5 100644 --- a/daml/splice-dso-governance-test/daml/Splice/Scripts/TestGovernance.daml +++ b/daml/splice-dso-governance-test/daml/Splice/Scripts/TestGovernance.daml @@ -34,6 +34,115 @@ import Splice.Testing.Utils -- Vote Requests ---------------- +-- | Tests the Phase 1 governance-voter action taxonomy. +testGovernanceVoterActionTaxonomy : Script () +testGovernanceVoterActionTaxonomy = do + (_app, dso, (sv1, sv2, _sv3, _sv4)) <- initMainNet + provider <- allocateParty "taxonomy-provider" + beneficiary <- allocateParty "taxonomy-beneficiary" + newSv <- allocateParty "taxonomy-new-sv" + now <- getTime + [(_, dsoRules)] <- query @DsoRules dso + [(_, amuletRules)] <- query @AmuletRules dso + [(_, openRound), _, _] <- sortOn (._2.round) <$> query @OpenMiningRound dso + rightCid <- submit dso $ createCmd FeaturedAppRight with + dso + provider + + forA_ + [ ARC_DsoRules with + dsoAction = SRARC_GrantFeaturedAppRight DsoRules_GrantFeaturedAppRight with provider + , ARC_DsoRules with + dsoAction = SRARC_RevokeFeaturedAppRight DsoRules_RevokeFeaturedAppRight with rightCid + , ARC_DsoRules with + dsoAction = SRARC_SetConfig DsoRules_SetConfig with + newConfig = dsoRules.config + baseConfig = Some dsoRules.config + , ARC_DsoRules with + dsoAction = SRARC_UpdateSvRewardWeight DsoRules_UpdateSvRewardWeight with + svParty = sv1 + newRewardWeight = 1 + , ARC_DsoRules with + dsoAction = SRARC_CreateUnallocatedUnclaimedActivityRecord DsoRules_CreateUnallocatedUnclaimedActivityRecord with + beneficiary + amount = 1.0 + reason = "taxonomy test" + expiresAt = now `addRelTime` (days 1) + , ARC_DsoRules with + dsoAction = SRARC_OffboardSv DsoRules_OffboardSv with sv = sv2 + , ARC_AmuletRules with + amuletRulesAction = CRARC_SetConfig AmuletRules_SetConfig with + newConfig = amuletRules.configSchedule.initialValue + baseConfig = amuletRules.configSchedule.initialValue + ] + (\action -> isGovernanceVoterAction action === True) + + forA_ + [ ARC_DsoRules with + dsoAction = SRARC_AddSv DsoRules_AddSv with + newSvParty = newSv + newSvName = "taxonomy-new-sv" + newSvRewardWeight = 1 + newSvParticipantId = "taxonomy-participant" + joinedAsOfRound = openRound.round + , ARC_DsoRules with + dsoAction = SRARC_ConfirmSvOnboarding DsoRules_ConfirmSvOnboarding with + newSvParty = newSv + newSvName = "taxonomy-new-sv" + newParticipantId = "taxonomy-participant" + newSvRewardWeight = 1 + reason = "taxonomy test" + , ARC_DsoRules with + dsoAction = SRARC_CreateExternalPartyAmuletRules DsoRules_CreateExternalPartyAmuletRules + , ARC_DsoRules with + dsoAction = SRARC_CreateTransferCommandCounter DsoRules_CreateTransferCommandCounter with + sender = provider + , ARC_DsoRules with + dsoAction = SRARC_CreateBootstrapExternalPartyConfigStateInstruction DsoRules_CreateBootstrapExternalPartyConfigStateInstruction + , ExtActionRequiringConformation with dummyUnitField = () + ] + (\action -> isGovernanceVoterAction action === False) + +-- | Tests that vote updates keep one vote slot for the represented SV. +testVoteUpdateKeepsOneSlotPerSv : Script () +testVoteUpdateKeepsOneSlotPerSv = do + (_app, dso, (sv1, sv2, _sv3, _sv4)) <- initMainNet + [(dsoRulesCid, _)] <- query @DsoRules dso + + result <- submit (actAs sv1 <> readAs dso) $ exerciseCmd dsoRulesCid DsoRules_RequestVote with + requester = sv1 + action = ARC_DsoRules with + dsoAction = SRARC_OffboardSv DsoRules_OffboardSv with + sv = sv2 + reason = Reason with url = ""; body = "taxonomy tally test" + targetEffectiveAt = None + voteRequestTimeout = Some (days 7) + let initialRequestCid = result.voteRequest + + Some initialRequest <- queryContractId dso initialRequestCid + Map.size initialRequest.votes === 1 + case Map.lookup initialRequest.requester initialRequest.votes of + None -> fail "requester vote missing" + Some vote -> vote.sv === sv1 + + passTime (minutes 1) + result <- submit (actAs sv1 <> readAs dso) $ exerciseCmd dsoRulesCid DsoRules_CastVote with + requestCid = initialRequestCid + vote = Vote with + sv = sv1 + accept = False + reason = Reason with url = ""; body = "updated vote" + optCastAt = None + + Some updatedRequest <- queryContractId dso result.voteRequest + Map.size updatedRequest.votes === 1 + updatedRequest.trackingCid === Some initialRequestCid + case Map.lookup updatedRequest.requester updatedRequest.votes of + None -> fail "updated requester vote missing" + Some vote -> do + vote.sv === sv1 + vote.accept === False + -- | Tests vote request machinery on featured app right granting and revoking without effectivity. testVoteRequestAcceptanceWithoutEffectivity : Script () testVoteRequestAcceptanceWithoutEffectivity = do diff --git a/daml/splice-dso-governance/daml.yaml b/daml/splice-dso-governance/daml.yaml index 485e14430e..98a104b890 100644 --- a/daml/splice-dso-governance/daml.yaml +++ b/daml/splice-dso-governance/daml.yaml @@ -1,7 +1,7 @@ sdk-version: 3.4.11 name: splice-dso-governance source: daml -version: 0.1.24 +version: 0.1.25 dependencies: - daml-prim - daml-stdlib diff --git a/daml/splice-dso-governance/daml/Splice/DsoRules.daml b/daml/splice-dso-governance/daml/Splice/DsoRules.daml index 5db7ad0b6e..612e7d1495 100644 --- a/daml/splice-dso-governance/daml/Splice/DsoRules.daml +++ b/daml/splice-dso-governance/daml/Splice/DsoRules.daml @@ -124,6 +124,26 @@ data AnsEntryContext_ActionRequiringConfirmation -- ^ Automated action to reject initial payment of an ans entry. deriving (Eq, Show) +-- | Phase 1 governance-voter action taxonomy. +-- +-- This is deliberately an explicit allowlist. New action constructors are not +-- governance-voter eligible unless they are reviewed and added here. +isGovernanceVoterAction : ActionRequiringConfirmation -> Bool +isGovernanceVoterAction action = case action of + ARC_DsoRules with dsoAction -> case dsoAction of + SRARC_OffboardSv _ -> True + SRARC_GrantFeaturedAppRight _ -> True + SRARC_RevokeFeaturedAppRight _ -> True + SRARC_SetConfig _ -> True + SRARC_UpdateSvRewardWeight _ -> True + SRARC_CreateUnallocatedUnclaimedActivityRecord _ -> True + _ -> False + ARC_AmuletRules with amuletRulesAction -> case amuletRulesAction of + CRARC_SetConfig _ -> True + _ -> False + ARC_AnsEntryContext _ _ -> False + ExtActionRequiringConformation _ -> False + -- | Information about SVs relevant to DSO governance. data SvInfo = SvInfo with name : Text -- ^ Human-readable name; must be unique. diff --git a/docs/src/sv_operator/index.rst b/docs/src/sv_operator/index.rst index 5c0ef21d93..5cb638696b 100644 --- a/docs/src/sv_operator/index.rst +++ b/docs/src/sv_operator/index.rst @@ -20,6 +20,7 @@ Supervalidators sv_restore.rst sv_security.rst sv_operations.rst + sv_governance_voter.rst sv_scratchnet.rst .. todo:: Add sections top-level sections on upgrades, node onboarding, validator functionality, DR diff --git a/docs/src/sv_operator/sv_governance_voter.rst b/docs/src/sv_operator/sv_governance_voter.rst new file mode 100644 index 0000000000..b7c31317f5 --- /dev/null +++ b/docs/src/sv_operator/sv_governance_voter.rst @@ -0,0 +1,24 @@ +.. + Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +.. + SPDX-License-Identifier: Apache-2.0 + +SV Governance Voter Prototype +============================== + +The governance-voter contract work is a prototype for review under +`Canton Development Fund PR #223 `_, +especially Milestone 1: Governance-Voting Identity and CIP. + +Phase 1 preserves the current one-vote-per-SV model. A governance voter is +intended to be an alternate signer for the represented SV's vote on explicitly +supported non-operational governance actions; it is not a new voting unit and +does not add voting weight. + +The first contract slice uses a hardcoded Daml allowlist for governance-voter +eligible actions. New ``ActionRequiringConfirmation`` constructors are rejected +by default until reviewed and added deliberately. The proposed allowlist is +intended to be concrete enough for maintainer and CIP review, not a final +statement of upstream governance policy. In particular, inclusion of +``SRARC_OffboardSv`` should be validated through that review because it is a +high-impact governance membership action.