Skip to content

Commit

Permalink
Merge branch 'main' into support-l2-plus
Browse files Browse the repository at this point in the history
  • Loading branch information
karlem authored Dec 10, 2024
2 parents 63a42f6 + ee04c63 commit 17acf21
Show file tree
Hide file tree
Showing 9 changed files with 151 additions and 9 deletions.
24 changes: 24 additions & 0 deletions contracts/contracts/lib/LibStaking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,18 @@ library LibValidatorSet {
return addresses;
}

function listWaitingValidators(ValidatorSet storage validators) internal view returns (address[] memory addresses) {
uint16 size = validators.waitingValidators.getSize();
addresses = new address[](size);
for (uint16 i = 1; i <= size; ) {
addresses[i - 1] = validators.waitingValidators.getAddress(i);
unchecked {
++i;
}
}
return addresses;
}

/// @notice Get the total collateral of *active* validators.
function getTotalActivePower(ValidatorSet storage validators) internal view returns (uint256 collateral) {
uint16 size = validators.activeValidators.getSize();
Expand Down Expand Up @@ -431,6 +443,18 @@ library LibStaking {
return s.validatorSet.waitingValidators.getSize() + s.validatorSet.activeValidators.getSize();
}

/// @notice Returns all active validators.
function listActiveValidators() internal view returns (address[] memory addresses) {
SubnetActorStorage storage s = LibSubnetActorStorage.appStorage();
return s.validatorSet.listActiveValidators();
}

/// @notice Returns all waiting validators.
function listWaitingValidators() internal view returns (address[] memory addresses) {
SubnetActorStorage storage s = LibSubnetActorStorage.appStorage();
return s.validatorSet.listWaitingValidators();
}

function getTotalConfirmedCollateral() internal view returns (uint256) {
SubnetActorStorage storage s = LibSubnetActorStorage.appStorage();
return s.validatorSet.getTotalConfirmedCollateral();
Expand Down
10 changes: 10 additions & 0 deletions contracts/contracts/subnet/SubnetActorGetterFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,16 @@ contract SubnetActorGetterFacet {
validator = s.validatorSet.validators[validatorAddress];
}

/// @notice Returns detailed information about all active validators.
function getActiveValidators() external view returns (address[] memory) {
return LibStaking.listActiveValidators();
}

/// @notice Returns detailed information about all waiting validators.
function getWaitingValidators() external view returns (address[] memory) {
return LibStaking.listWaitingValidators();
}

/// @notice Returns the total number of validators (active and waiting).
function getTotalValidatorsNumber() external view returns (uint16) {
return LibStaking.totalValidators();
Expand Down
2 changes: 1 addition & 1 deletion contracts/test/helpers/SelectorLibrary.sol
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ library SelectorLibrary {
if (keccak256(abi.encodePacked(facetName)) == keccak256(abi.encodePacked("SubnetActorGetterFacet"))) {
return
abi.decode(
hex"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000203354c3e10000000000000000000000000000000000000000000000000000000035142c8c0000000000000000000000000000000000000000000000000000000006c46853000000000000000000000000000000000000000000000000000000004b27aa72000000000000000000000000000000000000000000000000000000004b0694e200000000000000000000000000000000000000000000000000000000b6797d3c000000000000000000000000000000000000000000000000000000008ef3f76100000000000000000000000000000000000000000000000000000000e02d971b00000000000000000000000000000000000000000000000000000000903e693000000000000000000000000000000000000000000000000000000000948628a900000000000000000000000000000000000000000000000000000000d92e8f1200000000000000000000000000000000000000000000000000000000c7cda762000000000000000000000000000000000000000000000000000000009754b29e0000000000000000000000000000000000000000000000000000000038a210b30000000000000000000000000000000000000000000000000000000080f76021000000000000000000000000000000000000000000000000000000005dd9147c00000000000000000000000000000000000000000000000000000000d6eb591000000000000000000000000000000000000000000000000000000000332a5ac9000000000000000000000000000000000000000000000000000000001597bf7e0000000000000000000000000000000000000000000000000000000052d182d1000000000000000000000000000000000000000000000000000000001904bb2e00000000000000000000000000000000000000000000000000000000cfca28240000000000000000000000000000000000000000000000000000000040550a1c00000000000000000000000000000000000000000000000000000000d081be03000000000000000000000000000000000000000000000000000000001f3a0e410000000000000000000000000000000000000000000000000000000072d0a0e000000000000000000000000000000000000000000000000000000000599c7bd1000000000000000000000000000000000000000000000000000000009e33bd0200000000000000000000000000000000000000000000000000000000c5ab224100000000000000000000000000000000000000000000000000000000f0cf6c9600000000000000000000000000000000000000000000000000000000ad81e4d60000000000000000000000000000000000000000000000000000000080875df700000000000000000000000000000000000000000000000000000000",
hex"000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000223354c3e10000000000000000000000000000000000000000000000000000000035142c8c0000000000000000000000000000000000000000000000000000000006c46853000000000000000000000000000000000000000000000000000000004b27aa72000000000000000000000000000000000000000000000000000000004b0694e200000000000000000000000000000000000000000000000000000000b6797d3c000000000000000000000000000000000000000000000000000000008ef3f76100000000000000000000000000000000000000000000000000000000e02d971b00000000000000000000000000000000000000000000000000000000903e693000000000000000000000000000000000000000000000000000000000948628a900000000000000000000000000000000000000000000000000000000d92e8f12000000000000000000000000000000000000000000000000000000009de7025800000000000000000000000000000000000000000000000000000000c7cda762000000000000000000000000000000000000000000000000000000009754b29e0000000000000000000000000000000000000000000000000000000038a210b30000000000000000000000000000000000000000000000000000000080f76021000000000000000000000000000000000000000000000000000000005dd9147c00000000000000000000000000000000000000000000000000000000d6eb591000000000000000000000000000000000000000000000000000000000332a5ac9000000000000000000000000000000000000000000000000000000001597bf7e0000000000000000000000000000000000000000000000000000000052d182d1000000000000000000000000000000000000000000000000000000001904bb2e000000000000000000000000000000000000000000000000000000006ad04c7900000000000000000000000000000000000000000000000000000000cfca28240000000000000000000000000000000000000000000000000000000040550a1c00000000000000000000000000000000000000000000000000000000d081be03000000000000000000000000000000000000000000000000000000001f3a0e410000000000000000000000000000000000000000000000000000000072d0a0e000000000000000000000000000000000000000000000000000000000599c7bd1000000000000000000000000000000000000000000000000000000009e33bd0200000000000000000000000000000000000000000000000000000000c5ab224100000000000000000000000000000000000000000000000000000000f0cf6c9600000000000000000000000000000000000000000000000000000000ad81e4d60000000000000000000000000000000000000000000000000000000080875df700000000000000000000000000000000000000000000000000000000",
(bytes4[])
);
}
Expand Down
9 changes: 8 additions & 1 deletion contracts/test/integration/SubnetActorDiamond.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase {
require(saDiamond.getter().bottomUpCheckPeriod() == params.bottomUpCheckPeriod, "unexpected bottom-up period");
require(saDiamond.getter().majorityPercentage() == params.majorityPercentage, "unexpected majority percentage");
require(saDiamond.getter().getParent().toHash() == _parentId.toHash(), "unexpected parent subnetID hash");
require(saDiamond.getter().genesisValidators().length == 0, "unexpected genesis validators");
require(saDiamond.getter().getActiveValidators().length == 0, "unexpected active validators");
require(saDiamond.getter().getWaitingValidators().length == 0, "unexpected waiting validators");
}

function testSubnetActorDiamondReal_LoupeFunction() public view {
Expand Down Expand Up @@ -137,7 +140,9 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase {
TestUtils.ensureBytesEqual(v.metadata, publicKey1);
require(saDiamond.getter().bootstrapped(), "subnet not bootstrapped");
require(!saDiamond.getter().killed(), "subnet killed");
require(saDiamond.getter().genesisValidators().length == 1, "not one validator in genesis");
require(saDiamond.getter().genesisValidators().length == 1, "not 1 genesis validator");
require(saDiamond.getter().getActiveValidators().length == 1, "not 1 active validator");
require(saDiamond.getter().getWaitingValidators().length == 0, "not 0 waiting validator");

(uint64 nextConfigNum, uint64 startConfigNum) = saDiamond.getter().getConfigurationNumbers();
require(nextConfigNum == LibStaking.INITIAL_CONFIGURATION_NUMBER, "next config num not 1");
Expand Down Expand Up @@ -183,6 +188,8 @@ contract SubnetActorDiamondTest is Test, IntegrationTestBase {
require(!saDiamond.getter().isWaitingValidator(validator1), "waiting validator1");
require(saDiamond.getter().isActiveValidator(validator2), "not active validator2");
require(!saDiamond.getter().isWaitingValidator(validator2), "waiting validator2");
require(saDiamond.getter().getActiveValidators().length == 2, "not 2 active validators");
require(saDiamond.getter().getWaitingValidators().length == 0, "not 0 waiting validators");

(nextConfigNum, startConfigNum) = saDiamond.getter().getConfigurationNumbers();
require(
Expand Down
42 changes: 42 additions & 0 deletions ipc/cli/src/commands/subnet/list_validators.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright 2022-2024 Protocol Labs
// SPDX-License-Identifier: MIT
//! List subnets cli command
use crate::{get_ipc_provider, CommandLineHandler, GlobalArguments};
use async_trait::async_trait;
use clap::Args;
use ipc_api::subnet_id::SubnetID;
use std::fmt::Debug;
use std::str::FromStr;

/// The command to create a new subnet actor.
pub(crate) struct ListValidators;

#[async_trait]
impl CommandLineHandler for ListValidators {
type Arguments = ListValidatorsArgs;

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

let provider = get_ipc_provider(global)?;
let subnet = SubnetID::from_str(&arguments.subnet)?;

let validators = provider.list_validators(&subnet).await?;

for (addr, info) in validators {
println!("{}: {}", addr, info);
}
Ok(())
}
}

#[derive(Debug, Args)]
#[command(
name = "list validators",
about = "List the info of all the validators in the subnet, as viewed by the parent"
)]
pub(crate) struct ListValidatorsArgs {
#[arg(long, help = "The target subnet to perform query")]
pub subnet: String,
}
13 changes: 8 additions & 5 deletions ipc/cli/src/commands/subnet/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
// Copyright 2022-2024 Protocol Labs
// SPDX-License-Identifier: MIT

use self::bootstrap::{AddBootstrap, AddBootstrapArgs, ListBootstraps, ListBootstrapsArgs};
use self::join::{StakeSubnet, StakeSubnetArgs, UnstakeSubnet, UnstakeSubnetArgs};
use self::leave::{Claim, ClaimArgs};
use self::rpc::{ChainIdSubnet, ChainIdSubnetArgs};
pub use crate::commands::subnet::create::{CreateSubnet, CreateSubnetArgs};
use crate::commands::subnet::genesis_epoch::{GenesisEpoch, GenesisEpochArgs};
pub use crate::commands::subnet::join::{JoinSubnet, JoinSubnetArgs};
pub use crate::commands::subnet::kill::{KillSubnet, KillSubnetArgs};
pub use crate::commands::subnet::leave::{LeaveSubnet, LeaveSubnetArgs};
use crate::commands::subnet::list_subnets::{ListSubnets, ListSubnetsArgs};
use crate::commands::subnet::list_validators::{ListValidators, ListValidatorsArgs};
use crate::commands::subnet::rpc::{RPCSubnet, RPCSubnetArgs};
use crate::commands::subnet::send_value::{SendValue, SendValueArgs};
use crate::commands::subnet::set_federated_power::{SetFederatedPower, SetFederatedPowerArgs};
Expand All @@ -17,18 +22,14 @@ use crate::commands::subnet::validator::{ValidatorInfo, ValidatorInfoArgs};
use crate::{CommandLineHandler, GlobalArguments};
use clap::{Args, Subcommand};

use self::bootstrap::{AddBootstrap, AddBootstrapArgs, ListBootstraps, ListBootstrapsArgs};
use self::join::{StakeSubnet, StakeSubnetArgs, UnstakeSubnet, UnstakeSubnetArgs};
use self::leave::{Claim, ClaimArgs};
use self::rpc::{ChainIdSubnet, ChainIdSubnetArgs};

pub mod bootstrap;
pub mod create;
mod genesis_epoch;
pub mod join;
pub mod kill;
pub mod leave;
pub mod list_subnets;
pub mod list_validators;
pub mod rpc;
pub mod send_value;
mod set_federated_power;
Expand All @@ -53,6 +54,7 @@ impl SubnetCommandsArgs {
match &self.command {
Commands::Create(args) => CreateSubnet::handle(global, args).await,
Commands::List(args) => ListSubnets::handle(global, args).await,
Commands::ListValidators(args) => ListValidators::handle(global, args).await,
Commands::Join(args) => JoinSubnet::handle(global, args).await,
Commands::Rpc(args) => RPCSubnet::handle(global, args).await,
Commands::ChainId(args) => ChainIdSubnet::handle(global, args).await,
Expand All @@ -78,6 +80,7 @@ impl SubnetCommandsArgs {
pub(crate) enum Commands {
Create(CreateSubnetArgs),
List(ListSubnetsArgs),
ListValidators(ListValidatorsArgs),
Join(JoinSubnetArgs),
Rpc(RPCSubnetArgs),
ChainId(ChainIdSubnetArgs),
Expand Down
10 changes: 10 additions & 0 deletions ipc/provider/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,16 @@ impl IpcProvider {
conn.manager().get_validator_info(subnet, validator).await
}

pub async fn list_validators(
&self,
subnet: &SubnetID,
) -> anyhow::Result<Vec<(Address, ValidatorInfo)>> {
let parent = subnet.parent().ok_or_else(|| anyhow!("no parent found"))?;
let conn = self.get_connection(&parent)?;

conn.manager().list_validators(subnet).await
}

/// Get the changes in subnet validators. This is fetched from parent.
pub async fn get_validator_changeset(
&self,
Expand Down
44 changes: 44 additions & 0 deletions ipc/provider/src/manager/evm/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,50 @@ impl SubnetManager for EthSubnetManager {
})
}

async fn list_validators(&self, subnet: &SubnetID) -> Result<Vec<(Address, ValidatorInfo)>> {
let address = contract_address_from_subnet(subnet)?;
let contract = subnet_actor_getter_facet::SubnetActorGetterFacet::new(
address,
Arc::new(self.ipc_contract_info.provider.clone()),
);

let mut addresses: Vec<Address> = vec![];
let mut validators: Vec<ValidatorInfo> = vec![];

let active = contract.get_active_validators().call().await?;
addresses.extend(
active
.iter()
.map(ethers_address_to_fil_address)
.collect::<Result<Vec<_>, _>>()?,
);
for addr in active {
let info = contract.get_validator(addr).call().await?;
validators.push(ValidatorInfo {
staking: ValidatorStakingInfo::try_from(info)?,
is_active: true,
is_waiting: false,
});
}
let waiting = contract.get_waiting_validators().call().await?;
addresses.extend(
waiting
.iter()
.map(ethers_address_to_fil_address)
.collect::<Result<Vec<_>, _>>()?,
);
for addr in waiting {
let info = contract.get_validator(addr).call().await?;
validators.push(ValidatorInfo {
staking: ValidatorStakingInfo::try_from(info)?,
is_active: false,
is_waiting: true,
});
}

Ok(addresses.into_iter().zip(validators).collect())
}

async fn set_federated_power(
&self,
from: &Address,
Expand Down
6 changes: 4 additions & 2 deletions ipc/provider/src/manager/subnet.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// Copyright 2022-2024 Protocol Labs
// SPDX-License-Identifier: MIT

use std::collections::{BTreeMap, HashMap};

use anyhow::Result;
use async_trait::async_trait;
use fvm_shared::clock::ChainEpoch;
Expand All @@ -17,6 +15,7 @@ use ipc_api::staking::{StakingChangeRequest, ValidatorInfo};
use ipc_api::subnet::{Asset, ConstructParams, PermissionMode};
use ipc_api::subnet_id::SubnetID;
use ipc_api::validator::Validator;
use std::collections::{BTreeMap, HashMap};

use crate::lotus::message::ipc::SubnetInfo;

Expand Down Expand Up @@ -182,6 +181,9 @@ pub trait SubnetManager:
validator: &Address,
) -> Result<ValidatorInfo>;

/// Lists all the validators
async fn list_validators(&self, subnet: &SubnetID) -> Result<Vec<(Address, ValidatorInfo)>>;

async fn set_federated_power(
&self,
from: &Address,
Expand Down

0 comments on commit 17acf21

Please sign in to comment.