Skip to content

Commit 5b70ab2

Browse files
committed
Merge branch 'devnet-ready' into feat/solidity-get-stake
2 parents 0b30f3b + a6bd117 commit 5b70ab2

File tree

5 files changed

+387
-300
lines changed

5 files changed

+387
-300
lines changed

.github/workflows/e2e-bittensor-tests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ jobs:
7070
python3 -m pip install -e .
7171
python3 -m pip install torch
7272
python3 -m pip install pytest
73+
python3 -m pip install -r requirements/dev.txt
7374
7475
- name: Run tests
7576
working-directory: ${{ github.workspace }}/bittensor

pallets/subtensor/src/coinbase/run_coinbase.rs

Lines changed: 144 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -247,32 +247,20 @@ impl<T: Config> Pallet<T> {
247247
alpha_out
248248
);
249249

250-
// 6.1 Distribute the 18% owner cut.
250+
// Calculate the 18% owner cut.
251251
let owner_cut: u64 = I96F32::from_num(alpha_out)
252252
.saturating_mul(Self::get_float_subnet_owner_cut())
253253
.to_num::<u64>();
254254
log::debug!("Owner cut for netuid {:?}: {:?}", netuid, owner_cut);
255-
// 6.1.1: Check for existence of owner cold/hot pair and distribute emission directly to them.
256-
if let Ok(owner_coldkey) = SubnetOwner::<T>::try_get(netuid) {
257-
if let Ok(owner_hotkey) = SubnetOwnerHotkey::<T>::try_get(netuid) {
258-
// Increase stake for both coldkey and hotkey on the subnet
259-
Self::increase_stake_for_hotkey_and_coldkey_on_subnet(
260-
&owner_hotkey,
261-
&owner_coldkey,
262-
netuid,
263-
owner_cut,
264-
);
265-
log::debug!("Distributed owner cut for netuid {:?} to owner_hotkey {:?} and owner_coldkey {:?}", netuid, owner_hotkey, owner_coldkey);
266-
}
267-
}
255+
268256
let remaining_emission: u64 = alpha_out.saturating_sub(owner_cut);
269257
log::debug!(
270258
"Remaining emission for netuid {:?}: {:?}",
271259
netuid,
272260
remaining_emission
273261
);
274262

