diff --git a/swagger.yaml b/swagger.yaml index b75c74c..f5c1eb9 100644 --- a/swagger.yaml +++ b/swagger.yaml @@ -288,11 +288,11 @@ paths: application/json: schema: $ref: '#/components/schemas/GetPlayerDataResponse' - /get-round-earnings: + /get-round-emissions: get: tags: - GET - summary: Get round earnings for algorithms, opow, and players for a specific round + summary: Get round emissions for a specific round (algorithms, breakthroughs, opow, players, and totals) description: |- # Notes * `algorithms` is a map of `` to `uint256` @@ -310,6 +310,8 @@ paths: * `players` is a map of `` to a dict of reward types (algorithm, benchmark, breakthroughs, delegator) * `names` is a map of `` to ENS name (only if one exists) + + * `totals` is a map of emission types to `uint256` parameters: - name: round in: query @@ -324,7 +326,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/GetRoundEarningsResponse' + $ref: '#/components/schemas/GetRoundEmissionsResponse' /request-api-key: post: tags: @@ -836,6 +838,21 @@ components: timestamp: type: integer format: uint64 + emissions: + type: object + properties: + algorithms: + $ref: '#/components/schemas/PreciseNumber' + breakthroughs: + $ref: '#/components/schemas/PreciseNumber' + benchmarkers: + $ref: '#/components/schemas/PreciseNumber' + delegators: + $ref: '#/components/schemas/PreciseNumber' + bootstrap: + $ref: '#/components/schemas/PreciseNumber' + vault: + $ref: '#/components/schemas/PreciseNumber' BlockData: type: object properties: @@ -1139,7 +1156,7 @@ components: solution_ratio_by_challenge: type: object additionalProperties: - type: double + type: number format: number example: {"c001": 0.001, "c002": 0.5} cutoff: @@ -1462,7 +1479,7 @@ components: type: array items: $ref: '#/components/schemas/TopUp' - GetRoundEarningsResponse: + GetRoundEmissionsResponse: type: object properties: algorithms: @@ -1503,7 +1520,21 @@ components: type: object additionalProperties: type: string - + totals: + type: object + properties: + algorithms: + $ref: '#/components/schemas/PreciseNumber' + breakthroughs: + $ref: '#/components/schemas/PreciseNumber' + benchmarkers: + $ref: '#/components/schemas/PreciseNumber' + delegators: + $ref: '#/components/schemas/PreciseNumber' + bootstrap: + $ref: '#/components/schemas/PreciseNumber' + vault: + $ref: '#/components/schemas/PreciseNumber' RequestApiKeyRequest: type: object properties: diff --git a/tig-protocol/src/contracts/rewards.rs b/tig-protocol/src/contracts/rewards.rs index 84ebae1..9bb8a27 100644 --- a/tig-protocol/src/contracts/rewards.rs +++ b/tig-protocol/src/contracts/rewards.rs @@ -25,6 +25,8 @@ pub(crate) async fn update(cache: &mut AddBlockCache) { let active_breakthrough_ids = &block_data.active_ids[&ActiveType::Breakthrough]; let active_challenge_ids = &block_data.active_ids[&ActiveType::Challenge]; + let zero = PreciseNumber::from(0); + let gamma = 1.0258 * (1.0 - 0.8730 * (-0.0354 * active_challenge_ids.len() as f64).exp()); let block_reward = PreciseNumber::from_f64( config .rewards @@ -40,10 +42,10 @@ pub(crate) async fn update(cache: &mut AddBlockCache) { }) .block_reward, ); + let scaled_reward = block_reward * PreciseNumber::from_f64(gamma); // update algorithm rewards let adoption_threshold = PreciseNumber::from_f64(config.algorithms.adoption_threshold); - let zero = PreciseNumber::from(0); let mut eligible_algorithms_by_challenge = HashMap::>::new(); for algorithm_id in active_algorithm_ids.iter() { let algorithm_state = &active_algorithms_state[algorithm_id]; @@ -59,7 +61,7 @@ pub(crate) async fn update(cache: &mut AddBlockCache) { .get_mut(&algorithm_details.player_id) .unwrap() .reward_by_type - .insert(RewardType::Algorithm, zero.clone()); + .insert(EmissionsType::Algorithm, zero.clone()); if algorithm_data.adoption >= adoption_threshold || (is_merged && algorithm_data.adoption > zero) @@ -70,10 +72,12 @@ pub(crate) async fn update(cache: &mut AddBlockCache) { .push(algorithm_id.clone()); } } + let algorithms_reward_pool = + scaled_reward * PreciseNumber::from_f64(config.rewards.distribution.algorithms); + let mut total_algorithms_reward = zero.clone(); if eligible_algorithms_by_challenge.len() > 0 { - let reward_pool_per_challenge = block_reward - * PreciseNumber::from_f64(config.rewards.distribution.algorithms) - / PreciseNumber::from(eligible_algorithms_by_challenge.len()); + let reward_pool_per_challenge = + algorithms_reward_pool / PreciseNumber::from(eligible_algorithms_by_challenge.len()); for algorithm_ids in eligible_algorithms_by_challenge.values() { let total_adoption: PreciseNumber = algorithm_ids @@ -82,15 +86,16 @@ pub(crate) async fn update(cache: &mut AddBlockCache) { .sum(); for algorithm_id in algorithm_ids.iter() { let algorithm_data = active_algorithms_block_data.get_mut(algorithm_id).unwrap(); - algorithm_data.reward = - reward_pool_per_challenge * algorithm_data.adoption / total_adoption; + let reward = reward_pool_per_challenge * algorithm_data.adoption / total_adoption; + algorithm_data.reward = reward; + total_algorithms_reward += reward; let algorithm_details = &active_algorithms_details[algorithm_id]; *active_players_block_data .get_mut(&algorithm_details.player_id) .unwrap() .reward_by_type - .get_mut(&RewardType::Algorithm) + .get_mut(&EmissionsType::Algorithm) .unwrap() += algorithm_data.reward; } } @@ -98,9 +103,11 @@ pub(crate) async fn update(cache: &mut AddBlockCache) { // update breakthrough rewards let adoption_threshold = PreciseNumber::from_f64(config.breakthroughs.adoption_threshold); - let reward_pool_per_challenge = block_reward - * PreciseNumber::from_f64(config.rewards.distribution.breakthroughs) - / PreciseNumber::from(active_challenge_ids.len()); + let breakthroughs_reward_pool = + scaled_reward * PreciseNumber::from_f64(config.rewards.distribution.breakthroughs); + let mut total_breakthroughs_reward = zero.clone(); + let reward_pool_per_challenge = + breakthroughs_reward_pool / PreciseNumber::from(active_challenge_ids.len()); for breakthrough_id in active_breakthrough_ids.iter() { let breakthrough_state = &active_breakthroughs_state[breakthrough_id]; let breakthrough_details = &active_breakthroughs_details[breakthrough_id]; @@ -123,17 +130,19 @@ pub(crate) async fn update(cache: &mut AddBlockCache) { .get_mut(&breakthrough_details.player_id) .unwrap() .reward_by_type - .entry(RewardType::Breakthrough) + .entry(EmissionsType::Breakthrough) .or_insert(zero.clone()) += reward; active_breakthroughs_block_data .get_mut(breakthrough_id) .unwrap() .reward = reward; + total_breakthroughs_reward += reward; } // update benchmark rewards - let reward_pool = block_reward * PreciseNumber::from_f64(config.rewards.distribution.opow); - let zero = PreciseNumber::from(0); + let reward_pool = scaled_reward * PreciseNumber::from_f64(config.rewards.distribution.opow); + let mut total_benchmarkers_reward = zero.clone(); + let mut total_delegators_reward = zero.clone(); for (delegatee, opow_data) in active_opow_block_data.iter_mut() { opow_data.reward = opow_data.influence * reward_pool; @@ -163,14 +172,15 @@ pub(crate) async fn update(cache: &mut AddBlockCache) { .iter() { let fraction = PreciseNumber::from_f64(*fraction); - let amount = coinbase_amount * fraction; - opow_data.coinbase.insert(output.clone(), amount.clone()); + let reward = coinbase_amount * fraction; + opow_data.coinbase.insert(output.clone(), reward.clone()); let player_data = active_players_block_data.get_mut(output).unwrap(); *player_data .reward_by_type - .entry(RewardType::Benchmarker) - .or_insert(zero.clone()) += amount; + .entry(EmissionsType::Benchmarker) + .or_insert(zero.clone()) += reward; + total_benchmarkers_reward += reward; } if opow_data.reward_share == zero { @@ -180,12 +190,38 @@ pub(crate) async fn update(cache: &mut AddBlockCache) { for delegator in opow_data.delegators.iter() { let player_data = active_players_block_data.get_mut(delegator).unwrap(); let fraction = PreciseNumber::from_f64(*player_data.delegatees.get(delegatee).unwrap()); + let reward = opow_data.reward_share * fraction * player_data.weighted_deposit + / opow_data.delegated_weighted_deposit; *player_data .reward_by_type - .entry(RewardType::Delegator) - .or_insert(zero.clone()) += - opow_data.reward_share * fraction * player_data.weighted_deposit - / opow_data.delegated_weighted_deposit; + .entry(EmissionsType::Delegator) + .or_insert(zero.clone()) += reward; + total_delegators_reward += reward; } } + + block_details.emissions.insert( + EmissionsType::Bootstrap, + breakthroughs_reward_pool - total_breakthroughs_reward, + ); + block_details.emissions.insert( + EmissionsType::Vault, + block_reward + - total_algorithms_reward + - breakthroughs_reward_pool + - total_benchmarkers_reward + - total_delegators_reward, + ); + block_details + .emissions + .insert(EmissionsType::Algorithm, total_algorithms_reward); + block_details + .emissions + .insert(EmissionsType::Breakthrough, total_breakthroughs_reward); + block_details + .emissions + .insert(EmissionsType::Benchmarker, total_benchmarkers_reward); + block_details + .emissions + .insert(EmissionsType::Delegator, total_delegators_reward); } diff --git a/tig-structs/src/core.rs b/tig-structs/src/core.rs index 9dece1a..f97f9dc 100644 --- a/tig-structs/src/core.rs +++ b/tig-structs/src/core.rs @@ -241,6 +241,16 @@ pub enum ActiveType { OPoW, Player, } +#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)] +#[serde(rename_all = "lowercase")] +pub enum EmissionsType { + Benchmarker, + Algorithm, + Breakthrough, + Delegator, + Bootstrap, + Vault, +} serializable_struct_with_getters! { BlockDetails { prev_block_id: String, @@ -249,6 +259,7 @@ serializable_struct_with_getters! { num_confirmed: HashMap, num_active: HashMap, timestamp: u64, + emissions: HashMap, } } serializable_struct_with_getters! { @@ -386,18 +397,10 @@ serializable_struct_with_getters! { coinbase: Option>>, } } -#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)] -#[serde(rename_all = "lowercase")] -pub enum RewardType { - Benchmarker, - Algorithm, - Breakthrough, - Delegator, -} serializable_struct_with_getters! { PlayerBlockData { delegatees: HashMap, - reward_by_type: HashMap, + reward_by_type: HashMap, deposit_by_locked_period: Vec, weighted_deposit: PreciseNumber, }