Skip to content
This repository has been archived by the owner on Jan 11, 2024. It is now read-only.

Commit

Permalink
IPC-347: add pre-fund command and genesis balances in GenesisInfo call
Browse files Browse the repository at this point in the history
  • Loading branch information
adlrocha committed Nov 1, 2023
1 parent 65e92a3 commit a41ac21
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 8 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
[workspace]
resolver = "2"
members = [
# "ipc/daemon",
# "ipc/daemon",
"ipc/cli",
# "ipc/testing/e2e",
# "ipc/testing/e2e",
# "ipc/testing/*",
"ipc/provider",
"ipc/identity",
"ipc/identity",
"ipc/sdk"
]

Expand Down Expand Up @@ -42,7 +42,7 @@ hex = "0.4.3"
tempfile = "3.4.0"
serde_json = { version = "1.0.91", features = ["raw_value"] }

ipc_actors_abis = { git = "https://github.com/consensus-shipyard/ipc-solidity-actors.git", branch = "dev" }
ipc_actors_abis = { git = "https://github.com/consensus-shipyard/ipc-solidity-actors.git", branch = "fm-347-subnet-prefund" }

libipld = { version = "0.14", default-features = false, features = ["dag-cbor"] }
libsecp256k1 = "0.7"
Expand Down
59 changes: 58 additions & 1 deletion ipc/cli/src/commands/subnet/join.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ impl CommandLineHandler for JoinSubnet {
None => None,
};
let public_key = hex::decode(&arguments.public_key)?;
if let Some(initial_balance) = arguments.initial_balance {
println!("pre-funding address with {initial_balance}");
provider
.prefund_subnet(
subnet.clone(),
from,
f64_to_token_amount(initial_balance.clone())?,
)
.await?;
}
let epoch = provider
.join_subnet(
subnet,
Expand All @@ -37,7 +47,7 @@ impl CommandLineHandler for JoinSubnet {
public_key,
)
.await?;
log::info!("joined at epoch: {epoch}");
println!("joined at epoch: {epoch}");

Ok(())
}
Expand All @@ -58,6 +68,11 @@ pub struct JoinSubnetArgs {
pub collateral: f64,
#[arg(long, short, help = "The validator's metadata, hex encoded")]
pub public_key: String,
#[arg(
long,
help = "Optionally add an initial balance to the validator in genesis in the subnet"
)]
pub initial_balance: Option<f64>,
}

/// The command to stake in a subnet from validator
Expand Down Expand Up @@ -136,3 +151,45 @@ pub struct UnstakeSubnetArgs {
)]
pub collateral: f64,
}

pub struct PreFundSubnet;

#[async_trait]
impl CommandLineHandler for PreFundSubnet {
type Arguments = PreFundSubnetArgs;

async fn handle(global: &GlobalArguments, arguments: &Self::Arguments) -> anyhow::Result<()> {
log::debug!("pre-fund subnet with args: {:?}", arguments);

let mut provider = get_ipc_provider(global)?;
let subnet = SubnetID::from_str(&arguments.subnet)?;
let from = match &arguments.from {
Some(address) => Some(require_fil_addr_from_str(address)?),
None => None,
};
provider
.prefund_subnet(
subnet.clone(),
from,
f64_to_token_amount(arguments.initial_balance)?,
)
.await?;
println!("address pre-funded successfully");

Ok(())
}
}

#[derive(Debug, Args)]
#[command(
name = "pre-fund",
about = "Pre fund with some funds in genesis in a child-subnet"
)]
pub struct PreFundSubnetArgs {
#[arg(long, short, help = "The address funded in the subnet")]
pub from: Option<String>,
#[arg(long, short, help = "The subnet to add balance to")]
pub subnet: String,
#[arg(help = "Optionally add an initial balance to the validator in genesis in the subnet")]
pub initial_balance: f64,
}
18 changes: 18 additions & 0 deletions ipc/provider/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,24 @@ impl IpcProvider {
.await
}

pub async fn prefund_subnet(
&mut self,
subnet: SubnetID,
from: Option<Address>,
balance: TokenAmount,
) -> anyhow::Result<()> {
let parent = subnet.parent().ok_or_else(|| anyhow!("no parent found"))?;
let conn = match self.connection(&parent) {
None => return Err(anyhow!("target parent subnet not found")),
Some(conn) => conn,
};

let subnet_config = conn.subnet();
let sender = self.check_sender(subnet_config, from)?;

conn.manager().pre_fund(subnet, sender, balance).await
}

