Skip to content

[DRAFT] SV weight management fully on-ledger#5567

Draft
jose-velasco-ieu wants to merge 7 commits into
mainfrom
josevelasco/sv-weights
Draft

[DRAFT] SV weight management fully on-ledger#5567
jose-velasco-ieu wants to merge 7 commits into
mainfrom
josevelasco/sv-weights

Conversation

@jose-velasco-ieu
Copy link
Copy Markdown
Contributor

@jose-velasco-ieu jose-velasco-ieu commented May 15, 2026

Summary

This PR adds a Daml draft for the new on-ledger SV weight model. The goal is to represent SV weights fully on-ledger, including SV beneficiary weights.

Main changes:

  • Adds HostedSvInfo and the hostedSvs / offboardedHostedSvs fields to the DsoRules template to represent SV reward weights separately from legacy SV node/operator state.
  • Keeps SvInfo for SV node/operator information, but marks joinedAsOfRound and svRewardWeight as deprecated in favor of HostedSvInfo.
  • Adds governed choices for hosted SV lifecycle management: DsoRules_AddHostedSv to add hosted SVs, DsoRules_UpdateHostedSvRewardWeight to update hosted SV weights, and DsoRules_OffboardHostedSv to offboard hosted SVs.
  • Adds DsoRules_AddSvNode, which replaces DsoRules_AddSv for adding SV nodes. Unlike DsoRules_AddSv, it does not take newSvRewardWeight or joinedAsOfRound, since SV nodes no longer have reward weight attached in the new model.
  • Adds the SvRewardBeneficiaries template to optionally configure on-ledger beneficiary splits for an SV’s rewards.
  • Adds DsoRules_SetSvRewardBeneficiaries to create, update, or clear beneficiary distributions.
  • Adds a temporary convenience choice, DsoRules_MigrateHostedSvs, to migrate an SV operator’s legacy reward weight into hosted SV entries.
  • Adds DsoRules_ReceiveSvRewardCoupon_V2, which creates reward coupons for all SVs operated by an SV operator using hosted SV weights and optional beneficiary splits.
  • Deprecates the legacy SV reward weight flow, including DsoRules_UpdateSvRewardWeight and DsoRules_ReceiveSvRewardCoupon, once all SVs have migrated to hostedSvs.
  • Marks the existing SV onboarding flow as deprecated, as it still creates legacy SV node entries with reward-weight semantics.
  • Adds a Daml Script test covering migration, beneficiary setup/update/removal, V2 reward coupon creation, hosted SV migration between operators, and SV node onboarding/offboarding.

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 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).

Signed-off-by: Jose Velasco <jose.velasco@intellecteu.com>
Comment thread daml/splice-dso-governance/daml/Splice/DsoRules.daml Outdated
choice DsoRules_AddSvOperator : DsoRules_AddSvOperatorResult
with
newSvParty : Party
-- DRAFT note for the reviewer: In the future, newSvName should not be used, since an SV operator may operate multiple SVs.
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.

I would suggest making this choice
AddSvNode, not AddSvOperator, and if a single operator operates multiple nodes, then it is just listed as the operator on each of them.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ok

On the other hand:

  • What do you think about my comment on newSvName : Text ?
  • What about newSvParty : Party ? Actually it is an SV operato even though we insert it in the svs Map,

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.

I think we will still need a name for sv nodes, at least for onboarding, so probably need a newSvNodeName.

we insert it in the svs Map

Yeah, that's an ugliness we'll probably need to carry with us as we cannot rename that map. Ideally, I'd rename it to svNodes, but that's an incompatible daml change.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I would suggest making this choice AddSvNode, not AddSvOperator, and if a single operator operates multiple nodes, then it is just listed as the operator on each of them.

I'm afraid the current model cannot support a single SV operator party operating multiple nodes, because SV operators are used as keys in the map.

svs : Map.Map Party SvInfo

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.

