Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

delegation_manager.gno

5.25 Kb · 151 lines
  1package staker
  2
  3import (
  4	bptree "gno.land/p/nt/bptree/v0"
  5)
  6
  7// DelegationManager manages the mapping between users and their delegation IDs.
  8// It provides efficient lookup and management of user delegations organized by delegator and delegatee addresses.
  9type DelegationManager struct {
 10	// userDelegations maps delegator address -> *bptree.BPTree (delegatee address -> list of delegation IDs)
 11	// Using BPTree instead of map to handle unbounded growth of delegators efficiently
 12	userDelegations *bptree.BPTree
 13}
 14
 15// NewDelegationManager creates a new instance of DelegationManager.
 16// This factory function initializes the BPTree structure for tracking user delegations.
 17//
 18// Returns:
 19//   - *DelegationManager: manager ready to track delegator/delegatee ID lists.
 20func NewDelegationManager() *DelegationManager {
 21	return &DelegationManager{
 22		userDelegations: bptree.NewBPTreeN(16),
 23	}
 24}
 25
 26// GetUserDelegations returns the entire user delegations tree.
 27//
 28// Returns:
 29//   - *bptree.BPTree: tree keyed by delegator address string.
 30func (dm *DelegationManager) GetUserDelegations() *bptree.BPTree {
 31	return dm.userDelegations
 32}
 33
 34// SetUserDelegations replaces the root delegator-to-delegations tree.
 35//
 36// Parameters:
 37//   - userDelegations: tree keyed by delegator address string and containing delegatee trees.
 38func (dm *DelegationManager) SetUserDelegations(userDelegations *bptree.BPTree) {
 39	dm.userDelegations = userDelegations
 40}
 41
 42// GetDelegatorDelegations returns the delegatee tree for one delegator.
 43//
 44// Parameters:
 45//   - delegator: delegator address string used as the root-tree key.
 46//
 47// Returns:
 48//   - *bptree.BPTree: delegatee-to-delegation-ID tree when present and correctly typed.
 49//   - bool: true when the delegator entry exists with the expected tree type.
 50func (dm *DelegationManager) GetDelegatorDelegations(delegator string) (*bptree.BPTree, bool) {
 51	delegations := dm.userDelegations.Get(delegator)
 52	if delegations == nil {
 53		return nil, false
 54	}
 55	delegationsTree, ok := delegations.(*bptree.BPTree)
 56	if !ok {
 57		return nil, false
 58	}
 59	return delegationsTree, true
 60}
 61
 62// GetDelegationIDs returns IDs recorded for one delegator/delegatee pair.
 63//
 64// Parameters:
 65//   - delegator: delegator address string used to select the nested tree.
 66//   - delegatee: delegatee address string used as the nested-tree key.
 67//
 68// Returns:
 69//   - []int64: delegation IDs stored for the pair.
 70//   - bool: true when the pair exists with a valid ID slice.
 71func (dm *DelegationManager) GetDelegationIDs(delegator, delegatee string) ([]int64, bool) {
 72	delegations, exists := dm.GetDelegatorDelegations(delegator)
 73	if !exists {
 74		return nil, false
 75	}
 76	ids := delegations.Get(delegatee)
 77	if ids == nil {
 78		return nil, false
 79	}
 80	idsSlice, ok := ids.([]int64)
 81	if !ok {
 82		return nil, false
 83	}
 84	return idsSlice, true
 85}
 86
 87// SetDelegationIDs stores the complete ID slice for a delegator/delegatee pair.
 88// A missing delegator entry is initialized with a new nested tree.
 89//
 90// Parameters:
 91//   - delegator: delegator address string used to select or create the nested tree.
 92//   - delegatee: delegatee address string used as the nested-tree key.
 93//   - ids: delegation IDs to store for the pair.
 94func (dm *DelegationManager) SetDelegationIDs(delegator, delegatee string, ids []int64) {
 95	delegations, exists := dm.GetDelegatorDelegations(delegator)
 96	if !exists {
 97		delegations = NewDelegationTree()
 98		dm.userDelegations.Set(delegator, delegations)
 99	}
100	delegations.Set(delegatee, ids)
101}
102
103// AddDelegationID appends a delegation ID to the delegator-delegatee pair,
104// skipping duplicates. The whole get-modify-set runs inside this domain method
105// so the nested BPTree mutation never escapes the owning realm. Performing the
106// lookup in one realm and the write in another (e.g. re-fetching the inner tree
107// across a realm boundary and mutating it) would hit the cross-realm write
108// guard for the persisted leaf slot.
109//
110// Parameters:
111//   - delegator: delegator address string used to select the nested tree.
112//   - delegatee: delegatee address string used as the nested-tree key.
113//   - delegationID: delegation ID to append when it is not already present.
114func (dm *DelegationManager) AddDelegationID(delegator, delegatee string, delegationID int64) {
115	ids, _ := dm.GetDelegationIDs(delegator, delegatee)
116	for _, id := range ids {
117		if id == delegationID {
118			return
119		}
120	}
121	ids = append(ids, delegationID)
122	dm.SetDelegationIDs(delegator, delegatee, ids)
123}
124
125// RemoveDelegationID removes a delegation ID from the delegator-delegatee pair.
126// Like AddDelegationID, the read-modify-write is kept inside this domain method.
127// RemoveDelegationID removes one ID from a delegator/delegatee pair.
128// Missing pairs and IDs are left unchanged.
129//
130// Parameters:
131//   - delegator: delegator address string used to select the nested tree.
132//   - delegatee: delegatee address string used as the nested-tree key.
133//   - delegationID: delegation ID to remove when it is present.
134func (dm *DelegationManager) RemoveDelegationID(delegator, delegatee string, delegationID int64) {
135	ids, exists := dm.GetDelegationIDs(delegator, delegatee)
136	if !exists {
137		return
138	}
139	index := -1
140	for i, id := range ids {
141		if id == delegationID {
142			index = i
143			break
144		}
145	}
146	if index == -1 {
147		return
148	}
149	ids = append(ids[:index], ids[index+1:]...)
150	dm.SetDelegationIDs(delegator, delegatee, ids)
151}