Skip to content

Commit

Permalink
Working integration test for list_node_provider_rewards
Browse files Browse the repository at this point in the history
  • Loading branch information
max-dfinity committed Aug 15, 2024
1 parent dd153bf commit b694b84
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 18 deletions.
18 changes: 9 additions & 9 deletions rs/nns/governance/api/src/ic_nns_governance.pb.v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4566,33 +4566,33 @@ impl ProposalRewardStatus {
/// A closed range of dates (i.e. includes both start and end dates)
#[derive(candid::CandidType, candid::Deserialize, serde::Serialize, comparable::Comparable)]
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq)]
pub struct DateRangeFilter {
/// The start date of the range as seconds since epoch
start_timestamp_seconds: Option<u64>,
pub start_timestamp_seconds: Option<u64>,
/// The end date of the range
end_timestamp_seconds: Option<u64>,
pub end_timestamp_seconds: Option<u64>,
}

/// A Request to list minted node provider rewards
#[derive(candid::CandidType, candid::Deserialize, serde::Serialize, comparable::Comparable)]
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq)]
pub struct ListNodeProviderRewardsRequest {
/// The next page - a token used to get the next set of results.
page: Option<u32>,
pub page: Option<u32>,
/// Filter for the dates of the rewards
date_filter: Option<DateRangeFilter>,
pub date_filter: Option<DateRangeFilter>,
}

/// A Response to list minted node provider rewards.
/// Includes optional paging information to get next set of results.
#[derive(candid::CandidType, candid::Deserialize, serde::Serialize, comparable::Comparable)]
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq)]
pub struct ListNodeProviderRewardsResponse {
/// The list of minted node provider rewards
rewards: Vec<MonthlyNodeProviderRewards>,
pub rewards: Vec<MonthlyNodeProviderRewards>,
/// The next page token to be used in the next request to get the next set of results.
next_page: Option<u32>,
pub next_page: Option<u32>,
}
4 changes: 2 additions & 2 deletions rs/nns/governance/canister/canister.rs
Original file line number Diff line number Diff line change
Expand Up @@ -737,8 +737,8 @@ async fn get_monthly_node_provider_rewards_() -> Result<RewardNodeProviders, Gov

#[export_name = "canister_query list_node_provider_rewards"]
fn list_node_provider_rewards() {
debug_log("get_minted_node_provider_rewards");
over(candid, |req| list_node_provider_rewards_(req))
debug_log("list_node_provider_rewards");
over(candid_one, list_node_provider_rewards_)
}

#[candid_method(query, rename = "list_node_provider_rewards")]
Expand Down
159 changes: 155 additions & 4 deletions rs/nns/integration_tests/src/node_provider_remuneration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@ use ic_nns_governance_api::pb::v1::{
manage_neuron_response::Command as CommandResponse,
proposal::Action,
reward_node_provider::{RewardMode, RewardToAccount},
AddOrRemoveNodeProvider, ExecuteNnsFunction, GovernanceError, NetworkEconomics, NnsFunction,
NodeProvider, Proposal, RewardNodeProvider, RewardNodeProviders,
AddOrRemoveNodeProvider, ExecuteNnsFunction, GovernanceError, ListNodeProviderRewardsRequest,
NetworkEconomics, NnsFunction, NodeProvider, Proposal, RewardNodeProvider, RewardNodeProviders,
};
use ic_nns_test_utils::{
common::NnsInitPayloadsBuilder,
state_test_helpers::{
get_pending_proposals, ledger_account_balance, nns_get_monthly_node_provider_rewards,
nns_get_most_recent_monthly_node_provider_rewards, nns_get_network_economics_parameters,
nns_governance_get_proposal_info, nns_governance_make_proposal,
nns_wait_for_proposal_execution, query, setup_nns_canisters,
state_machine_builder_for_nns_tests, update_with_sender,
nns_list_node_provider_rewards, nns_wait_for_proposal_execution, query,
setup_nns_canisters, state_machine_builder_for_nns_tests, update_with_sender,
},
};
use ic_protobuf::registry::{
Expand Down Expand Up @@ -68,6 +68,157 @@ impl NodeInfo {
}
}

