Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4241,7 +4241,7 @@ object DarResources {
)
val dsoGovernance_0_1_28 = DarResource(
"splice-dso-governance-0.1.28.dar",
"d1ceb0493b95818b6edb8018370b0231ef8a6237bd03e896803130e16dfd3b7f",
"fbe0681d6c1f55e269be120f11f416c975707dbe704168c6929d087cbf9655d0",
PackageMetadata(
PackageName.assertFromString("splice-dso-governance"),
PackageVersion.assertFromString("0.1.28"),
Expand Down Expand Up @@ -4305,7 +4305,7 @@ object DarResources {
)
val dsoGovernance_current = DarResource(
"splice-dso-governance-current.dar",
"d1ceb0493b95818b6edb8018370b0231ef8a6237bd03e896803130e16dfd3b7f",
"fbe0681d6c1f55e269be120f11f416c975707dbe704168c6929d087cbf9655d0",
PackageMetadata(
PackageName.assertFromString("splice-dso-governance"),
PackageVersion.assertFromString("0.1.28"),
Expand Down
4 changes: 2 additions & 2 deletions daml/dars.lock
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,15 @@ splice-dso-governance 0.1.24 4974c654485d4ecaa6b5caf8ef3c2679efa8195c4b50d4965a8
splice-dso-governance 0.1.25 dfe102514acd41f79945b8363ca84d8243be97b2b235522ce77c754a36bb8479
splice-dso-governance 0.1.26 45099e955ce443f7895125097a62c509b9ad297091c91d6377ffe94f183c0e3e
splice-dso-governance 0.1.27 014473d35514cb36583bdeca269386e46ae4e2283fe9b04beb2f53cdb408e1a2
splice-dso-governance 0.1.28 d1ceb0493b95818b6edb8018370b0231ef8a6237bd03e896803130e16dfd3b7f
splice-dso-governance 0.1.28 fbe0681d6c1f55e269be120f11f416c975707dbe704168c6929d087cbf9655d0
splice-dso-governance 0.1.3 b0ae3cc03e418790305a3c15f761fe495572de5827f8d322fb8b96996b783c13
splice-dso-governance 0.1.4 dc24fd18b4d151cd1e0ff6bfb7438bafb2f50fe076d0f16f50565e60b153a0be
splice-dso-governance 0.1.5 9e3ca1d22ad495dfabf3d61acae3dc1a7718f527f02092280b58cf69edfdc84c
splice-dso-governance 0.1.6 4e7653cfbf7ca249de4507aca9cd3b91060e5489042a522c589d3c4199580cd8
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.34 c1f017c15bb39f1f43128c03767579907e74f43b7950a9f6877b8333362c7dcd
splice-dso-governance-test 0.1.34 5c792944831e9257a35d9f55c12d4a76f57e948b872163f06398ee72e2104c2d
splice-test-token-v1 1.0.0 aaa0b576b5a3db49b3a4f7a4710fe6f8ae462aabbde4da89f639eb87fd62e90c
splice-test-token-v1-test 1.0.1 397e9016f18a08c7b28abc5f26d10e6ed4bfb4593321e21c396992642061e84f
splice-test-token-v2 1.0.0 a38a96b6f46c14c599b2763bc4fc68911a9cada90f89c599a1401e8e3df685e1
Expand Down
Binary file modified daml/dars/splice-dso-governance-0.1.28.dar
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import Splice.Scripts.DsoTestUtils

test_ExtensionRewards_viaVote : Script ()
test_ExtensionRewards_viaVote = do
(app, dso, (sv1, sv2, sv3, sv4)) <- initMainNet
(app, _dso, (sv1, sv2, sv3, sv4)) <- initMainNet

operator <- allocateParty "dedicatedSyncOperator"
featured <- allocateParty "featuredAppOnExtension"
Expand All @@ -43,14 +43,10 @@ test_ExtensionRewards_viaVote = do
-- The vote-created registration authorizes reward processing below.
[(regCid, _)] <- query @RegisteredSynchronizer operator

-- Reporting state (created directly as the DSO party in this PoC; production wiring of the
-- state creation is part of the registration follow-ups).
stateCid <- submit dso $ createCmd DedicatedSynchronizerState with
dso
synchronizerId = dedicatedSyncId
operator
lastReportedRound = None
totalActivityReported = 0.0
-- Registration created the reporting state; the operator reports against it.
[(stateCid, st)] <- query @DedicatedSynchronizerState operator
st.synchronizerId === dedicatedSyncId
st.totalActivityReported === 0.0

-- The operator reports a single-leaf tree of activity weights for round 1.
let leaf = BatchOfMintingAllowances [MintingAllowance with provider = featured; amount = 25.0]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ import Daml.Script
import Splice.DsoRules
-- The registry contract created by the vote. It lives in splice-amulet (AmuletRules must be
-- able to fetch it), and this test package data-depends on splice-amulet.
import Splice.DecentralizedSynchronizer (RegisteredSynchronizer)
import Splice.Amulet.CryptoHash qualified as CryptoHash
import Splice.Amulet.RewardAccountingV2 (Batch(..))
import Splice.DecentralizedSynchronizer
import Splice.Types (Round(..))

-- Shared helpers that spin up a 4-SV network and drive a vote end-to-end.
import Splice.Scripts.DsoTestUtils
Expand Down Expand Up @@ -54,3 +57,52 @@ test_RegisterSynchronizer_viaVote = do
-- The operator is an observer, so it can see its own registration.
operatorView <- query @RegisteredSynchronizer operator
length operatorView === 1

-- Registration also created the synchronizer's reporting state (extension reward flow).
states <- query @DedicatedSynchronizerState operator
case states of
[(_cid, st)] -> do
st.synchronizerId === dedicatedSyncId
st.operator === operator
st.totalActivityReported === 0.0
_ -> abort $ "expected exactly one DedicatedSynchronizerState, got " <> show (length states)

-- | Offboard a registered synchronizer via a supermajority vote: the registration is archived,
-- which closes both economic paths (the buy needs the disclosed registration; reward
-- processing requires the live registration - see test_StartProcessing_registrationGate in
-- splice-amulet-test). The reporting state deliberately survives the vote (its contract id
-- changes with every report, so a vote must not pin it); it is inert residue, cleaned up by a
-- separate archive by DSO automation, off the vote's critical path.
test_ArchiveSynchronizerRegistration_viaVote : Script ()
test_ArchiveSynchronizerRegistration_viaVote = do
(app, dso, (sv1, sv2, sv3, sv4)) <- initMainNet
operator <- allocateParty "dedicatedSyncOperator"
let dedicatedSyncId = "dedicated-sync::1220acacacacacacacacacacacacacacacacacacacacacacacacacacacacacac"

initiateAndAcceptVote app [sv1, sv2, sv3, sv4] $
ARC_DsoRules with
dsoAction = SRARC_RegisterSynchronizer DsoRules_RegisterSynchronizer with
synchronizerId = dedicatedSyncId
operator
[(regCid, _)] <- query @RegisteredSynchronizer operator
[(stateCid, _)] <- query @DedicatedSynchronizerState operator

initiateAndAcceptVote app [sv1, sv2, sv3, sv4] $
ARC_DsoRules with
dsoAction = SRARC_ArchiveSynchronizerRegistration DsoRules_ArchiveSynchronizerRegistration with
registeredSynchronizerCid = regCid

-- the registration is gone: nothing to disclose to a buy, nothing to authorize processing
[] <- query @RegisteredSynchronizer operator

-- the state survives and reporting still runs, but the reports are inert: without a live
-- registration they can never be turned into minting (the start-processing gate)
result <- submit operator $ exerciseCmd stateCid DedicatedSynchronizerState_ReportActivity with
round = Round 1
activityRootHash = CryptoHash.hash (BatchOfMintingAllowances [])
totalActivity = 0.0

-- cleanup is a plain archive by DSO automation, retried freely against the current state cid
submit dso $ archiveCmd result.stateCid
[] <- query @DedicatedSynchronizerState operator
pure ()
36 changes: 35 additions & 1 deletion daml/splice-dso-governance/daml/Splice/DsoRules.daml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import Splice.ValidatorLicense
import Splice.Wallet.Subscriptions
-- `RegisteredSynchronizer` (PoC): created by `DsoRules_RegisterSynchronizer` below; the template
-- itself lives in splice-amulet because AmuletRules must be able to fetch it.
import Splice.DecentralizedSynchronizer (MemberTraffic, RegisteredSynchronizer(..))
import Splice.DecentralizedSynchronizer (MemberTraffic, RegisteredSynchronizer(..), DedicatedSynchronizerState(..))

import qualified Splice.CometBft as CometBft
import Splice.Ans
Expand Down Expand Up @@ -132,6 +132,9 @@ data DsoRules_ActionRequiringConfirmation
-- (one run by its own operator) by binding its id to an operator party, so its traffic can
-- be funded in Amulet. Executed via DSO governance; see the `DsoRules_RegisterSynchronizer`
-- choice.
| SRARC_ArchiveSynchronizerRegistration DsoRules_ArchiveSynchronizerRegistration
-- ^ PoC (dedicated-synchronizer traffic): voted action to offboard a registered synchronizer,
-- archiving its registration and reporting state.
deriving (Eq, Show)

data AnsEntryContext_ActionRequiringConfirmation
Expand Down Expand Up @@ -346,6 +349,9 @@ data DsoRules_CreateUnallocatedUnclaimedActivityRecordResult = DsoRules_CreateUn
-- | Result of `DsoRules_RegisterSynchronizer`: the cid of the created registration.
data DsoRules_RegisterSynchronizerResult = DsoRules_RegisterSynchronizerResult with
registeredSynchronizerCid : ContractId RegisteredSynchronizer
dedicatedSynchronizerStateCid : ContractId DedicatedSynchronizerState

data DsoRules_ArchiveSynchronizerRegistrationResult = DsoRules_ArchiveSynchronizerRegistrationResult

data DsoRules_AllocateUnallocatedUnclaimedActivityRecordResult = DsoRules_AllocateUnallocatedUnclaimedActivityRecordResult with
unclaimedActivityRecordCid : ContractId UnclaimedActivityRecord
Expand Down Expand Up @@ -1707,8 +1713,35 @@ template DsoRules with
do
require "synchronizerId is non-empty" (not (T.isEmpty synchronizerId))
registeredSynchronizerCid <- create RegisteredSynchronizer with dso; synchronizerId; operator
-- reporting state for the extension reward flow (see DedicatedSynchronizerState),
-- created at registration so the operator can report from its first round
dedicatedSynchronizerStateCid <- create DedicatedSynchronizerState with
dso
synchronizerId
operator
lastReportedRound = None
totalActivityReported = 0.0
pure $ DsoRules_RegisterSynchronizerResult with ..

nonconsuming choice DsoRules_ArchiveSynchronizerRegistration : DsoRules_ArchiveSynchronizerRegistrationResult
-- ^ PoC (dedicated-synchronizer traffic): governed offboarding of a registered synchronizer
-- by archiving its registration. That closes both economic paths structurally: future
-- purchases are impossible (an archived RegisteredSynchronizer cannot be disclosed to the
-- buy choice) and reward processing is impossible (start-processing requires the live
-- registration). The reporting state is deliberately not archived here: it is inert
-- without the registration, and its contract id changes with every report, so pinning it
-- in a vote's arguments would let the operator invalidate the vote by reporting while the
-- vote is open. Cleaning up the leftover state is a separate archive by DSO automation, safe to
-- retry off the vote's critical path. Records of past purchases (MemberTraffic) and reward
-- processing already authorized for past rounds are untouched: authorized work completes,
-- new work stops.
with
registeredSynchronizerCid : ContractId RegisteredSynchronizer
controller dso
do
void $ fetchAndArchive (ForDso with dso) registeredSynchronizerCid
pure DsoRules_ArchiveSynchronizerRegistrationResult

nonconsuming choice DsoRules_AllocateUnallocatedUnclaimedActivityRecord : DsoRules_AllocateUnallocatedUnclaimedActivityRecordResult
with
unallocatedUnclaimedActivityRecordCid : ContractId UnallocatedUnclaimedActivityRecord
Expand Down Expand Up @@ -1848,6 +1881,7 @@ executeActionRequiringConfirmation dso dsoRulesCid amuletRulesCid act = case act
SRARC_CreateUnallocatedUnclaimedActivityRecord choiceArg -> void $ exercise dsoRulesCid choiceArg
-- PoC: an accepted vote to register a dedicated synchronizer runs the choice on DsoRules.
SRARC_RegisterSynchronizer choiceArg -> void $ exercise dsoRulesCid choiceArg
SRARC_ArchiveSynchronizerRegistration choiceArg -> void $ exercise dsoRulesCid choiceArg
SRARC_CreateBootstrapExternalPartyConfigStateInstruction choiceArg -> void $ exercise dsoRulesCid choiceArg
ARC_AnsEntryContext with .. -> do
void $ fetchChecked (ForDso with dso) ansEntryContextCid
Expand Down
Loading