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

fix(node): skip power scale if not collateral based #1149

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
7 changes: 4 additions & 3 deletions fendermint/app/options/src/genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@ pub struct GenesisFromParentArgs {
#[arg(long, short = 'f', value_parser = parse_token_amount, default_value = "1000")]
pub base_fee: TokenAmount,

/// Number of decimals to use during converting FIL to Power.
#[arg(long, default_value = "3")]
pub power_scale: i8,
/// Number of decimals to use during converting FIL to Power. Only configurable if the subnet
/// is collateral based.
#[arg(long, default_value = "Some(3)")]
pub power_scale: Option<i8>,
}
18 changes: 15 additions & 3 deletions fendermint/app/src/cmd/genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@
use anyhow::{anyhow, Context};
use fendermint_crypto::PublicKey;
use fvm_shared::address::Address;
use fvm_shared::econ::TokenAmount;
use ipc_provider::config::subnet::{EVMSubnet, SubnetConfig};
use ipc_provider::IpcProvider;
use std::path::PathBuf;

use fendermint_vm_actor_interface::eam::EthAddress;
use fendermint_vm_core::{chainid, Timestamp};
use fendermint_vm_genesis::{
ipc, Account, Actor, ActorMeta, Collateral, Genesis, Multisig, PermissionMode, SignerAddr,
Validator, ValidatorKey,
ipc, Account, Actor, ActorMeta, Collateral, Genesis, Multisig, PermissionMode, PowerScale,
SignerAddr, Validator, ValidatorKey,
};
use fendermint_vm_interpreter::genesis::{GenesisAppState, GenesisBuilder};

Expand All @@ -21,6 +22,8 @@ use crate::options::genesis::*;

use super::key::read_public_key;

const DEFAULT_POWER_SCALE: PowerScale = 3;

