99
1010from gittensor .classes import MinerEvaluation , MinerEvaluationCache
1111from gittensor .constants import (
12- ISSUE_DISCOVERY_EMISSION_SHARE ,
1312 ISSUES_TREASURY_EMISSION_SHARE ,
1413 ISSUES_TREASURY_UID ,
1514 OSS_EMISSION_SHARE ,
16- RECYCLE_EMISSION_SHARE ,
1715 RECYCLE_UID ,
1816)
1917from gittensor .utils .uids import get_all_uids
@@ -62,12 +60,12 @@ async def forward(self: 'Validator') -> None:
6260 token_config = load_token_config ()
6361
6462 # 1. Score OSS contributions
65- oss_rewards , miner_evaluations , cached_uids , penalized_uids = await oss_contributions (
63+ _ , miner_evaluations , cached_uids , penalized_uids = await oss_contributions (
6664 self , miner_uids , master_repositories , programming_languages , token_config
6765 )
6866
6967 # 2. Score issue discovery
70- issue_rewards = await issue_discovery (
68+ _ = await issue_discovery (
7169 miner_evaluations ,
7270 master_repositories ,
7371 programming_languages ,
@@ -86,7 +84,7 @@ async def forward(self: 'Validator') -> None:
8684 await self .bulk_store_evaluation (miner_evaluations , skip_uids = cached_uids )
8785
8886 # 5. Blend 4 emission pools into final rewards
89- rewards = blend_emission_pools (oss_rewards , issue_rewards , miner_uids )
87+ rewards = blend_emission_pools (miner_evaluations , miner_uids , master_repositories )
9088
9189 self .update_scores (rewards , miner_uids , blacklisted_uids = sorted (penalized_uids ))
9290
@@ -150,49 +148,84 @@ async def issue_discovery(
150148
151149
152150def blend_emission_pools (
153- oss_rewards : np .ndarray ,
154- issue_rewards : np .ndarray ,
151+ miner_evaluations : Dict [int , MinerEvaluation ],
155152 miner_uids : set [int ],
153+ master_repositories : Dict [str , RepositoryConfig ],
156154) -> np .ndarray :
157- """Blend 4 emission pools into a single rewards array .
155+ """Blend the round emission pools using per-repo emission shares .
158156
159- - OSS contributions: 30%
160- - Issue discovery: 30%
161- - Issue treasury: 15% (flat to UID 111)
162- - Recycle: 25% (flat to UID 0)
157+ - OSS scoring pool: 90% distributed by repo emission_share
158+ - Treasury: 10% flat to UID 111
159+ - Recycle: natural slack from unallocated registry share + unclaimed repo slices
163160 """
164161 sorted_uids = sorted (miner_uids )
165162 rewards = np .zeros (len (sorted_uids ))
163+ uid_to_index = {uid : idx for idx , uid in enumerate (sorted_uids )}
166164 recycle_extra = 0.0
167165
168- # Pool 1: OSS contributions (30%)
169- oss_total = float (oss_rewards .sum ())
170- if oss_total > 0 :
171- rewards += oss_rewards * OSS_EMISSION_SHARE
172- else :
173- recycle_extra += OSS_EMISSION_SHARE
174-
175- # Pool 2: Issue discovery (30%)
176- issue_total = float (issue_rewards .sum ())
177- if issue_total > 0 :
178- rewards += issue_rewards * ISSUE_DISCOVERY_EMISSION_SHARE
179- else :
180- recycle_extra += ISSUE_DISCOVERY_EMISSION_SHARE
181-
182- # Pool 3: Issue treasury (15% flat to UID 111)
166+ total_registry_share = sum (repo .emission_share for repo in master_repositories .values ())
167+ if total_registry_share < 1.0 :
168+ recycle_extra += OSS_EMISSION_SHARE * (1.0 - total_registry_share )
169+
170+ for repo_name , repo_config in master_repositories .items ():
171+ repo_slice = OSS_EMISSION_SHARE * repo_config .emission_share
172+ if repo_slice <= 0.0 :
173+ continue
174+
175+ pr_scores : Dict [int , float ] = {}
176+ issue_scores : Dict [int , float ] = {}
177+ for uid , evaluation in miner_evaluations .items ():
178+ pr_score = sum (
179+ pr .earned_score
180+ for pr in evaluation .merged_prs
181+ if pr .repository_full_name == repo_name and pr .earned_score > 0
182+ )
183+ if pr_score > 0 :
184+ pr_scores [uid ] = pr_score
185+
186+ issue_score = evaluation .issue_discovery_scores_by_repo .get (repo_name , 0.0 )
187+ if issue_score > 0 :
188+ issue_scores [uid ] = issue_score
189+
190+ pr_total = sum (pr_scores .values ())
191+ issue_total = sum (issue_scores .values ())
192+
193+ if pr_total <= 0.0 and issue_total <= 0.0 :
194+ recycle_extra += repo_slice
195+ continue
196+
197+ issue_subslice = repo_slice * repo_config .issue_discovery_share
198+ pr_subslice = repo_slice * (1.0 - repo_config .issue_discovery_share )
199+
200+ if pr_total <= 0.0 :
201+ issue_subslice += pr_subslice
202+ pr_subslice = 0.0
203+ elif issue_total <= 0.0 :
204+ pr_subslice += issue_subslice
205+ issue_subslice = 0.0
206+
207+ if pr_subslice > 0.0 and pr_total > 0.0 :
208+ for uid , score in pr_scores .items ():
209+ idx = uid_to_index .get (uid )
210+ if idx is not None :
211+ rewards [idx ] += pr_subslice * (score / pr_total )
212+
213+ if issue_subslice > 0.0 and issue_total > 0.0 :
214+ for uid , score in issue_scores .items ():
215+ idx = uid_to_index .get (uid )
216+ if idx is not None :
217+ rewards [idx ] += issue_subslice * (score / issue_total )
218+
219+ # Treasury pool (10% flat to UID 111)
183220 if ISSUES_TREASURY_UID > 0 and ISSUES_TREASURY_UID in miner_uids :
184221 treasury_idx = sorted_uids .index (ISSUES_TREASURY_UID )
185222 rewards [treasury_idx ] += ISSUES_TREASURY_EMISSION_SHARE
186- bt .logging .info (
187- f'Treasury allocation: UID { ISSUES_TREASURY_UID } receives '
188- f'{ ISSUES_TREASURY_EMISSION_SHARE * 100 :.0f} % of emissions'
189- )
223+ else :
224+ recycle_extra += ISSUES_TREASURY_EMISSION_SHARE
190225
191- # Pool 4: Recycle (25% + unclaimed from empty pools )
226+ # Recycle pool: unclaimed repo slices + registry slack (+ treasury fallback )
192227 if RECYCLE_UID in miner_uids :
193228 recycle_idx = sorted_uids .index (RECYCLE_UID )
194- rewards [recycle_idx ] += RECYCLE_EMISSION_SHARE + recycle_extra
195- if recycle_extra > 0 :
196- bt .logging .info (f'Recycling { recycle_extra * 100 :.0f} % unclaimed emissions from empty pools' )
229+ rewards [recycle_idx ] += recycle_extra
197230
198231 return rewards
0 commit comments