-
Notifications
You must be signed in to change notification settings - Fork 296
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(governance): 🧊 test that community pool spend proposals can be d…
…isabled (#4222) fixes #4079. related to, but does not finish #2105. this introduces test coverage to show that community pool spend proposals can be disabled via a chain parameter. ### related changes some changes made, related to writing tests for the governance component: * 6b3be58 refactor(governance): 💶 `Value` accessors for proposal actions * de16dac feat(tx): 🌮 `ActionPlan: From` for community pool actions * 4e6b874 feat(amount): ➖ `Amount: std::ops::SubAssign` ### tests this addresses part of #2105. we should add tests that exercise the other tallying logic before that issue is complete. tests are added in the following commits: * fedfa8d tests(app): 💭 test a community pool spend * 201fe48 tests(app): 🏊 test a community pool deposit * 8543869 tests(app): 🥶 test that community pool can be frozen
- Loading branch information
Showing
7 changed files
with
937 additions
and
17 deletions.
There are no files selected for viewing
129 changes: 129 additions & 0 deletions
129
crates/core/app/tests/app_can_deposit_into_community_pool.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
use { | ||
self::common::BuilderExt, | ||
anyhow::anyhow, | ||
cnidarium::TempStorage, | ||
penumbra_app::{genesis::AppState, server::consensus::Consensus}, | ||
penumbra_asset::asset, | ||
penumbra_community_pool::{CommunityPoolDeposit, StateReadExt}, | ||
penumbra_keys::test_keys, | ||
penumbra_mock_client::MockClient, | ||
penumbra_mock_consensus::TestNode, | ||
penumbra_num::Amount, | ||
penumbra_proto::DomainType, | ||
penumbra_shielded_pool::SpendPlan, | ||
penumbra_transaction::{TransactionParameters, TransactionPlan}, | ||
rand_core::OsRng, | ||
std::collections::BTreeMap, | ||
tap::{Tap, TapFallible}, | ||
tracing::info, | ||
}; | ||
|
||
mod common; | ||
|
||
/// Exercises that the app can deposit a note into the community pool. | ||
#[tokio::test] | ||
async fn app_can_deposit_into_community_pool() -> anyhow::Result<()> { | ||
// Install a test logger, and acquire some temporary storage. | ||
let guard = common::set_tracing_subscriber(); | ||
let storage = TempStorage::new().await?; | ||
|
||
// Define our application state, and start the test node. | ||
let mut test_node = { | ||
let app_state = AppState::default(); | ||
let consensus = Consensus::new(storage.as_ref().clone()); | ||
TestNode::builder() | ||
.single_validator() | ||
.with_penumbra_auto_app_state(app_state)? | ||
.init_chain(consensus) | ||
.await | ||
.tap_ok(|e| tracing::info!(hash = %e.last_app_hash_hex(), "finished init chain"))? | ||
}; | ||
|
||
// Sync the mock client, using the test wallet's spend key, to the latest snapshot. | ||
let client = MockClient::new(test_keys::SPEND_KEY.clone()) | ||
.with_sync_to_storage(&storage) | ||
.await? | ||
.tap(|c| info!(client.notes = %c.notes.len(), "mock client synced to test storage")); | ||
|
||
// Take one of the test wallet's notes, and prepare to deposit it in the community pool. | ||
let note = client | ||
.notes | ||
.values() | ||
.cloned() | ||
.next() | ||
.ok_or_else(|| anyhow!("mock client had no note"))?; | ||
|
||
// Create a community pool transaction. | ||
let mut plan = { | ||
let value = note.value(); | ||
let spend = SpendPlan::new( | ||
&mut OsRng, | ||
note.clone(), | ||
client | ||
.position(note.commit()) | ||
.ok_or_else(|| anyhow!("input note commitment was unknown to mock client"))?, | ||
) | ||
.into(); | ||
let deposit = CommunityPoolDeposit { value }.into(); | ||
TransactionPlan { | ||
actions: vec![spend, deposit], | ||
// Now fill out the remaining parts of the transaction needed for verification: | ||
memo: None, | ||
detection_data: None, // We'll set this automatically below | ||
transaction_parameters: TransactionParameters { | ||
chain_id: TestNode::<()>::CHAIN_ID.to_string(), | ||
..Default::default() | ||
}, | ||
} | ||
}; | ||
plan.populate_detection_data(OsRng, 0); | ||
let tx = client.witness_auth_build(&plan).await?; | ||
|
||
// Execute the transaction, applying it to the chain state. | ||
let pre_tx_snapshot = storage.latest_snapshot(); | ||
test_node | ||
.block() | ||
.with_data(vec![tx.encode_to_vec()]) | ||
.execute() | ||
.await?; | ||
let post_tx_snapshot = storage.latest_snapshot(); | ||
|
||
// Assert that the community pool balance looks correct for the deposited asset id, and that | ||
// other amounts were not affected by the deposit. | ||
{ | ||
type Balance = BTreeMap<asset::Id, Amount>; | ||
|
||
let id = note.asset_id(); | ||
let pre_tx_balance = pre_tx_snapshot.community_pool_balance().await?; | ||
let post_tx_balance = post_tx_snapshot.community_pool_balance().await?; | ||
|
||
let get_balance_for_id = |balance: &Balance| balance.get(&id).copied().unwrap_or_default(); | ||
let pre_tx_amount = get_balance_for_id(&pre_tx_balance); | ||
let post_tx_amount = get_balance_for_id(&post_tx_balance); | ||
assert_eq!( | ||
pre_tx_amount + note.amount(), | ||
post_tx_amount, | ||
"community pool balance should include the deposited note" | ||
); | ||
|
||
let count_other_assets_in_pool = |balance: &Balance| { | ||
balance | ||
.into_iter() | ||
// Skip the amount for our note's asset id. | ||
.filter(|(&entry_id, _)| entry_id != id) | ||
.map(|(_, &amount)| amount) | ||
.sum::<Amount>() | ||
}; | ||
assert_eq!( | ||
count_other_assets_in_pool(&pre_tx_balance), | ||
count_other_assets_in_pool(&post_tx_balance), | ||
"other community pool balance amounts should not have changed" | ||
); | ||
} | ||
|
||
// Free our temporary storage. | ||
Ok(()) | ||
.tap(|_| drop(test_node)) | ||
.tap(|_| drop(storage)) | ||
.tap(|_| drop(guard)) | ||
} |
Oops, something went wrong.