Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cp: add initial_balance to content message #4666

Merged
merged 6 commits into from
Jun 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 21 additions & 7 deletions crates/core/app/tests/app_can_disable_community_pool_spends.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use {
server::consensus::Consensus,
CommunityPoolStateReadExt as _,
},
penumbra_asset::STAKING_TOKEN_ASSET_ID,
penumbra_community_pool::{
CommunityPoolDeposit, CommunityPoolOutput, CommunityPoolSpend, StateReadExt as _,
},
Expand All @@ -17,10 +18,11 @@ use {
},
penumbra_keys::{
keys::{SpendKey, SpendKeyBytes},
test_keys::{self},
test_keys,
},
penumbra_mock_client::MockClient,
penumbra_mock_consensus::TestNode,
penumbra_num::Amount,
penumbra_proto::{
core::keys::v1::{GovernanceKey, IdentityKey},
penumbra::core::component::stake::v1::Validator as PenumbraValidator,
Expand Down Expand Up @@ -124,6 +126,7 @@ async fn app_can_disable_community_pool_spends() -> anyhow::Result<()> {
// Disable community spend proposals.
community_pool_spend_proposals_enabled: false,
},
..Default::default()
},
..Default::default()
};
Expand Down Expand Up @@ -309,15 +312,23 @@ async fn app_can_disable_community_pool_spends() -> anyhow::Result<()> {

// At the outset, the pool should be empty.
assert_eq!(
original_pool_balance,
BTreeMap::default(),
original_pool_balance.len(),
1,
"fresh community pool only track the staking token"
);
assert_eq!(
*original_pool_balance
.get(&STAKING_TOKEN_ASSET_ID)
.expect("CP tracks staking token, even with no balance"),
Amount::zero(),
"the community pool should be empty at the beginning of the chain"
);

// After we deposit a note into the community pool, we should see the original pool contents,
// plus the amount that we deposited.
assert_eq!(
[(note.asset_id(), note.amount())]
[(note.asset_id(), note.amount()),
(*STAKING_TOKEN_ASSET_ID, Amount::zero())]
.into_iter()
.collect::<BTreeMap<_, _>>(),
post_deposit_pool_balance,
Expand Down Expand Up @@ -354,9 +365,12 @@ async fn app_can_disable_community_pool_spends() -> anyhow::Result<()> {
// After any possible voting period, we should see the same pool balance.
assert_eq!(
post_voting_period_pool_balance,
[(note.asset_id(), note.amount())]
.into_iter()
.collect::<BTreeMap<_, _>>(),
[
(note.asset_id(), note.amount()),
(*STAKING_TOKEN_ASSET_ID, Amount::zero())
]
.into_iter()
.collect::<BTreeMap<_, _>>(),
"a rejected proposal should not decrease the funds of the community pool"
);
assert_eq!(
Expand Down
28 changes: 21 additions & 7 deletions crates/core/app/tests/app_can_propose_community_pool_spends.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use {
server::consensus::Consensus,
CommunityPoolStateReadExt as _,
},
penumbra_asset::STAKING_TOKEN_ASSET_ID,
penumbra_community_pool::{
CommunityPoolDeposit, CommunityPoolOutput, CommunityPoolSpend, StateReadExt as _,
},
Expand All @@ -17,10 +18,11 @@ use {
},
penumbra_keys::{
keys::{SpendKey, SpendKeyBytes},
test_keys::{self},
test_keys,
},
penumbra_mock_client::MockClient,
penumbra_mock_consensus::TestNode,
penumbra_num::Amount,
penumbra_proto::{
core::keys::v1::{GovernanceKey, IdentityKey},
penumbra::core::component::stake::v1::Validator as PenumbraValidator,
Expand Down Expand Up @@ -303,17 +305,27 @@ async fn app_can_propose_community_pool_spends() -> anyhow::Result<()> {

// At the outset, the pool should be empty.
assert_eq!(
original_pool_balance,
BTreeMap::default(),
original_pool_balance.len(),
1,
"fresh community pool only track the staking token"
);
assert_eq!(
*original_pool_balance
.get(&STAKING_TOKEN_ASSET_ID)
.expect("CP tracks the staking token"),
Amount::zero(),
"the community pool should be empty at the beginning of the chain"
);

// After we deposit a note into the community pool, we should see the original pool contents,
// plus the amount that we deposited.
assert_eq!(
[(note.asset_id(), note.amount())]
.into_iter()
.collect::<BTreeMap<_, _>>(),
[
(note.asset_id(), note.amount()),
(*STAKING_TOKEN_ASSET_ID, Amount::zero())
]
.into_iter()
.collect::<BTreeMap<_, _>>(),
post_deposit_pool_balance,
"a community pool deposit should be reflected in the visible balance"
);
Expand Down Expand Up @@ -353,7 +365,9 @@ async fn app_can_propose_community_pool_spends() -> anyhow::Result<()> {
// After the proposal passes, we should see the balance decrease by the amount proposed.
assert_eq!(
post_voting_period_pool_balance,
BTreeMap::default(),
[(*STAKING_TOKEN_ASSET_ID, Amount::zero())]
.into_iter()
.collect::<BTreeMap<_, _>>(),
"the successful proposal should decrease the funds of the community pool"
);
assert_eq!(
Expand Down
1 change: 1 addition & 0 deletions crates/core/component/community-pool/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ impl Component for CommunityPool {
match app_state {
Some(genesis) => {
state.put_community_pool_params(genesis.community_pool_params.clone());
state.community_pool_deposit(genesis.initial_balance).await;
erwanor marked this conversation as resolved.
Show resolved Hide resolved
}
None => {}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ impl ActionHandler for CommunityPoolDeposit {
}

async fn check_and_execute<S: StateWrite>(&self, mut state: S) -> Result<()> {
state.community_pool_deposit(self.value).await
Ok(state.community_pool_deposit(self.value).await)
}
}
9 changes: 6 additions & 3 deletions crates/core/component/community-pool/src/component/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,14 @@ pub trait StateWriteExt: StateWrite {
self.put(state_key::community_pool_params().into(), params)
}

async fn community_pool_deposit(&mut self, value: Value) -> Result<()> {
async fn community_pool_deposit(&mut self, value: Value) {
let key = state_key::balance_for_asset(value.asset_id);
let current = self.get(&key).await?.unwrap_or_else(|| Amount::from(0u64));
let current = self
.get(&key)
.await
.expect("no deserialization errors")
.unwrap_or_else(|| Amount::from(0u64));
self.put(key, current + value.amount);
Ok(())
}

async fn community_pool_withdraw(&mut self, value: Value) -> Result<()> {
Expand Down
26 changes: 23 additions & 3 deletions crates/core/component/community-pool/src/genesis.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
use anyhow::Context;
use penumbra_asset::{Value, STAKING_TOKEN_ASSET_ID};
use penumbra_proto::{penumbra::core::component::community_pool::v1 as pb, DomainType};
use serde::{Deserialize, Serialize};

use crate::params::CommunityPoolParameters;

#[derive(Deserialize, Serialize, Debug, Clone, Default)]
#[derive(Deserialize, Serialize, Debug, Clone)]
#[serde(try_from = "pb::GenesisContent", into = "pb::GenesisContent")]
pub struct Content {
/// The initial configuration parameters for the Community Pool component.
pub community_pool_params: CommunityPoolParameters,
/// The initial balance of the Community Pool.
pub initial_balance: Value,
}

impl From<Content> for pb::GenesisContent {
fn from(value: Content) -> Self {
fn from(genesis: Content) -> Self {
pb::GenesisContent {
community_pool_params: Some(value.community_pool_params.into()),
community_pool_params: Some(genesis.community_pool_params.into()),
initial_balance: Some(genesis.initial_balance.into()),
}
}
}
Expand All @@ -24,6 +28,10 @@ impl TryFrom<pb::GenesisContent> for Content {

fn try_from(msg: pb::GenesisContent) -> Result<Self, Self::Error> {
Ok(Content {
initial_balance: msg
.initial_balance
.context("Initial balance not present in protobuf message")?
.try_into()?,
community_pool_params: msg
.community_pool_params
.context("Community Pool params not present in protobuf message")?
Expand All @@ -35,3 +43,15 @@ impl TryFrom<pb::GenesisContent> for Content {
impl DomainType for Content {
type Proto = pb::GenesisContent;
}

impl Default for Content {
fn default() -> Self {
Content {
community_pool_params: CommunityPoolParameters::default(),
initial_balance: Value {
amount: 0u128.into(),
erwanor marked this conversation as resolved.
Show resolved Hide resolved
asset_id: *STAKING_TOKEN_ASSET_ID,
},
}
}
}
2 changes: 1 addition & 1 deletion crates/core/component/funding/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ impl Component for Funding {
amount: reward_amount_for_stream.into(),
asset_id: *STAKING_TOKEN_ASSET_ID,
})
.await?;
.await;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ pub struct GenesisContent {
/// CommunityPool parameters.
#[prost(message, optional, tag = "1")]
pub community_pool_params: ::core::option::Option<CommunityPoolParameters>,
/// The initial balance of the Community Pool.
#[prost(message, optional, tag = "2")]
pub initial_balance: ::core::option::Option<super::super::super::asset::v1::Value>,
}
impl ::prost::Name for GenesisContent {
const NAME: &'static str = "GenesisContent";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,10 +296,16 @@ impl serde::Serialize for GenesisContent {
if self.community_pool_params.is_some() {
len += 1;
}
if self.initial_balance.is_some() {
len += 1;
}
let mut struct_ser = serializer.serialize_struct("penumbra.core.component.community_pool.v1.GenesisContent", len)?;
if let Some(v) = self.community_pool_params.as_ref() {
struct_ser.serialize_field("communityPoolParams", v)?;
}
if let Some(v) = self.initial_balance.as_ref() {
struct_ser.serialize_field("initialBalance", v)?;
}
struct_ser.end()
}
}
Expand All @@ -312,11 +318,14 @@ impl<'de> serde::Deserialize<'de> for GenesisContent {
const FIELDS: &[&str] = &[
"community_pool_params",
"communityPoolParams",
"initial_balance",
"initialBalance",
];

#[allow(clippy::enum_variant_names)]
enum GeneratedField {
CommunityPoolParams,
InitialBalance,
__SkipField__,
}
impl<'de> serde::Deserialize<'de> for GeneratedField {
Expand All @@ -340,6 +349,7 @@ impl<'de> serde::Deserialize<'de> for GenesisContent {
{
match value {
"communityPoolParams" | "community_pool_params" => Ok(GeneratedField::CommunityPoolParams),
"initialBalance" | "initial_balance" => Ok(GeneratedField::InitialBalance),
_ => Ok(GeneratedField::__SkipField__),
}
}
Expand All @@ -360,6 +370,7 @@ impl<'de> serde::Deserialize<'de> for GenesisContent {
V: serde::de::MapAccess<'de>,
{
let mut community_pool_params__ = None;
let mut initial_balance__ = None;
while let Some(k) = map_.next_key()? {
match k {
GeneratedField::CommunityPoolParams => {
Expand All @@ -368,13 +379,20 @@ impl<'de> serde::Deserialize<'de> for GenesisContent {
}
community_pool_params__ = map_.next_value()?;
}
GeneratedField::InitialBalance => {
if initial_balance__.is_some() {
return Err(serde::de::Error::duplicate_field("initialBalance"));
}
initial_balance__ = map_.next_value()?;
}
GeneratedField::__SkipField__ => {
let _ = map_.next_value::<serde::de::IgnoredAny>()?;
}
}
}
Ok(GenesisContent {
community_pool_params: community_pool_params__,
initial_balance: initial_balance__,
})
}
}
Expand Down
Binary file modified crates/proto/src/gen/proto_descriptor.bin.no_lfs
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ message CommunityPoolParameters {
message GenesisContent {
// CommunityPool parameters.
CommunityPoolParameters community_pool_params = 1;
// The initial balance of the Community Pool.
core.asset.v1.Value initial_balance = 2;
}

// Query operations for the community_pool component.
Expand Down
Loading