Skip to content

Commit 359e24f

Browse files
committed
Merge branch '@anchpop/NNS1-2194' into 'master'
Add CF to payment_flow_with_finalization_test Adds the CF to the payment flow test in two steps (one per commit): 1. Allows the caller of `setup` to specify some NNS neurons to initialize the NNS with. I went this route instead of creating the neurons at runtime because I wanted to have exact control over the amount of maturity the NNS neurons would have. 2. Modifies payment_flow_with_finalization_test to insert an NNS neuron that has joined the CF. Closes NNS1-2194 Closes NNS1-2194 See merge request dfinity-lab/public/ic!11858
2 parents cf25f0d + 3a0989f commit 359e24f

File tree

7 files changed

+151
-78
lines changed

7 files changed

+151
-78
lines changed

rs/nns/governance/src/init.rs

Lines changed: 64 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -90,73 +90,70 @@ impl GovernanceCanisterInitPayloadBuilder {
9090
TEST_NEURON_1_OWNER_PRINCIPAL, TEST_NEURON_2_OWNER_PRINCIPAL,
9191
TEST_NEURON_3_OWNER_PRINCIPAL,
9292
};
93-
let neuron_id = NeuronIdProto::from(self.new_neuron_id());
94-
let subaccount = self.make_subaccount().into();
95-
assert_eq!(
96-
self.proto.neurons.insert(
97-
neuron_id.id,
98-
Neuron {
99-
id: Some(neuron_id),
100-
controller: Some(*TEST_NEURON_1_OWNER_PRINCIPAL),
101-
dissolve_state: Some(DissolveState::DissolveDelaySeconds(
102-
TWELVE_MONTHS_SECONDS
103-
)),
104-
cached_neuron_stake_e8s: 1_000_000_000, /* invariant: part of
105-
* TEST_NEURON_TOTAL_STAKE_E8S */
106-
account: subaccount,
107-
not_for_profit: true,
108-
..Default::default()
109-
}
110-
),
111-
None,
112-
"There is more than one neuron with the same id."
113-
);
114-
let neuron_id = NeuronIdProto::from(self.new_neuron_id());
115-
let subaccount = self.make_subaccount().into();
116-
assert_eq!(
117-
self.proto.neurons.insert(
118-
neuron_id.id,
119-
Neuron {
120-
id: Some(neuron_id),
121-
controller: Some(*TEST_NEURON_2_OWNER_PRINCIPAL),
122-
dissolve_state: Some(DissolveState::DissolveDelaySeconds(
123-
TWELVE_MONTHS_SECONDS
124-
)),
125-
cached_neuron_stake_e8s: 100_000_000, /* invariant: part of
126-
* TEST_NEURON_TOTAL_STAKE_E8S */
127-
created_timestamp_seconds: 1,
128-
aging_since_timestamp_seconds: 1,
129-
account: subaccount,
130-
not_for_profit: false,
131-
..Default::default()
132-
}
133-
),
134-
None,
135-
"There is more than one neuron with the same id."
136-
);
137-
let neuron_id = NeuronIdProto::from(self.new_neuron_id());
138-
let subaccount = self.make_subaccount().into();
139-
assert_eq!(
140-
self.proto.neurons.insert(
141-
neuron_id.id,
142-
Neuron {
143-
id: Some(neuron_id),
144-
controller: Some(*TEST_NEURON_3_OWNER_PRINCIPAL),
145-
dissolve_state: Some(DissolveState::DissolveDelaySeconds(
146-
TWELVE_MONTHS_SECONDS
147-
)),
148-
cached_neuron_stake_e8s: 10_000_000, /* invariant: part of
149-
* TEST_NEURON_TOTAL_STAKE_E8S */
150-
created_timestamp_seconds: 10,
151-
aging_since_timestamp_seconds: 10,
152-
account: subaccount,
153-
not_for_profit: false,
154-
..Default::default()
155-
}
156-
),
157-
None,
158-
"There is more than one neuron with the same id."
159-
);
93+
94+
let neuron1 = {
95+
let neuron_id = NeuronIdProto::from(self.new_neuron_id());
96+
let subaccount = self.make_subaccount().into();
97+
Neuron {
98+
id: Some(neuron_id),
99+
controller: Some(*TEST_NEURON_1_OWNER_PRINCIPAL),
100+
dissolve_state: Some(DissolveState::DissolveDelaySeconds(TWELVE_MONTHS_SECONDS)),
101+
cached_neuron_stake_e8s: 1_000_000_000, /* invariant: part of
102+
* TEST_NEURON_TOTAL_STAKE_E8S */
103+
account: subaccount,
104+
not_for_profit: true,
105+
..Default::default()
106+
}
107+
};
108+
109+
let neuron2 = {
110+
let neuron_id = NeuronIdProto::from(self.new_neuron_id());
111+
let subaccount = self.make_subaccount().into();
112+
Neuron {
113+
id: Some(neuron_id),
114+
controller: Some(*TEST_NEURON_2_OWNER_PRINCIPAL),
115+
dissolve_state: Some(DissolveState::DissolveDelaySeconds(TWELVE_MONTHS_SECONDS)),
116+
cached_neuron_stake_e8s: 100_000_000, /* invariant: part of
117+
* TEST_NEURON_TOTAL_STAKE_E8S */
118+
created_timestamp_seconds: 1,
119+
aging_since_timestamp_seconds: 1,
120+
account: subaccount,
121+
not_for_profit: false,
122+
..Default::default()
123+
}
124+
};
125+
126+
let neuron3 = {
127+
let neuron_id = NeuronIdProto::from(self.new_neuron_id());
128+
let subaccount = self.make_subaccount().into();
129+
Neuron {
130+
id: Some(neuron_id),
131+
controller: Some(*TEST_NEURON_3_OWNER_PRINCIPAL),
132+
dissolve_state: Some(DissolveState::DissolveDelaySeconds(TWELVE_MONTHS_SECONDS)),
133+
cached_neuron_stake_e8s: 10_000_000, /* invariant: part of
134+
* TEST_NEURON_TOTAL_STAKE_E8S */
135+
created_timestamp_seconds: 10,
136+
aging_since_timestamp_seconds: 10,
137+
account: subaccount,
138+
not_for_profit: false,
139+
..Default::default()
140+
}
141+
};
142+
self.with_additional_neurons(vec![neuron1, neuron2, neuron3])
143+
}
144+
145+
/// Initializes the governance canister with the given neurons.
146+
#[cfg(not(target_arch = "wasm32"))]
147+
pub fn with_additional_neurons(&mut self, neurons: Vec<Neuron>) -> &mut Self {
148+
for neuron in neurons {
149+
let id: u64 = neuron.id.as_ref().unwrap().id;
150+
assert_eq!(
151+
self.proto.neurons.insert(id, neuron),
152+
None,
153+
"There is more than one neuron with the same id ({:?}).",
154+
id
155+
);
156+
}
160157
self
161158
}
162159