#[test]
fn test_list_node_provider_rewards() {
let state_machine = state_machine_builder_for_nns_tests().build();

let nns_init_payload = NnsInitPayloadsBuilder::new()
.with_initial_invariant_compliant_mutations()
.with_test_neurons()
.build();
setup_nns_canisters(&state_machine, nns_init_payload);

add_data_centers(&state_machine);
add_node_rewards_table(&state_machine);

// Define the set of node operators and node providers
let node_info_1 = NodeInfo::new(
*TEST_USER1_PRINCIPAL,
*TEST_USER2_PRINCIPAL,
AccountIdentifier::from(*TEST_USER2_PRINCIPAL),
None,
);
let reward_mode_1 = Some(RewardMode::RewardToAccount(RewardToAccount {
to_account: Some(node_info_1.provider_account.into()),
}));
let expected_rewards_e8s_1 = ((10 * 24_000) * TOKEN_SUBDIVIDABLE_BY) / 155_000;
let expected_node_provider_reward_1 = RewardNodeProvider {
node_provider: Some(node_info_1.provider.clone()),
amount_e8s: expected_rewards_e8s_1,
reward_mode: reward_mode_1.clone(),
};

// Add Node Providers
add_node_provider(&state_machine, node_info_1.provider.clone());

// Add Node Operator 1
let rewardable_nodes_1 = btreemap! { "default".to_string() => 10 };
add_node_operator(
&state_machine,
&node_info_1.operator_id,
&node_info_1.provider_id,
"AN1",
rewardable_nodes_1,
"0:0:0:0:0:0:0:0",
);

// Set the average conversion rate
set_average_icp_xdr_conversion_rate(&state_machine, 155_000);

// Call get_monthly_node_provider_rewards assert the value is as expected
let monthly_node_provider_rewards_result: Result<RewardNodeProviders, GovernanceError> =
nns_get_monthly_node_provider_rewards(&state_machine);

let monthly_node_provider_rewards = monthly_node_provider_rewards_result.unwrap();
println!("{:?}", expected_node_provider_reward_1);
println!("{:?}", monthly_node_provider_rewards);
assert!(monthly_node_provider_rewards
.rewards
.contains(&expected_node_provider_reward_1));

// Assert account balances are 0
assert_account_balance(&state_machine, node_info_1.provider_account, 0);

// Assert there is no most recent monthly Node Provider reward
let most_recent_rewards = nns_get_most_recent_monthly_node_provider_rewards(&state_machine);
assert!(most_recent_rewards.is_none());

// Submit and execute proposal to pay NPs via Registry-driven rewards
reward_node_providers_via_registry(&state_machine);

// Assert account balances are as expected
assert_account_balance(
&state_machine,
node_info_1.provider_account,
expected_node_provider_reward_1.amount_e8s,
);

// Assert the most recent monthly Node Provider reward was set as expected
let mut most_recent_rewards =
nns_get_most_recent_monthly_node_provider_rewards(&state_machine).unwrap();
let this_rewards_timestamp = most_recent_rewards.timestamp;

assert!(most_recent_rewards
.rewards
.contains(&expected_node_provider_reward_1));

// Assert advancing time less than a month doesn't trigger monthly NP rewards
let mut rewards_were_triggered = false;
for _ in 0..5 {
state_machine.advance_time(Duration::from_secs(60));
let most_recent_rewards =
nns_get_most_recent_monthly_node_provider_rewards(&state_machine).unwrap();
if most_recent_rewards.timestamp != this_rewards_timestamp {
rewards_were_triggered = true;
break;
}
}

assert!(
!rewards_were_triggered,
"Automated rewards were triggered even though less than 1 month has passed."
);

// Assert account balances haven't changed
assert_account_balance(
&state_machine,
node_info_1.provider_account,
expected_node_provider_reward_1.amount_e8s,
);

// Set a new average conversion rate so that we can assert that the automated monthly
// NP rewards paid a different reward than the proposal-based reward.
let average_icp_xdr_conversion_rate_for_automated_rewards = 345_000;
set_average_icp_xdr_conversion_rate(
&state_machine,
average_icp_xdr_conversion_rate_for_automated_rewards,
);

let mut minted_rewards = vec![most_recent_rewards.clone()];
for _ in 0..12 {
// Assert that advancing time by a month triggers an automated monthly NP reward event
state_machine.advance_time(Duration::from_secs(ONE_MONTH_SECONDS + 1));
state_machine.advance_time(Duration::from_secs(60));
state_machine.tick();
state_machine.tick();
state_machine.tick();
state_machine.tick();
state_machine.tick();
state_machine.tick();
state_machine.tick();
state_machine.tick();

let rewards = nns_get_most_recent_monthly_node_provider_rewards(&state_machine).unwrap();

minted_rewards.push(rewards.clone());
}

let response = nns_list_node_provider_rewards(
&state_machine,
ListNodeProviderRewardsRequest {
page: None,
date_filter: None,
},
);

assert_eq!(response.rewards.len(), 5);
//
// let received_ts: Vec<u64> = response.rewards.iter().map(|r| r.timestamp).collect();
// let expected_ts: Vec<u64> = minted_rewards.iter().map(|r| r.timestamp).collect();
//
// assert_eq!(received_ts, expected_ts[8..]);
assert_eq!(response.rewards, minted_rewards[8..]);
}
#[test]
fn test_automated_node_provider_remuneration() {
let state_machine = state_machine_builder_for_nns_tests().build();
Expand Down
27 changes: 24 additions & 3 deletions rs/nns/test_utils/src/state_test_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,10 @@ use ic_nns_governance_api::pb::v1::{
manage_neuron_response::{self, ClaimOrRefreshResponse},
proposal::{self, Action},
Empty, ExecuteNnsFunction, Governance, GovernanceError, InstallCode, ListNeurons,
ListNeuronsResponse, ListProposalInfo, ListProposalInfoResponse, ManageNeuron,
ManageNeuronResponse, MonthlyNodeProviderRewards, NetworkEconomics, NnsFunction, Proposal,
ProposalInfo, RewardNodeProviders, Vote,
ListNeuronsResponse, ListNodeProviderRewardsRequest, ListNodeProviderRewardsResponse,
ListProposalInfo, ListProposalInfoResponse, ManageNeuron, ManageNeuronResponse,
MonthlyNodeProviderRewards, NetworkEconomics, NnsFunction, Proposal, ProposalInfo,
RewardNodeProviders, Vote,
};
use ic_nns_handler_lifeline_interface::UpgradeRootProposal;
use ic_nns_handler_root::init::RootCanisterInitPayload;
Expand Down Expand Up @@ -1388,6 +1389,26 @@ pub fn nns_get_most_recent_monthly_node_provider_rewards(
Decode!(&result, Option<MonthlyNodeProviderRewards>).unwrap()
}

pub fn nns_list_node_provider_rewards(
state_machine: &StateMachine,
list_node_provider_rewards_request: ListNodeProviderRewardsRequest,
) -> ListNodeProviderRewardsResponse {
let result = state_machine
.execute_ingress(
GOVERNANCE_CANISTER_ID,
"list_node_provider_rewards",
Encode!(&list_node_provider_rewards_request).unwrap(),
)
.unwrap();

let result = match result {
WasmResult::Reply(result) => result,
WasmResult::Reject(s) => panic!("Call to list_node_provider_rewards failed: {:#?}", s),
};

Decode!(&result, ListNodeProviderRewardsResponse).unwrap()
}

pub fn nns_get_network_economics_parameters(state_machine: &StateMachine) -> NetworkEconomics {
let result = state_machine
.execute_ingress(
Expand Down

0 comments on commit b694b84

Please sign in to comment.