I think that actually makes sense to forbid.
The operator party is an internal party in the node itself, so clearly they should be unique per node.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

-- which is not a requirement in the current proposal.
newSvName : Text
newSvParticipantId : Text
joinedAsOfRound : Round
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.

I don't think we need this, this was typically to track rewards. If rewards are no longer associated with the node, we don't need it in the node contract

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Currently, joinedAsOfRound is part of SvRewardState, which ensures that SV rewards are created only once per round.

-- check and update state
rewardState <- fetchAndArchive (ForSv with dso; svName = info.name) rewardStateCid
let state = rewardState.state
require
  ("Round " <> show openRound.round <> " is greater than the last round a reward has been received for " <> show state.lastRoundCollected)
  (state.lastRoundCollected < openRound.round)
 

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.

Right, but this is for adding a node, so no weights associated with it.
Or do we need it initially during the migration period?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'm not referring to the migration period.

My point is that the SV operator exercising the new DsoRules_ReceiveSvRewardCoupon_V2 still needs to provide its SvRewardState contract, which contains lastRoundCollected, as we do today, to ensure that SV rewards are created only once per round.

Therefore, I think we still need joinedAsOfRound to create the initial RewardState for the SV operator. Maybe I’m missing something.

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.

But won't you have different joinedAsOfRound for every (weighted) SV?
I think this should be part of sv onboarding, not part of the node onboarding.

Either way, next step should be some daml tests. These usually flesh out the details of the different usage scenarios, and help envision much better what the end result would look like. We should have our answers on this once we see those.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ok, I wasn't aware that we needed a new onboarding flow for adding new SVs. I thought SV onboarding would only require creating the corresponding on-ledger weight.

How should that flow work?

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, sorry, that's what I meant by onboarding. Either way, when the SV got added in, that's the minimum round for when they should get rewards. Not when the node was onboarded.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ok, I will work on that.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

newDsoRules <- create this with svs = newSvs
return DsoRules_UpdateSvRewardWeightResult with ..

choice DsoRules_UpdateSvRewardWeight_V2 : DsoRules_UpdateSvRewardWeight_V2Result
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.

I think you meant for this to be nonconsuming
(but see my comment below)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

weight = newRewardWeight
pure DsoRules_UpdateSvRewardWeight_V2Result with svWeightCid

nonconsuming choice DsoRules_AddSvRewardWeight : DsoRules_AddSvRewardWeightResult
Copy link
Copy Markdown
Contributor

@isegall-da isegall-da May 15, 2026

Choose a reason for hiding this comment

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

Given that the long term direction is for votes to be associated with weights, I think the weights should be part of dsoRules, similarly to how nodes are (or how SVs are today) rather than just standalone contracts between operator&sv.

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.

But I must admit that I'm not 100% clear on the tradeoffs around this design choice. What's the downside of doing what I proposed? More churn on dsoRules? (which I think is fine, as weights won't change very often)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It sounds good. I wouldn't expect many weights changes.
In that case, I should get rid of the template SvWeight, right?

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, if we manage it on dsoRules then I don't think we need SvWeight at all.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ok, I will refactor this model accordingly

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done

jose-velasco-ieu and others added 6 commits May 15, 2026 17:02
Co-authored-by: Itai Segall <itai.segall@digitalasset.com>
Signed-off-by: Jose Velasco <jose.velasco@intellecteu.com>
Signed-off-by: Jose Velasco <jose.velasco@intellecteu.com>
Signed-off-by: Jose Velasco <jose.velasco@intellecteu.com>
Signed-off-by: Jose Velasco <jose.velasco@intellecteu.com>
Signed-off-by: Jose Velasco <jose.velasco@intellecteu.com>
Signed-off-by: Jose Velasco <jose.velasco@intellecteu.com>
@jose-velasco-ieu
Copy link
Copy Markdown
Contributor Author

@isegall-da
I've added a Daml test covering the happy path scenario

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.

2 participants