cmd! {
GenesisArgs(self) {
let genesis_file = self.genesis_file.clone();
Expand Down Expand Up @@ -329,6 +332,15 @@ async fn new_genesis_from_parent(

let genesis_info = parent_provider.get_genesis_info(&args.subnet_id).await?;

let power_scale = if matches!(
genesis_info.permission_mode,
ipc_api::subnet::PermissionMode::Collateral
) {
args.power_scale.unwrap_or(DEFAULT_POWER_SCALE)
} else {
TokenAmount::DECIMALS as PowerScale
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will this be the value we put in set-federated-power? that would be great if so!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cryptoAtwill shouldn't this be 1? We want X federated power to translate directly into X weight, right? Having 18 here would force users to append 18 zeroes to whatever power they actually want to see in the subnet?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's a subtraction here:

d if d >= 0 => TokenAmount::DECIMALS.saturating_sub(d as usize) as u32,

};

// get gateway genesis
let ipc_params = ipc::IpcParams {
gateway: ipc::GatewayParams {
Expand All @@ -347,7 +359,7 @@ async fn new_genesis_from_parent(
chain_name: args.subnet_id.to_string(),
network_version: args.network_version,
base_fee: args.base_fee.clone(),
power_scale: args.power_scale,
power_scale,
validators: Vec::new(),
accounts: Vec::new(),
eam_permission_mode: PermissionMode::Unrestricted,
Expand Down
9 changes: 8 additions & 1 deletion fendermint/vm/genesis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ mod tests {
use num_traits::Num;
use quickcheck_macros::quickcheck;

use crate::{Collateral, Genesis};
use crate::{Collateral, Genesis, PowerScale};

#[quickcheck]
fn genesis_json(value0: Genesis) {
Expand Down Expand Up @@ -299,6 +299,13 @@ mod tests {
}
}

#[test]
fn power_scale_18_decimals() {
let c = Collateral(TokenAmount::from_atto(1000));
let p = c.into_power(TokenAmount::DECIMALS as PowerScale);
assert_eq!(p.0, 1000);
}

#[test]
fn atto_per_power() {
// Collateral given in atto (18 digits after the decimal)
Expand Down
58 changes: 48 additions & 10 deletions fendermint/vm/interpreter/src/fvm/state/ipc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ impl<DB: Blockstore + Clone> GatewayCaller<DB> {
.current_membership(state)
.context("failed to get current membership")?;

let power_table = membership_to_power_table(&membership, state.power_scale());
let power_table = membership_to_power_table(&membership, state.power_scale())?;

Ok((membership.configuration_number, power_table))
}
Expand Down Expand Up @@ -351,19 +351,57 @@ pub fn tokens_to_burn(msgs: &[checkpointing_facet::IpcEnvelope]) -> TokenAmount
fn membership_to_power_table(
m: &gateway_getter_facet::Membership,
power_scale: PowerScale,
) -> Vec<Validator<Power>> {
) -> anyhow::Result<Vec<Validator<Power>>> {
let mut pt = Vec::new();

for v in m.validators.iter() {
// Ignoring any metadata that isn't a public key.
if let Ok(pk) = PublicKey::parse_slice(&v.metadata, None) {
let c = from_eth::to_fvm_tokens(&v.weight);
pt.push(Validator {
public_key: ValidatorKey(pk),
power: Collateral(c).into_power(power_scale),
})
}
let Ok(pk) = PublicKey::parse_slice(&v.metadata, None) else {
return Err(anyhow!(
"metadata not correct public key: {}",
hex::encode(&v.metadata)
));
};

let c = from_eth::to_fvm_tokens(&v.weight);
pt.push(Validator {
public_key: ValidatorKey(pk),
power: Collateral(c).into_power(power_scale),
})
}

pt
Ok(pt)
}

#[cfg(test)]
mod tests {
use crate::fvm::state::ipc::membership_to_power_table;
use fendermint_vm_genesis::PowerScale;
use fvm_shared::econ::TokenAmount;
use ipc_actors_abis::gateway_getter_facet::gateway_getter_facet;
use std::str::FromStr;

#[test]
fn test_membership_to_power_table() {
let m = gateway_getter_facet::Membership {
configuration_number: 4,
validators: vec![
gateway_getter_facet::Validator {
weight: ethers::types::U256::from(1),
addr: ethers::types::Address::from_str("0x489Ee71B9E8eDEabB30eBA1b09De783Ee9B85F6B").unwrap(),
metadata: ethers::types::Bytes::from_str("0x0485ff6016b937c0cec4f77cc452d250901aa8ff601faba7f4153a34c94ef9cdd8305e9432be8f94036d243dc1d8d5d0526d656ad179d252cf4dfdb49c78c47c65").unwrap(),
},
gateway_getter_facet::Validator {
weight: ethers::types::U256::from(1000),
addr: ethers::types::Address::from_str("0x0b18D28e32B2A24e003769960e4F3E262b176399").unwrap(),
metadata: ethers::types::Bytes::from_str("0x0485ff6016b937c0cec4f77cc452d250901aa8ff601faba7f4153a34c94ef9cdd8305e9432be8f94036d243dc1d8d5d0526d656ad179d252cf4dfdb49c78c47c65").unwrap(),
},
],
};

let v = membership_to_power_table(&m, TokenAmount::DECIMALS as PowerScale).unwrap();

assert_eq!(v[0].power.0, 1);
assert_eq!(v[1].power.0, 1000);
}
}
14 changes: 14 additions & 0 deletions ipc/api/src/subnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
/// However, we should either deprecate the native actors, or make
/// them use the types from this sdk directly.
use crate::subnet_id::SubnetID;
use anyhow::anyhow;
use fvm_ipld_encoding::repr::*;
use fvm_shared::{address::Address, clock::ChainEpoch, econ::TokenAmount};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -96,3 +97,16 @@ pub struct ConstructParams {
pub enum ConsensusType {
Fendermint,
}

impl TryFrom<u8> for PermissionMode {
type Error = anyhow::Error;

fn try_from(value: u8) -> Result<Self, Self::Error> {
Ok(match value {
0 => PermissionMode::Collateral,
1 => PermissionMode::Federated,
2 => PermissionMode::Static,
_ => return Err(anyhow!("unknown power permission mode")),
})
}
}
5 changes: 3 additions & 2 deletions ipc/provider/src/manager/evm/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,8 @@ impl SubnetManager for EthSubnetManager {

let genesis_balances = contract.genesis_balances().await?;
let bottom_up_checkpoint_period = contract.bottom_up_check_period().call().await?.as_u64();
let permission_mode =
PermissionMode::try_from(contract.permission_mode().call().await? as u8)?;

Ok(SubnetGenesisInfo {
// Active validators limit set for the child subnet.
Expand All @@ -809,8 +811,7 @@ impl SubnetManager for EthSubnetManager {
// Custom message fee that the child subnet wants to set for cross-net messages
validators: from_contract_validators(contract.genesis_validators().call().await?)?,
genesis_balances: into_genesis_balance_map(genesis_balances.0, genesis_balances.1)?,
// TODO: fixme https://github.com/consensus-shipyard/ipc-monorepo/issues/496
permission_mode: PermissionMode::Collateral,
permission_mode,
supply_source: Asset {
kind: AssetKind::Native,
token_address: None,
Expand Down
Loading