@@ -252,27 +252,10 @@ impl<T: Config> Pallet<T> {
252252 }
253253 }
254254
255- pub fn drain_pending_emission (
255+ pub fn calculate_dividends_and_incentives (
256256 netuid : u16 ,
257- pending_alpha : u64 ,
258- pending_tao : u64 ,
259- pending_swapped : u64 ,
260- owner_cut : u64 ,
261- ) {
262- log:: debug!(
263- "Draining pending alpha emission for netuid {:?}, pending_alpha: {:?}, pending_tao: {:?}, pending_swapped: {:?}, owner_cut: {:?}" ,
264- netuid,
265- pending_alpha,
266- pending_tao,
267- pending_swapped,
268- owner_cut
269- ) ;
270-
271- // Run the epoch.
272- let hotkey_emission: Vec < ( T :: AccountId , u64 , u64 ) > =
273- Self :: epoch ( netuid, pending_alpha. saturating_add ( pending_swapped) ) ;
274- log:: debug!( "hotkey_emission: {:?}" , hotkey_emission) ;
275-
257+ hotkey_emission : Vec < ( T :: AccountId , u64 , u64 ) > ,
258+ ) -> ( BTreeMap < T :: AccountId , u64 > , BTreeMap < T :: AccountId , I96F32 > ) {
276259 // Accumulate emission of dividends and incentive per hotkey.
277260 let mut incentives: BTreeMap < T :: AccountId , u64 > = BTreeMap :: new ( ) ;
278261 let mut dividends: BTreeMap < T :: AccountId , I96F32 > = BTreeMap :: new ( ) ;
@@ -284,7 +267,7 @@ impl<T: Config> Pallet<T> {
284267 . or_insert ( incentive) ;
285268 // Accumulate dividends to parents.
286269 let div_tuples: Vec < ( T :: AccountId , u64 ) > =
287- Self :: get_dividends_distribution ( & hotkey, netuid, dividend) ;
270+ Self :: get_parent_child_dividends_distribution ( & hotkey, netuid, dividend) ;
288271 // Accumulate dividends per hotkey.
289272 for ( parent, parent_div) in div_tuples {
290273 dividends
@@ -296,64 +279,71 @@ impl<T: Config> Pallet<T> {
296279 log:: debug!( "incentives: {:?}" , incentives) ;
297280 log:: debug!( "dividends: {:?}" , dividends) ;
298281
299- Self :: distribute_dividends_and_incentives (
300- netuid,
301- pending_tao,
302- owner_cut,
303- incentives,
304- dividends,
305- ) ;
282+ ( incentives, dividends)
306283 }
307284
308- pub fn distribute_dividends_and_incentives (
309- netuid : u16 ,
285+ pub fn calculate_dividend_distribution (
286+ pending_alpha : u64 ,
310287 pending_tao : u64 ,
311- owner_cut : u64 ,
312- incentives : BTreeMap < T :: AccountId , u64 > ,
288+ tao_weight : I96F32 ,
289+ stake_map : BTreeMap < T :: AccountId , ( u64 , u64 ) > ,
313290 dividends : BTreeMap < T :: AccountId , I96F32 > ,
291+ ) -> (
292+ BTreeMap < T :: AccountId , I96F32 > ,
293+ BTreeMap < T :: AccountId , I96F32 > ,
314294 ) {
295+ log:: debug!( "dividends: {:?}" , dividends) ;
296+ log:: debug!( "stake_map: {:?}" , stake_map) ;
297+ log:: debug!( "pending_alpha: {:?}" , pending_alpha) ;
298+ log:: debug!( "pending_tao: {:?}" , pending_tao) ;
299+ log:: debug!( "tao_weight: {:?}" , tao_weight) ;
300+
315301 // Setup.
316302 let zero: I96F32 = asfloat ! ( 0.0 ) ;
317303
318304 // Accumulate root divs and alpha_divs. For each hotkey we compute their
319305 // local and root dividend proportion based on their alpha_stake/root_stake
320306 let mut total_root_divs: I96F32 = asfloat ! ( 0 ) ;
307+ let mut total_alpha_divs: I96F32 = asfloat ! ( 0 ) ;
321308 let mut root_dividends: BTreeMap < T :: AccountId , I96F32 > = BTreeMap :: new ( ) ;
322309 let mut alpha_dividends: BTreeMap < T :: AccountId , I96F32 > = BTreeMap :: new ( ) ;
323310 for ( hotkey, dividend) in dividends {
324- // Get hotkey ALPHA on subnet.
325- let alpha_stake = asfloat ! ( Self :: get_stake_for_hotkey_on_subnet( & hotkey, netuid) ) ;
326- // Get hotkey TAO on root.
327- let root_stake: I96F32 = asfloat ! ( Self :: get_stake_for_hotkey_on_subnet(
328- & hotkey,
329- Self :: get_root_netuid( )
330- ) ) ;
331- // Convert TAO to alpha with weight.
332- let root_alpha: I96F32 = root_stake. saturating_mul ( Self :: get_tao_weight ( ) ) ;
333- // Get total from root and local
334- let total_alpha: I96F32 = alpha_stake. saturating_add ( root_alpha) ;
335- // Copmute root prop.
336- let root_prop: I96F32 = root_alpha. checked_div ( total_alpha) . unwrap_or ( zero) ;
337- // Compute root dividends
338- let root_divs: I96F32 = dividend. saturating_mul ( root_prop) ;
339- // Compute alpha dividends
340- let alpha_divs: I96F32 = dividend. saturating_sub ( root_divs) ;
341- // Record the alpha dividends.
342- alpha_dividends
343- . entry ( hotkey. clone ( ) )
344- . and_modify ( |e| * e = e. saturating_add ( alpha_divs) )
345- . or_insert ( alpha_divs) ;
346- // Record the root dividends.
347- root_dividends
348- . entry ( hotkey. clone ( ) )
349- . and_modify ( |e| * e = e. saturating_add ( root_divs) )
350- . or_insert ( root_divs) ;
351- // Accumulate total root divs.
352- total_root_divs = total_root_divs. saturating_add ( root_divs) ;
311+ if let Some ( ( alpha_stake_u64, root_stake_u64) ) = stake_map. get ( & hotkey) {
312+ // Get hotkey ALPHA on subnet.
313+ let alpha_stake: I96F32 = asfloat ! ( * alpha_stake_u64) ;
314+ // Get hotkey TAO on root.
315+ let root_stake: I96F32 = asfloat ! ( * root_stake_u64) ;
316+
317+ // Convert TAO to alpha with weight.
318+ let root_alpha: I96F32 = root_stake. saturating_mul ( tao_weight) ;
319+ // Get total from root and local
320+ let total_alpha: I96F32 = alpha_stake. saturating_add ( root_alpha) ;
321+ // Compute root prop.
322+ let root_prop: I96F32 = root_alpha. checked_div ( total_alpha) . unwrap_or ( zero) ;
323+ // Compute root dividends
324+ let root_divs: I96F32 = dividend. saturating_mul ( root_prop) ;
325+ // Compute alpha dividends
326+ let alpha_divs: I96F32 = dividend. saturating_sub ( root_divs) ;
327+ // Record the alpha dividends.
328+ alpha_dividends
329+ . entry ( hotkey. clone ( ) )
330+ . and_modify ( |e| * e = e. saturating_add ( alpha_divs) )
331+ . or_insert ( alpha_divs) ;
332+ // Accumulate total alpha divs.
333+ total_alpha_divs = total_alpha_divs. saturating_add ( alpha_divs) ;
334+ // Record the root dividends.
335+ root_dividends
336+ . entry ( hotkey. clone ( ) )
337+ . and_modify ( |e| * e = e. saturating_add ( root_divs) )
338+ . or_insert ( root_divs) ;
339+ // Accumulate total root divs.
340+ total_root_divs = total_root_divs. saturating_add ( root_divs) ;
341+ }
353342 }
354343 log:: debug!( "alpha_dividends: {:?}" , alpha_dividends) ;
355344 log:: debug!( "root_dividends: {:?}" , root_dividends) ;
356345 log:: debug!( "total_root_divs: {:?}" , total_root_divs) ;
346+ log:: debug!( "total_alpha_divs: {:?}" , total_alpha_divs) ;
357347
358348 // Compute root divs as TAO. Here we take
359349 let mut tao_dividends: BTreeMap < T :: AccountId , I96F32 > = BTreeMap :: new ( ) ;
@@ -372,6 +362,34 @@ impl<T: Config> Pallet<T> {
372362 }
373363 log:: debug!( "tao_dividends: {:?}" , tao_dividends) ;
374364
365+ // Compute proportional alpha divs using the pending alpha and total alpha divs from the epoch.
366+ let mut prop_alpha_dividends: BTreeMap < T :: AccountId , I96F32 > = BTreeMap :: new ( ) ;
367+ for ( hotkey, alpha_divs) in alpha_dividends {
368+ // Alpha proportion.
369+ let alpha_share: I96F32 = alpha_divs. checked_div ( total_alpha_divs) . unwrap_or ( zero) ;
370+ log:: debug!( "hotkey: {:?}, alpha_share: {:?}" , hotkey, alpha_share) ;
371+
372+ // Compute the proportional pending_alpha to this hotkey.
373+ let prop_alpha: I96F32 = asfloat ! ( pending_alpha) . saturating_mul ( alpha_share) ;
374+ log:: debug!( "hotkey: {:?}, prop_alpha: {:?}" , hotkey, prop_alpha) ;
375+ // Record the proportional alpha dividends.
376+ prop_alpha_dividends
377+ . entry ( hotkey. clone ( ) )
378+ . and_modify ( |e| * e = prop_alpha)
379+ . or_insert ( prop_alpha) ;
380+ }
381+ log:: debug!( "prop_alpha_dividends: {:?}" , prop_alpha_dividends) ;
382+
383+ ( prop_alpha_dividends, tao_dividends)
384+ }
385+
386+ pub fn distribute_dividends_and_incentives (
387+ netuid : u16 ,
388+ owner_cut : u64 ,
389+ incentives : BTreeMap < T :: AccountId , u64 > ,
390+ alpha_dividends : BTreeMap < T :: AccountId , I96F32 > ,
391+ tao_dividends : BTreeMap < T :: AccountId , I96F32 > ,
392+ ) {
375393 // Distribute the owner cut.
376394 if let Ok ( owner_coldkey) = SubnetOwner :: < T > :: try_get ( netuid) {
377395 if let Ok ( owner_hotkey) = SubnetOwnerHotkey :: < T > :: try_get ( netuid) {
@@ -468,6 +486,114 @@ impl<T: Config> Pallet<T> {
468486 }
469487 }
470488
489+ pub fn get_stake_map (
490+ netuid : u16 ,
491+ hotkeys : Vec < & T :: AccountId > ,
492+ ) -> BTreeMap < T :: AccountId , ( u64 , u64 ) > {
493+ let mut stake_map: BTreeMap < T :: AccountId , ( u64 , u64 ) > = BTreeMap :: new ( ) ;
494+ for hotkey in hotkeys {
495+ // Get hotkey ALPHA on subnet.
496+ let alpha_stake: u64 = Self :: get_stake_for_hotkey_on_subnet ( hotkey, netuid) ;
497+ // Get hotkey TAO on root.
498+ let root_stake: u64 =
499+ Self :: get_stake_for_hotkey_on_subnet ( hotkey, Self :: get_root_netuid ( ) ) ;
500+ stake_map. insert ( hotkey. clone ( ) , ( alpha_stake, root_stake) ) ;
501+ }
502+ stake_map
503+ }
504+
505+ pub fn calculate_dividend_and_incentive_distribution (
506+ netuid : u16 ,
507+ pending_tao : u64 ,
508+ pending_validator_alpha : u64 ,
509+ hotkey_emission : Vec < ( T :: AccountId , u64 , u64 ) > ,
510+ tao_weight : I96F32 ,
511+ ) -> (
512+ BTreeMap < T :: AccountId , u64 > ,
513+ (
514+ BTreeMap < T :: AccountId , I96F32 > ,
515+ BTreeMap < T :: AccountId , I96F32 > ,
516+ ) ,
517+ ) {
518+ let ( incentives, dividends) =
519+ Self :: calculate_dividends_and_incentives ( netuid, hotkey_emission) ;
520+
521+ let stake_map: BTreeMap < T :: AccountId , ( u64 , u64 ) > =
522+ Self :: get_stake_map ( netuid, dividends. keys ( ) . collect :: < Vec < _ > > ( ) ) ;
523+
524+ let ( alpha_dividends, tao_dividends) = Self :: calculate_dividend_distribution (
525+ pending_validator_alpha,
526+ pending_tao,
527+ tao_weight,
528+ stake_map,
529+ dividends,
530+ ) ;
531+
532+ ( incentives, ( alpha_dividends, tao_dividends) )
533+ }
534+
535+ pub fn drain_pending_emission (
536+ netuid : u16 ,
537+ pending_alpha : u64 ,
538+ pending_tao : u64 ,
539+ pending_swapped : u64 ,
540+ owner_cut : u64 ,
541+ ) {
542+ log:: debug!(
543+ "Draining pending alpha emission for netuid {:?}, pending_alpha: {:?}, pending_tao: {:?}, pending_swapped: {:?}, owner_cut: {:?}" ,
544+ netuid,
545+ pending_alpha,
546+ pending_tao,
547+ pending_swapped,
548+ owner_cut
549+ ) ;
550+
551+ let tao_weight = Self :: get_tao_weight ( ) ;
552+
553+ // Run the epoch.
554+ let hotkey_emission: Vec < ( T :: AccountId , u64 , u64 ) > =
555+ Self :: epoch ( netuid, pending_alpha. saturating_add ( pending_swapped) ) ;
556+ log:: debug!( "hotkey_emission: {:?}" , hotkey_emission) ;
557+
558+ // Compute the pending validator alpha.
559+ // This is the total alpha being injected,
560+ // minus the the alpha for the miners, (50%)
561+ // and minus the alpha swapped for TAO (pending_swapped).
562+ // Important! If the incentives are 0, then Validators get 100% of the alpha.
563+ let incentive_sum = hotkey_emission
564+ . iter ( )
565+ . map ( |( _, incentive, _) | incentive)
566+ . sum :: < u64 > ( ) ;
567+ log:: debug!( "incentive_sum: {:?}" , incentive_sum) ;
568+
569+ let pending_validator_alpha: u64 = if incentive_sum != 0 {
570+ pending_alpha
571+ . saturating_add ( pending_swapped)
572+ . saturating_div ( 2 )
573+ . saturating_sub ( pending_swapped)
574+ } else {
575+ // If the incentive is 0, then Validators get 100% of the alpha.
576+ pending_alpha
577+ } ;
578+
579+ let ( incentives, ( alpha_dividends, tao_dividends) ) =
580+ Self :: calculate_dividend_and_incentive_distribution (
581+ netuid,
582+ pending_tao,
583+ pending_validator_alpha,
584+ hotkey_emission,
585+ tao_weight,
586+ ) ;
587+
588+ Self :: distribute_dividends_and_incentives (
589+ netuid,
590+ owner_cut,
591+ incentives,
592+ alpha_dividends,
593+ tao_dividends,
594+ ) ;
595+ }
596+
471597 /// Returns the self contribution of a hotkey on a subnet.
472598 /// This is the portion of the hotkey's stake that is provided by itself, and not delegated to other hotkeys.
473599 pub fn get_self_contribution ( hotkey : & T :: AccountId , netuid : u16 ) -> u64 {
@@ -516,7 +642,7 @@ impl<T: Config> Pallet<T> {
516642 /// # Returns
517643 /// * dividend_tuples: `Vec<(T::AccountId, u64)>` - Vector of (hotkey, divs) for each parent including self.
518644 ///
519- pub fn get_dividends_distribution (
645+ pub fn get_parent_child_dividends_distribution (
520646 hotkey : & T :: AccountId ,
521647 netuid : u16 ,
522648 dividends : u64 ,
0 commit comments