rs/nns/test_utils/src/common.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ use ic_nns_common::init::{LifelineCanisterInitPayload, LifelineCanisterInitPaylo
1010
use ic_nns_constants::{
1111
ALL_NNS_CANISTER_IDS, GOVERNANCE_CANISTER_ID, LEDGER_CANISTER_ID, ROOT_CANISTER_ID,
1212
};
13-
use ic_nns_governance::{init::GovernanceCanisterInitPayloadBuilder, pb::v1::Governance};
13+
use ic_nns_governance::{
14+
init::GovernanceCanisterInitPayloadBuilder,
15+
pb::v1::{Governance, Neuron},
16+
};
1417
use ic_nns_gtc::{init::GenesisTokenCanisterInitPayloadBuilder, pb::v1::Gtc};
1518
use ic_nns_gtc_accounts::{ECT_ACCOUNTS, SEED_ROUND_ACCOUNTS};
1619
use ic_nns_handler_root::init::{RootCanisterInitPayload, RootCanisterInitPayloadBuilder};
@@ -126,6 +129,11 @@ impl NnsInitPayloadsBuilder {
126129
self
127130
}
128131

132+
pub fn with_additional_neurons(&mut self, neurons: Vec<Neuron>) -> &mut Self {
133+
self.governance.with_additional_neurons(neurons);
134+
self
135+
}
136+
129137
pub fn with_governance_init_payload(
130138
&mut self,
131139
governance_init_payload_builder: GovernanceCanisterInitPayloadBuilder,

rs/tests/nns/sns/payment_flow_with_finalization_test.rs

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
use std::time::Duration;
22

33
use anyhow::Result;
4+
use ic_nns_common::pb::v1::NeuronId;
5+
use ic_nns_governance::pb::v1::{neuron::DissolveState, Neuron};
46
use ic_sns_init::pb::v1::SnsInitPayload;
57
use ic_tests::driver::test_env_api::NnsCanisterWasmStrategy;
8+
use icp_ledger::Subaccount;
9+
use rand::RngCore;
10+
use rand_chacha::rand_core::SeedableRng;
11+
use rand_chacha::ChaChaRng;
612
use rust_decimal::prelude::ToPrimitive;
713

814
use ic_nervous_system_common::{i2d, E8};
@@ -20,7 +26,9 @@ use ic_tests::sns_client::{
2026
SNS_SALE_PARAM_MIN_PARTICIPANT_ICP_E8S,
2127
};
2228
use ic_tests::systest;
23-
use ic_tests::util::block_on;
29+
use ic_tests::util::{block_on, generate_identity};
30+
31+
const CF_CONTRIBUTION: u64 = 100 * E8;
2432

2533
fn sale_params() -> Params {
2634
Params {
@@ -39,6 +47,34 @@ fn sale_params() -> Params {
3947
}
4048
}
4149

50+
/// Deterministically generates a neuron that's joined the community fund (CF).
51+
/// As long as at least one neuron is in the CF, the CF will contribute to the SNS.
52+
fn nns_cf_neuron() -> Neuron {
53+
const TWELVE_MONTHS_SECONDS: u64 = 12 * 30 * 24 * 60 * 60;
54+
55+
let (_keypair, _pubkey, principal) = generate_identity(2000);
56+
57+
let mut rng = ChaChaRng::seed_from_u64(2000_u64);
58+
59+
let id = Some(NeuronId { id: rng.next_u64() });
60+
let account = {
61+
let mut bytes = [0u8; 32];
62+
rng.fill_bytes(&mut bytes);
63+
Subaccount(bytes)
64+
};
65+
Neuron {
66+
id,
67+
account: account.into(),
68+
maturity_e8s_equivalent: CF_CONTRIBUTION,
69+
cached_neuron_stake_e8s: E8,
70+
controller: Some(principal),
71+
dissolve_state: Some(DissolveState::DissolveDelaySeconds(TWELVE_MONTHS_SECONDS)),
72+
not_for_profit: false,
73+
joined_community_fund_timestamp_seconds: Some(1000), // should be a long time ago
74+
..Default::default()
75+
}
76+
}
77+
4278
fn init_payload() -> SnsInitPayload {
4379
oc_sns_init_payload()
4480
}
@@ -47,6 +83,7 @@ fn sns_setup_fast(env: TestEnv) {
4783
sns_deployment::setup(
4884
env,
4985
vec![],
86+
vec![nns_cf_neuron()],
5087
init_payload(),
5188
NnsCanisterWasmStrategy::TakeBuiltFromSources,
5289
true,
@@ -55,9 +92,7 @@ fn sns_setup_fast(env: TestEnv) {
5592

5693
fn initiate_token_swap_with_custom_parameters(env: TestEnv) {
5794
let params = sale_params();
58-
// TODO: NNS1-2194: Add community fund investment and verify that it works as intended.
59-
let community_fund_investment_e8s = 0;
60-
initiate_token_swap(env, params, community_fund_investment_e8s);
95+
initiate_token_swap(env, params, CF_CONTRIBUTION);
6196
}
6297

6398
/// Creates ticket participants and has them contribute in such a way that they'll hit max_icp_e8s with min_participants.
@@ -73,10 +108,10 @@ fn multiple_ticket_participants(env: TestEnv) {
73108
let num_participants = params.min_participants as u64;
74109

75110
// Calculate a value for `contribution_per_user` that will cause the icp
76-
// raised by the swap to exactly equal `params.max_participant_icp_e8s`.
111+
// raised by the swap to exactly equal `params.max_icp_e8s - CF_CONTRIBUTION`.
77112
let contribution_per_user = ic_tests::util::divide_perfectly(
78-
"max_participant_icp_e8s",
79-
params.max_participant_icp_e8s,
113+
"max_icp_e8s",
114+
params.max_icp_e8s - CF_CONTRIBUTION,
80115
num_participants,
81116
)
82117
.unwrap();
@@ -103,8 +138,8 @@ fn finalize_swap(env: TestEnv) {
103138

104139
let expected_derived_swap_state = DerivedState {
105140
direct_participant_count: Some(params.min_participants as u64),
106-
cf_participant_count: Some(0),
107-
cf_neuron_count: Some(0),
141+
cf_participant_count: Some(1),
142+
cf_neuron_count: Some(1),
108143
buyer_total_icp_e8s: params.max_icp_e8s,
109144
sns_tokens_per_icp,
110145
};

rs/tests/src/driver/test_env_api.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ use ic_nervous_system_common_test_keys::TEST_USER1_PRINCIPAL;
152152
use ic_nns_constants::{
153153
CYCLES_MINTING_CANISTER_ID, GOVERNANCE_CANISTER_ID, LIFELINE_CANISTER_ID, REGISTRY_CANISTER_ID,
154154
};
155+
use ic_nns_governance::pb::v1::Neuron;
155156
use ic_nns_init::read_initial_mutations_from_local_store_dir;
156157
use ic_nns_test_utils::{common::NnsInitPayloadsBuilder, itest_helpers::NnsCanisters};
157158
use ic_prep_lib::prep_state_directory::IcPrepStateDir;
@@ -1336,6 +1337,7 @@ pub trait NnsInstallationExt {
13361337
pub struct NnsCustomizations {
13371338
/// Summarizes the custom parameters that a newly installed NNS should have.
13381339
pub ledger_balances: Option<HashMap<AccountIdentifier, Tokens>>,
1340+
pub neurons: Option<Vec<Neuron>>,
13391341
}
13401342

13411343
#[derive(Clone, Copy, Debug)]
@@ -1393,6 +1395,7 @@ where
13931395
true,
13941396
false,
13951397
customizations.ledger_balances,
1398+
customizations.neurons,
13961399
);
13971400
Ok(())
13981401
}
@@ -1430,7 +1433,7 @@ where
14301433
};
14311434
info!(log, "Wait for node reporting healthy status");
14321435
self.await_status_is_healthy().unwrap();
1433-
install_nns_canisters(&log, url, &prep_dir, true, true, None);
1436+
install_nns_canisters(&log, url, &prep_dir, true, true, None, None);
14341437
Ok(())
14351438
}
14361439
}
@@ -1794,6 +1797,7 @@ pub fn install_nns_canisters(
17941797
nns_test_neurons_present: bool,
17951798
install_at_ids: bool,
17961799
ledger_balances: Option<HashMap<AccountIdentifier, Tokens>>,
1800+
neurons: Option<Vec<Neuron>>,
17971801
) {
17981802
let rt = Rt::new().expect("Could not create tokio runtime.");
17991803
info!(
@@ -1808,6 +1812,11 @@ pub fn install_nns_canisters(
18081812
} else {
18091813
HashMap::new()
18101814
};
1815+
let neurons = if let Some(neurons) = neurons {
1816+
neurons
1817+
} else {
1818+
Vec::new()
1819+
};
18111820
ledger_balances.insert(
18121821
LIFELINE_CANISTER_ID.get().into(),
18131822
Tokens::from_tokens(10_000).unwrap(),
@@ -1838,6 +1847,7 @@ pub fn install_nns_canisters(
18381847

18391848
init_payloads
18401849
.with_test_neurons()
1850+
.with_additional_neurons(neurons)
18411851
.with_ledger_init_state(ledger_init_payload);
18421852
}
18431853
let registry_local_store = ic_prep_state_dir.registry_local_store_path();

rs/tests/src/nns_dapp.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ pub fn nns_dapp_customizations() -> NnsCustomizations {
4444
);
4545
NnsCustomizations {
4646
ledger_balances: Some(ledger_balances),
47+
neurons: None,
4748
}
4849
}
4950

rs/tests/src/nns_tests/sns_deployment.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,9 @@ pub fn workload_static_testnet_sale_bot(env: TestEnv) {
267267
///
268268
/// This function should be the one used "by default" for most tests, to ensure
269269
/// that the tests are using realistic parameters.
270+
///
271+
/// The NNS will be initialized with only the "test" neurons.
272+
/// (See [`ic_nns_governance::init::GovernanceCanisterInitPayloadBuilder::with_test_neurons`].)
270273
pub fn setup_with_oc_init_payload(
271274
env: TestEnv,
272275
sale_participants: Vec<SaleParticipant>,
@@ -277,6 +280,7 @@ pub fn setup_with_oc_init_payload(
277280
setup(
278281
env,
279282
sale_participants,
283+
vec![], // no neurons
280284
sns_init_payload,
281285
canister_wasm_strategy,
282286
fast_test_setup,
@@ -286,6 +290,7 @@ pub fn setup_with_oc_init_payload(
286290
pub fn setup(
287291
env: TestEnv,
288292
sale_participants: Vec<SaleParticipant>,
293+
neurons: Vec<ic_nns_governance::pb::v1::Neuron>, // NNS Neurons to add in addition to the "test" neurons
289294
sns_init_payload: SnsInitPayload,
290295
canister_wasm_strategy: NnsCanisterWasmStrategy,
291296
fast_test_setup: bool,
@@ -337,6 +342,7 @@ pub fn setup(
337342
}
338343
let nns_customizations = NnsCustomizations {
339344
ledger_balances: Some(ledger_balances),
345+
neurons: Some(neurons),
340346
};
341347

342348
// Install NNS with ledger customizations

0 commit comments

Comments
 (0)