From ed2fbc588ff5a90d41c37825a986effe9501b125 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 16 Oct 2024 17:34:34 +0100 Subject: [PATCH] allow to overwrite contract state with explicit config flag --- nym-api/src/ecash/state/local.rs | 4 ++ nym-api/src/ecash/state/mod.rs | 12 +++- nym-api/src/ecash/tests/issued_credentials.rs | 4 +- nym-api/src/ecash/tests/mod.rs | 55 ++++++++++++------- nym-api/src/support/cli/run.rs | 1 + 5 files changed, 54 insertions(+), 22 deletions(-) diff --git a/nym-api/src/ecash/state/local.rs b/nym-api/src/ecash/state/local.rs index 64eef0ce07..b840bab394 100644 --- a/nym-api/src/ecash/state/local.rs +++ b/nym-api/src/ecash/state/local.rs @@ -80,6 +80,8 @@ pub(crate) struct LocalEcashState { pub(crate) ecash_keypair: KeyPair, pub(crate) identity_keypair: identity::KeyPair, + pub(crate) explicitly_disabled: bool, + /// Specifies whether this api is a signer in given epoch pub(crate) active_signer: CachedImmutableEpochItem, @@ -96,10 +98,12 @@ impl LocalEcashState { ecash_keypair: KeyPair, identity_keypair: identity::KeyPair, double_spending_filter: TicketDoubleSpendingFilter, + explicitly_disabled: bool, ) -> Self { LocalEcashState { ecash_keypair, identity_keypair, + explicitly_disabled, active_signer: Default::default(), partial_coin_index_signatures: Default::default(), partial_expiration_date_signatures: Default::default(), diff --git a/nym-api/src/ecash/state/mod.rs b/nym-api/src/ecash/state/mod.rs index e1a3908510..11ed0d3ff7 100644 --- a/nym-api/src/ecash/state/mod.rs +++ b/nym-api/src/ecash/state/mod.rs @@ -75,6 +75,7 @@ impl EcashState { key_pair: KeyPair, comm_channel: D, storage: NymApiStorage, + signer_disabled: bool, ) -> Result where C: LocalClient + Send + Sync + 'static, @@ -84,13 +85,22 @@ impl EcashState { Ok(Self { global: GlobalEcachState::new(contract_address), - local: LocalEcashState::new(key_pair, identity_keypair, double_spending_filter), + local: LocalEcashState::new( + key_pair, + identity_keypair, + double_spending_filter, + signer_disabled, + ), aux: AuxiliaryEcashState::new(client, comm_channel, storage), }) } /// Ensures that this nym-api is one of ecash signers for the current epoch pub(crate) async fn ensure_signer(&self) -> Result<()> { + if self.local.explicitly_disabled { + return Err(EcashError::NotASigner); + } + let epoch_id = self.aux.current_epoch().await?; let is_epoch_signer = self diff --git a/nym-api/src/ecash/tests/issued_credentials.rs b/nym-api/src/ecash/tests/issued_credentials.rs index 877e974d05..00dac0d525 100644 --- a/nym-api/src/ecash/tests/issued_credentials.rs +++ b/nym-api/src/ecash/tests/issued_credentials.rs @@ -53,7 +53,7 @@ async fn epoch_credentials() { assert_eq!(parsed_response.total_issued, 2); assert_eq!(parsed_response.first_epoch_credential_id, Some(1)); - test_fixture.set_epoch(2); + test_fixture.set_epoch(2).await; let response = test_fixture.axum.get(&route_epoch2).await; assert_eq!(response.status_code(), StatusCode::OK); @@ -115,7 +115,7 @@ async fn issued_credential() { let cred1 = test_fixture.issue_credential(request1.clone()).await; - test_fixture.set_epoch(3); + test_fixture.set_epoch(3).await; let cred2 = test_fixture.issue_credential(request2.clone()).await; let response = test_fixture.axum.get(&route(1)).await; diff --git a/nym-api/src/ecash/tests/mod.rs b/nym-api/src/ecash/tests/mod.rs index aba83c5ec4..123c0a7930 100644 --- a/nym-api/src/ecash/tests/mod.rs +++ b/nym-api/src/ecash/tests/mod.rs @@ -1133,18 +1133,23 @@ impl DummyCommunicationChannel { } } - pub fn new_single_dummy(aggregated_verification_key: VerificationKeyAuth) -> Self { + pub fn new_single_dummy( + aggregated_verification_key: VerificationKeyAuth, + cosmos_address: AccountId, + ) -> Self { let client = EcashApiClient { api_client: NymApiClient::new("http://localhost:1234".parse().unwrap()), verification_key: aggregated_verification_key, node_id: 1, - cosmos_address: "n16a32stm6kknhq5cc8rx77elr66pygf2hfszw7wvpq746x3uffylqkjar4l" - .parse() - .unwrap(), + cosmos_address, }; Self::new(vec![client]) } + pub fn clients_arc(&self) -> Arc>>> { + Arc::clone(&self.ecash_clients) + } + pub fn with_epoch(mut self, current_epoch: Arc) -> Self { self.current_epoch = current_epoch; self @@ -1248,6 +1253,7 @@ struct TestFixture { storage: NymApiStorage, chain_state: SharedFakeChain, epoch: Arc, + ecash_clients: Arc>>>, _tmp_dir: TempDir, } @@ -1273,9 +1279,13 @@ impl TestFixture { let coconut_keypair = ttp_keygen(1, 1).unwrap().remove(0); let identity = identity::KeyPair::new(&mut rng); let epoch = Arc::new(AtomicU64::new(1)); - let comm_channel = - DummyCommunicationChannel::new_single_dummy(coconut_keypair.verification_key().clone()) - .with_epoch(epoch.clone()); + let address = AccountId::from_str(TEST_REWARDING_VALIDATOR_ADDRESS).unwrap(); + let comm_channel = DummyCommunicationChannel::new_single_dummy( + coconut_keypair.verification_key().clone(), + address.clone(), + ) + .with_epoch(epoch.clone()); + let ecash_clients = comm_channel.clients_arc(); // TODO: it's AWFUL to test with actual storage, we should somehow abstract it away let tmp_dir = tempdir().unwrap(); @@ -1293,10 +1303,7 @@ impl TestFixture { staged_key_pair.validate(); let chain_state = SharedFakeChain::default(); - let nyxd_client = DummyClient::new( - AccountId::from_str(TEST_REWARDING_VALIDATOR_ADDRESS).unwrap(), - chain_state.clone(), - ); + let nyxd_client = DummyClient::new(address, chain_state.clone()); let ecash_contract = chain_state .lock() @@ -1315,6 +1322,7 @@ impl TestFixture { staged_key_pair, comm_channel, storage.clone(), + false, ) .await .unwrap(); @@ -1329,12 +1337,20 @@ impl TestFixture { storage, chain_state, epoch, + ecash_clients, _tmp_dir: tmp_dir, } } - fn set_epoch(&self, epoch: u64) { - self.epoch.store(epoch, Ordering::Relaxed) + async fn set_epoch(&self, epoch: u64) { + let current_epoch = self.epoch.load(Ordering::Relaxed); + self.epoch.store(epoch, Ordering::Relaxed); + + // copy the same epoch_signers as we had initially + let existing = self.ecash_clients.read().await.get(¤t_epoch).cloned(); + if let Some(clients) = existing { + self.ecash_clients.write().await.insert(epoch, clients); + } } #[allow(dead_code)] @@ -1455,19 +1471,19 @@ mod credential_tests { async fn state_functions() { let mut rng = OsRng; let identity = identity::KeyPair::new(&mut rng); + let address = AccountId::from_str(TEST_REWARDING_VALIDATOR_ADDRESS).unwrap(); - let nyxd_client = DummyClient::new( - AccountId::from_str(TEST_REWARDING_VALIDATOR_ADDRESS).unwrap(), - Default::default(), - ); + let nyxd_client = DummyClient::new(address.clone(), Default::default()); let key_pair = ttp_keygen(1, 1).unwrap().remove(0); let tmp_dir = tempdir().unwrap(); let storage = NymApiStorage::init(tmp_dir.path().join("storage.db")) .await .unwrap(); - let comm_channel = - DummyCommunicationChannel::new_single_dummy(key_pair.verification_key().clone()); + let comm_channel = DummyCommunicationChannel::new_single_dummy( + key_pair.verification_key().clone(), + address, + ); let staged_key_pair = crate::ecash::keys::KeyPair::new(); staged_key_pair .set(KeyPairWithEpoch { @@ -1486,6 +1502,7 @@ mod credential_tests { staged_key_pair, comm_channel, storage.clone(), + false, ) .await .unwrap(); diff --git a/nym-api/src/support/cli/run.rs b/nym-api/src/support/cli/run.rs index 119043d230..cef94c86ce 100644 --- a/nym-api/src/support/cli/run.rs +++ b/nym-api/src/support/cli/run.rs @@ -146,6 +146,7 @@ async fn start_nym_api_tasks_axum(config: &Config) -> anyhow::Result