pub async fn stake(
&mut self,
subnet: SubnetID,
Expand Down
36 changes: 36 additions & 0 deletions ipc/provider/src/manager/evm/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,27 @@ impl SubnetManager for EthSubnetManager {
block_number_from_receipt(receipt)
}

async fn pre_fund(&self, subnet: SubnetID, from: Address, balance: TokenAmount) -> Result<()> {
let balance = balance
.atto()
.to_u128()
.ok_or_else(|| anyhow!("invalid min validator stake"))?;

let address = contract_address_from_subnet(&subnet)?;
log::info!("interacting with evm subnet contract: {address:} with balance: {balance:}");

let signer = Arc::new(self.get_signer(&from)?);
let contract =
subnet_actor_manager_facet::SubnetActorManagerFacet::new(address, signer.clone());

let mut txn = contract.pre_fund();
txn.tx.set_value(balance);
let txn = call_with_premium_estimation(signer, txn).await?;

txn.send().await?;
Ok(())
}

async fn stake(&self, subnet: SubnetID, from: Address, collateral: TokenAmount) -> Result<()> {
let collateral = collateral
.atto()
Expand Down Expand Up @@ -642,6 +663,9 @@ impl SubnetManager for EthSubnetManager {
address,
Arc::new(self.ipc_contract_info.provider.clone()),
);

let genesis_balances = contract.genesis_balances().await?;

Ok(SubnetGenesisInfo {
// Active validators limit set for the child subnet.
active_validators_limit: contract.active_validators_limit().call().await?,
Expand All @@ -656,6 +680,7 @@ impl SubnetManager for EthSubnetManager {
// Custom message fee that the child subnet wants to set for cross-net messages
msg_fee: eth_to_fil_amount(&contract.min_cross_msg_fee().call().await?)?,
validators: from_contract_validators(contract.genesis_validators().call().await?)?,
genesis_balances: into_genesis_balance_map(genesis_balances.0, genesis_balances.1)?,
})
}

Expand Down Expand Up @@ -1162,6 +1187,17 @@ fn is_valid_bootstrap_addr(input: &str) -> Option<(String, IpAddr, u16)> {
None
}

fn into_genesis_balance_map(
addrs: Vec<ethers::types::Address>,
balances: Vec<ethers::types::U256>,
) -> Result<HashMap<Address, TokenAmount>> {
let mut map = HashMap::new();
for (a, b) in addrs.into_iter().zip(balances) {
map.insert(ethers_address_to_fil_address(&a)?, eth_to_fil_amount(&b)?);
}
Ok(map)
}

/// Convert the ipc SubnetID type to an evm address. It extracts the last address from the Subnet id
/// children and turns it into evm address.
pub(crate) fn contract_address_from_subnet(subnet: &SubnetID) -> Result<ethers::types::Address> {
Expand Down
9 changes: 7 additions & 2 deletions ipc/provider/src/manager/subnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,16 @@ pub trait SubnetManager: Send + Sync + TopDownCheckpointQuery + BottomUpCheckpoi
metadata: Vec<u8>,
) -> Result<ChainEpoch>;

/// Adds some initial balance to an address before a child subnet bootstraps to make
/// it available in the subnet at genesis.
async fn pre_fund(&self, subnet: SubnetID, from: Address, balance: TokenAmount) -> Result<()>;

/// Allows validators that have already joined the subnet to stake more collateral
/// and increase their power in the subnet
/// and increase their power in the subnet.
async fn stake(&self, subnet: SubnetID, from: Address, collateral: TokenAmount) -> Result<()>;

/// Allows validators that have already joined the subnet to unstake collateral
/// and reduce their power in the subnet
/// and reduce their power in the subnet.
async fn unstake(&self, subnet: SubnetID, from: Address, collateral: TokenAmount)
-> Result<()>;

Expand Down Expand Up @@ -142,6 +146,7 @@ pub struct SubnetGenesisInfo {
pub min_collateral: TokenAmount,
pub genesis_epoch: ChainEpoch,
pub validators: Vec<Validator>,
pub genesis_balances: HashMap<Address, TokenAmount>,
}

/// The generic payload that returns the block hash of the data returning block with the actual
Expand Down

0 comments on commit a41ac21

Please sign in to comment.