275-
// 6.2 Run the epoch() --> hotkey emission.
263+
// Run the epoch() --> hotkey emission.
276264
let hotkey_emission: Vec<(T::AccountId, u64, u64)> =
277265
Self::epoch(netuid, remaining_emission);
278266
log::debug!(
@@ -281,11 +269,15 @@ impl<T: Config> Pallet<T> {
281269
hotkey_emission
282270
);
283271

284-
// 6.3 Pay out the hotkey alpha dividends.
272+
// Pay out the hotkey alpha dividends.
285273
// First clear the netuid from HotkeyDividends
286274
let mut total_root_alpha_divs: u64 = 0;
287275
let mut root_alpha_divs: BTreeMap<T::AccountId, u64> = BTreeMap::new();
288276
let _ = AlphaDividendsPerSubnet::<T>::clear_prefix(netuid, u32::MAX, None);
277+
278+
let mut dividends_to_distribute: Vec<(T::AccountId, Vec<(T::AccountId, u64)>)> = Vec::new();
279+
let mut mining_incentive_to_distribute: Vec<(T::AccountId, u64)> = Vec::new();
280+
289281
for (hotkey, incentive, dividends) in hotkey_emission {
290282
log::debug!(
291283
"Processing hotkey {:?} with incentive {:?} and dividends {:?}",
@@ -294,21 +286,10 @@ impl<T: Config> Pallet<T> {
294286
dividends
295287
);
296288

297-
// 6.3.1: Distribute mining incentive immediately.
298-
Self::increase_stake_for_hotkey_and_coldkey_on_subnet(
299-
&hotkey.clone(),
300-
&Owner::<T>::get(hotkey.clone()),
301-
netuid,
302-
incentive,
303-
);
304-
log::debug!(
305-
"Distributed mining incentive for hotkey {:?} on netuid {:?}: {:?}",
306-
hotkey,
307-
netuid,
308-
incentive
309-
);
289+
// Record mining incentive
290+
mining_incentive_to_distribute.push((hotkey.clone(), incentive));
310291

311-
// 6.3.2: Get dividend tuples for parents and self based on childkey relationships and child-take.
292+
// Get dividend tuples for parents and self based on childkey relationships and child-take.
312293
let dividend_tuples: Vec<(T::AccountId, u64)> =
313294
Self::get_dividends_distribution(&hotkey, netuid, dividends);
314295
log::debug!(
@@ -318,74 +299,66 @@ impl<T: Config> Pallet<T> {
318299
dividend_tuples
319300
);
320301

321-
// 6.3.3 Pay out dividends to hotkeys based on the local vs root proportion.
322-
for (hotkey_j, divs_j) in dividend_tuples {
302+
// Record dividends to distribute
303+
dividends_to_distribute.push((hotkey.clone(), dividend_tuples));
304+
}
305+
306+
// Calculate the validator take and root alpha divs using the alpha divs.
307+
for (hotkey, dividend_tuples) in dividends_to_distribute.iter() {
308+
// Get the local alpha and root alpha.
309+
let hotkey_tao: I96F32 = I96F32::from_num(Self::get_stake_for_hotkey_on_subnet(
310+
hotkey,
311+
Self::get_root_netuid(),
312+
));
313+
let hotkey_tao_as_alpha: I96F32 = hotkey_tao.saturating_mul(Self::get_tao_weight());
314+
let hotkey_alpha =
315+
I96F32::from_num(Self::get_stake_for_hotkey_on_subnet(hotkey, netuid));
316+
log::debug!("Hotkey tao for hotkey {:?} on root netuid: {:?}, hotkey tao as alpha: {:?}, hotkey alpha: {:?}", hotkey, hotkey_tao, hotkey_tao_as_alpha, hotkey_alpha);
317+
318+
// Compute alpha and root proportions.
319+
let alpha_prop: I96F32 = hotkey_alpha
320+
.checked_div(hotkey_alpha.saturating_add(hotkey_tao_as_alpha))
321+
.unwrap_or(I96F32::from_num(0.0));
322+
let root_prop: I96F32 = hotkey_tao_as_alpha
323+
.checked_div(hotkey_alpha.saturating_add(hotkey_tao_as_alpha))
324+
.unwrap_or(I96F32::from_num(0.0));
325+
log::debug!(
326+
"Alpha proportion: {:?}, root proportion: {:?}",
327+
alpha_prop,
328+
root_prop
329+
);
330+
331+
// Calculate the dividends to hotkeys based on the local vs root proportion.
332+
for (hotkey_j, divs_j) in dividend_tuples.iter() {
323333
log::debug!(
324334
"Processing dividend for hotkey {:?} to hotkey {:?}: {:?}",
325335
hotkey,
326336
hotkey_j,
327-
divs_j
337+
*divs_j
328338
);
329339

330-
// 6.3.3.1: Remove the hotkey take straight off the top.
331-
let take_prop: I96F32 = I96F32::from_num(Self::get_hotkey_take(&hotkey_j))
340+
// Remove the hotkey take straight off the top.
341+
let take_prop: I96F32 = I96F32::from_num(Self::get_hotkey_take(hotkey_j))
332342
.checked_div(I96F32::from_num(u16::MAX))
333343
.unwrap_or(I96F32::from_num(0.0));
334-
let validator_take: I96F32 = take_prop.saturating_mul(I96F32::from_num(divs_j));
335-
let rem_divs_j: I96F32 = I96F32::from_num(divs_j).saturating_sub(validator_take);
344+
let validator_take: I96F32 = take_prop.saturating_mul(I96F32::from_num(*divs_j));
345+
let rem_divs_j: I96F32 = I96F32::from_num(*divs_j).saturating_sub(validator_take);
336346
log::debug!(
337347
"Validator take for hotkey {:?}: {:?}, remaining dividends: {:?}",
338348
hotkey_j,
339349
validator_take,
340350
rem_divs_j
341351
);
342352

343-
// 6.3.3.2: Distribute validator take automatically.
344-
Self::increase_stake_for_hotkey_and_coldkey_on_subnet(
345-
&hotkey_j,
346-
&Owner::<T>::get(hotkey_j.clone()),
347-
netuid,
348-
validator_take.to_num::<u64>(),
349-
);
350-
log::debug!(
351-
"Distributed validator take for hotkey {:?} on netuid {:?}: {:?}",
352-
hotkey_j,
353-
netuid,
354-
validator_take.to_num::<u64>()
355-
);
356-
357-
// 6.3.3.3: Get the local alpha and root alpha.
358-
let hotkey_tao: I96F32 = I96F32::from_num(Self::get_stake_for_hotkey_on_subnet(
359-
&hotkey,
360-
Self::get_root_netuid(),
361-
));
362-
let hotkey_tao_as_alpha: I96F32 = hotkey_tao.saturating_mul(Self::get_tao_weight());
363-
let hotkey_alpha =
364-
I96F32::from_num(Self::get_stake_for_hotkey_on_subnet(&hotkey, netuid));
365-
log::debug!("Hotkey tao for hotkey {:?} on root netuid: {:?}, hotkey tao as alpha: {:?}, hotkey alpha: {:?}", hotkey, hotkey_tao, hotkey_tao_as_alpha, hotkey_alpha);
366-
367-
// 6.3.3.4 Compute alpha and root proportions.
368-
let alpha_prop: I96F32 = hotkey_alpha
369-
.checked_div(hotkey_alpha.saturating_add(hotkey_tao_as_alpha))
370-
.unwrap_or(I96F32::from_num(0.0));
371-
let root_prop: I96F32 = hotkey_tao_as_alpha
372-
.checked_div(hotkey_alpha.saturating_add(hotkey_tao_as_alpha))
373-
.unwrap_or(I96F32::from_num(0.0));
374-
log::debug!(
375-
"Alpha proportion: {:?}, root proportion: {:?}",
376-
alpha_prop,
377-
root_prop
378-
);
379-
380-
// 6.3.3.5: Compute alpha and root dividends
353+
// Compute root dividends
381354
let root_divs: I96F32 = rem_divs_j.saturating_mul(root_prop);
382355
log::debug!(
383356
"Alpha dividends: {:?}, root dividends: {:?}",
384357
rem_divs_j,
385358
root_divs
386359
);
387360

388-
// 6.3.3.6. Store the root alpha divs under hotkey_j
361+
// Store the root-alpha divs under hotkey_j
389362
root_alpha_divs
390363
.entry(hotkey_j.clone())
391364
.and_modify(|e| *e = e.saturating_add(root_divs.to_num::<u64>()))
@@ -397,10 +370,74 @@ impl<T: Config> Pallet<T> {
397370
hotkey_j,
398371
root_divs.to_num::<u64>()
399372
);
373+
}
374+
}
375+
376+
// Check for existence of owner cold/hot pair and distribute emission directly to them.
377+
if let Ok(owner_coldkey) = SubnetOwner::<T>::try_get(netuid) {
378+
if let Ok(owner_hotkey) = SubnetOwnerHotkey::<T>::try_get(netuid) {
379+
// Increase stake for both coldkey and hotkey on the subnet
380+
Self::increase_stake_for_hotkey_and_coldkey_on_subnet(
381+
&owner_hotkey,
382+
&owner_coldkey,
383+
netuid,
384+
owner_cut,
385+
);
386+
log::debug!("Distributed owner cut for netuid {:?} to owner_hotkey {:?} and owner_coldkey {:?}", netuid, owner_hotkey, owner_coldkey);
387+
}
388+
}
400389

401-
// 6.3.3.7: Distribute the alpha divs to the hotkey.
390+
// Distribute mining incentive.
391+
for (hotkey, incentive) in mining_incentive_to_distribute {
392+
// Distribute mining incentive immediately.
393+
Self::increase_stake_for_hotkey_and_coldkey_on_subnet(
394+
&hotkey.clone(),
395+
&Owner::<T>::get(hotkey.clone()),
396+
netuid,
397+
incentive,
398+
);
399+
log::debug!(
400+
"Distributed mining incentive for hotkey {:?} on netuid {:?}: {:?}",
401+
hotkey,
402+
netuid,
403+
incentive
404+
);
405+
}
406+
407+
// Distribute validator take and alpha-dividends.
408+
for (_hotkey, dividend_tuples) in dividends_to_distribute.iter() {
409+
// Pay out dividends to hotkeys based on the local vs root proportion.
410+
for (hotkey_j, divs_j) in dividend_tuples.iter() {
411+
// Remove the hotkey take straight off the top.
412+
let take_prop: I96F32 = I96F32::from_num(Self::get_hotkey_take(hotkey_j))
413+
.checked_div(I96F32::from_num(u16::MAX))
414+
.unwrap_or(I96F32::from_num(0.0));
415+
let validator_take: I96F32 = take_prop.saturating_mul(I96F32::from_num(*divs_j));
416+
let rem_divs_j: I96F32 = I96F32::from_num(*divs_j).saturating_sub(validator_take);
417+
log::debug!(
418+
"Validator take for hotkey {:?}: {:?}, remaining dividends: {:?}",
419+
hotkey_j,
420+
validator_take,
421+
rem_divs_j
422+
);
423+
424+
// Distribute validator take.
425+
Self::increase_stake_for_hotkey_and_coldkey_on_subnet(
426+
hotkey_j,
427+
&Owner::<T>::get(hotkey_j.clone()),
428+
netuid,
429+
validator_take.to_num::<u64>(),
430+
);
431+
log::debug!(
432+
"Distributed validator take for hotkey {:?} on netuid {:?}: {:?}",
433+
hotkey_j,
434+
netuid,
435+
validator_take.to_num::<u64>()
436+
);
437+
438+
// Distribute the alpha divs to the hotkey.
402439
Self::increase_stake_for_hotkey_on_subnet(
403-
&hotkey_j,
440+
hotkey_j,
404441
netuid,
405442
rem_divs_j.to_num::<u64>(),
406443
);
@@ -411,19 +448,20 @@ impl<T: Config> Pallet<T> {
411448
rem_divs_j.to_num::<u64>()
412449
);
413450

414-
// 7.6.3.9: Record dividends for this hotkey on this subnet.
451+
// Record dividends for this hotkey on this subnet.
415452
AlphaDividendsPerSubnet::<T>::mutate(netuid, hotkey_j.clone(), |divs| {
416-
*divs = divs.saturating_add(divs_j);
453+
*divs = divs.saturating_add(*divs_j);
417454
});
418455
log::debug!(
419456
"Recorded dividends for hotkey {:?} on netuid {:?}: {:?}",
420457
hotkey_j,
421458
netuid,
422-
divs_j
459+
*divs_j
423460
);
424461
}
425462
}
426-
// For all the root alpha divs give this proportion of the swapped tao to the root participants.
463+
464+
// For all the root-alpha divs give this proportion of the swapped tao to the root participants.
427465
let _ = TaoDividendsPerSubnet::<T>::clear_prefix(netuid, u32::MAX, None);
428466
let total_root_divs_to_distribute = PendingRootDivs::<T>::get(netuid);
429467
PendingRootDivs::<T>::insert(netuid, 0);
@@ -453,13 +491,15 @@ impl<T: Config> Pallet<T> {
453491
root_divs_to_pay
454492
);
455493

456-
// 7.6.3.9: Record dividends for this hotkey on this subnet.
494+
// Record dividends for this hotkey on this subnet.
457495
TaoDividendsPerSubnet::<T>::mutate(netuid, hotkey_j.clone(), |divs| {
458496
*divs = divs.saturating_add(root_divs_to_pay);
459497
});
460498
}
461499
}
462500

501+
/// Returns the self contribution of a hotkey on a subnet.
502+
/// This is the portion of the hotkey's stake that is provided by itself, and not delegated to other hotkeys.
463503
pub fn get_self_contribution(hotkey: &T::AccountId, netuid: u16) -> u64 {
464504
// Get all childkeys for this hotkey.
465505
let childkeys = Self::get_children(hotkey, netuid);
@@ -519,12 +559,27 @@ impl<T: Config> Pallet<T> {
519559
let childkey_take_proportion: I96F32 =
520560
I96F32::from_num(Self::get_childkey_take(hotkey, netuid))
521561
.saturating_div(I96F32::from_num(u16::MAX));
562+
log::debug!(
563+
"Childkey take proportion: {:?} for hotkey {:?}",
564+
childkey_take_proportion,
565+
hotkey
566+
);
522567
// NOTE: Only the validation emission should be split amongst parents.
523568

524569
// Reserve childkey take
525570
let child_emission_take: I96F32 =
526571
childkey_take_proportion.saturating_mul(I96F32::from_num(validating_emission));
527572
let remaining_emission: I96F32 = validating_emission.saturating_sub(child_emission_take);
573+
log::debug!(
574+
"Child emission take: {:?} for hotkey {:?}",
575+
child_emission_take,
576+
hotkey
577+
);
578+
log::debug!(
579+
"Remaining emission: {:?} for hotkey {:?}",
580+
remaining_emission,
581+
hotkey
582+
);
528583

529584
// Initialize variables to track emission distribution
530585
let mut to_parents: u64 = 0;
@@ -573,6 +628,12 @@ impl<T: Config> Pallet<T> {
573628
total_contribution = total_contribution.saturating_add(combined_contribution);
574629
// Store the parent's contributions for later use
575630
parent_contributions.push((parent.clone(), combined_contribution));
631+
log::debug!(
632+
"Parent contribution for hotkey {:?} from parent {:?}: {:?}",
633+
hotkey,
634+
parent,
635+
combined_contribution
636+
);
576637
}
577638

578639
// Distribute emission to parents based on their contributions.

pallets/subtensor/src/rpc_info/delegate_info.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ impl<T: Config> Pallet<T> {
6565

6666
let return_per_1000: U64F64 = if total_stake > U64F64::from_num(0) {
6767
emissions_per_day
68-
.saturating_mul(U64F64::from_num(0.82))
68+
.saturating_mul(u16::MAX.saturating_sub(take.0).into())
69+
.saturating_div(u16::MAX.into())
6970
.saturating_div(total_stake.saturating_div(U64F64::from_num(1000)))
7071
} else {
7172
U64F64::from_num(0)

0 commit comments

Comments
 (0)