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

feat: solana chain tracking events #5195

Merged
merged 3 commits into from
Aug 24, 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
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ where
BitcoinChainTracking(_) |
PolkadotChainTracking(_) |
ArbitrumChainTracking(_) |
SolanaChainTracking(_) |
EthereumVault(_) |
PolkadotVault(_) |
BitcoinVault(_) |
Expand Down
33 changes: 18 additions & 15 deletions state-chain/cf-integration-tests/src/mock_runtime.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
use cf_chains::{
arb::ArbitrumTrackedData,
btc::{BitcoinFeeInfo, BitcoinTrackedData},
dot::{PolkadotTrackedData, RuntimeVersion},
eth::EthereumTrackedData,
sol::{sol_tx_core::sol_test_values, SolTrackedData},
Arbitrum, Bitcoin, ChainState, Ethereum, Polkadot, Solana,
};
use chainflip_node::{
chain_spec::testnet::{EXPIRY_SPAN_IN_SECONDS, REDEMPTION_TTL_SECS},
test_account_from_seed,
Expand All @@ -16,21 +24,10 @@ use state_chain_runtime::{
opaque::SessionKeys,
test_runner::*,
AccountId, AccountRolesConfig, ArbitrumChainTrackingConfig, ArbitrumVaultConfig,
EmissionsConfig, EthereumVaultConfig, EvmThresholdSignerConfig, FlipConfig, FundingConfig,
GovernanceConfig, ReputationConfig, SessionConfig, SolanaElectionsConfig, SolanaVaultConfig,
ValidatorConfig,
};

use cf_chains::{
arb::ArbitrumTrackedData,
btc::{BitcoinFeeInfo, BitcoinTrackedData},
dot::{PolkadotTrackedData, RuntimeVersion},
eth::EthereumTrackedData,
sol::sol_tx_core::sol_test_values,
Arbitrum, Bitcoin, ChainState, Ethereum, Polkadot,
};
use state_chain_runtime::{
BitcoinChainTrackingConfig, EthereumChainTrackingConfig, PolkadotChainTrackingConfig,
BitcoinChainTrackingConfig, EmissionsConfig, EthereumChainTrackingConfig, EthereumVaultConfig,
EvmThresholdSignerConfig, FlipConfig, FundingConfig, GovernanceConfig,
PolkadotChainTrackingConfig, ReputationConfig, SessionConfig, SolanaChainTrackingConfig,
SolanaElectionsConfig, SolanaVaultConfig, ValidatorConfig,
};

pub const CURRENT_AUTHORITY_EMISSION_INFLATION_PERBILL: u32 = 28;
Expand Down Expand Up @@ -265,6 +262,12 @@ impl ExtBuilder {
},
},
},
solana_chain_tracking: SolanaChainTrackingConfig {
init_chain_state: ChainState::<Solana> {
block_height: 0,
tracked_data: SolTrackedData { priority_fee: COMPUTE_PRICE },
},
},
bitcoin_threshold_signer: Default::default(),
evm_threshold_signer: EvmThresholdSignerConfig {
key: Some(ethereum_vault_key),
Expand Down
11 changes: 9 additions & 2 deletions state-chain/node/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ use cf_chains::{
btc::{BitcoinFeeInfo, BitcoinTrackedData, BITCOIN_DUST_LIMIT},
dot::{PolkadotAccountId, PolkadotHash, PolkadotTrackedData, RuntimeVersion},
eth::EthereumTrackedData,
sol::{api::DurableNonceAndAccount, SolAddress, SolApiEnvironment, SolHash},
sol::{api::DurableNonceAndAccount, SolAddress, SolApiEnvironment, SolHash, SolTrackedData},
Arbitrum, Bitcoin, ChainState, Ethereum, Polkadot,
};
use cf_primitives::{
AccountRole, AuthorityCount, NetworkEnvironment, DEFAULT_MAX_AUTHORITY_SET_CONTRACTION,
chains::Solana, AccountRole, AuthorityCount, NetworkEnvironment,
DEFAULT_MAX_AUTHORITY_SET_CONTRACTION,
};
use common::FLIPPERINOS_PER_FLIP;
pub use sc_service::{ChainType, Properties};
Expand Down Expand Up @@ -792,6 +793,12 @@ fn testnet_genesis(
},
},
},
solana_chain_tracking: state_chain_runtime::SolanaChainTrackingConfig {
init_chain_state: ChainState::<Solana> {
block_height: 0,
tracked_data: SolTrackedData { priority_fee: 100_000 },
},
},
// Channel lifetimes are set to ~2 hours at average block times.
bitcoin_ingress_egress: state_chain_runtime::BitcoinIngressEgressConfig {
deposit_channel_lifetime: bitcoin_deposit_channel_lifetime.into(),
Expand Down
36 changes: 23 additions & 13 deletions state-chain/pallets/cf-chain-tracking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,19 +136,8 @@ pub mod pallet {
<T::TargetChain as Chain>::is_block_witness_root(new_chain_state.block_height),
Error::<T, I>::InvalidBlockHeight
);
CurrentChainState::<T, I>::try_mutate::<_, Error<T, I>, _>(|previous_chain_state| {
ensure!(
new_chain_state.block_height >
previous_chain_state.as_ref().expect(NO_CHAIN_STATE).block_height,
Error::<T, I>::StaleDataSubmitted
);
*previous_chain_state = Some(new_chain_state.clone());

Ok(())
})?;
Self::deposit_event(Event::<T, I>::ChainStateUpdated { new_chain_state });

Ok(().into())

Self::inner_update_chain_state(new_chain_state)
}

/// Update the fee multiplier with the provided value
Expand All @@ -170,6 +159,27 @@ pub mod pallet {
}
}

impl<T: Config<I>, I: 'static> Pallet<T, I> {
pub fn inner_update_chain_state(
new_chain_state: ChainState<T::TargetChain>,
) -> DispatchResultWithPostInfo {
CurrentChainState::<T, I>::try_mutate::<_, Error<T, I>, _>(|previous_chain_state| {
ensure!(
new_chain_state.block_height >
previous_chain_state.as_ref().expect(NO_CHAIN_STATE).block_height,
Error::<T, I>::StaleDataSubmitted
);
*previous_chain_state = Some(new_chain_state.clone());

Ok(())
})?;

Self::deposit_event(Event::<T, I>::ChainStateUpdated { new_chain_state });

Ok(().into())
}
}

impl<T: Config<I>, I: 'static> GetBlockHeight<T::TargetChain> for Pallet<T, I> {
fn get_block_height() -> <T::TargetChain as Chain>::ChainBlockNumber {
CurrentChainState::<T, I>::get().expect(NO_CHAIN_STATE).block_height
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ use frame_support::{
use itertools::Itertools;
use sp_std::vec::Vec;

pub trait MedianChangeHook<Value> {
fn on_change(value: Value);
}

/// This electoral system is for tracking a monotonically increasing `Value` that authorities may
/// not have the same view of, i.e. they may see slightly different values. It calculates a median
/// of all the authority votes and stores the latest median in the `ElectoralUnsynchronisedState`,
Expand All @@ -26,13 +30,14 @@ use sp_std::vec::Vec;
///
/// `Settings` can be used by governance to provide information to authorities about exactly how
/// they should `vote`.
pub struct MonotonicMedian<Value, Settings> {
_phantom: core::marker::PhantomData<(Value, Settings)>,
pub struct MonotonicMedian<Value, Settings, Hook> {
_phantom: core::marker::PhantomData<(Value, Settings, Hook)>,
}
impl<
Value: MaybeSerializeDeserialize + Member + Parameter + Ord,
Settings: Member + Parameter + MaybeSerializeDeserialize + Eq,
> ElectoralSystem for MonotonicMedian<Value, Settings>
Hook: MedianChangeHook<Value> + 'static,
> ElectoralSystem for MonotonicMedian<Value, Settings, Hook>
{
type ElectoralUnsynchronisedState = Value;
type ElectoralUnsynchronisedStateMapKey = ();
Expand Down Expand Up @@ -70,6 +75,7 @@ impl<
let mut election_access = electoral_access.election_mut(election_identifier)?;
if let Some(consensus) = election_access.check_consensus()?.has_consensus() {
election_access.delete();
Hook::on_change(consensus.clone());
electoral_access.new_election((), (), ())?;
electoral_access.mutate_unsynchronised_state(
|_electoral_access, unsynchronised_state| {
Expand Down
6 changes: 3 additions & 3 deletions state-chain/runtime/src/chainflip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ use crate::{
BitcoinThresholdSigner, BlockNumber, Emissions, Environment, EthereumBroadcaster,
EthereumChainTracking, EthereumIngressEgress, Flip, FlipBalance, Hash, PolkadotBroadcaster,
PolkadotChainTracking, PolkadotIngressEgress, PolkadotThresholdSigner, Runtime, RuntimeCall,
SolanaBroadcaster, SolanaChainTracking, SolanaIngressEgress, SolanaThresholdSigner, System,
Validator, YEAR,
SolanaBroadcaster, SolanaChainTrackingProvider, SolanaIngressEgress, SolanaThresholdSigner,
System, Validator, YEAR,
};
use backup_node_rewards::calculate_backup_rewards;
use cf_chains::{
Expand Down Expand Up @@ -559,7 +559,7 @@ impl ChainEnvironment<CurrentAggKey, SolAddress> for SolEnvironment {

impl ChainEnvironment<ComputePrice, SolAmount> for SolEnvironment {
fn lookup(_s: ComputePrice) -> Option<u64> {
SolanaChainTracking::priority_fee()
SolanaChainTrackingProvider::priority_fee()
}
}

Expand Down
34 changes: 27 additions & 7 deletions state-chain/runtime/src/chainflip/solana_elections.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{Environment, Runtime, SolanaBroadcaster, SolanaThresholdSigner};
use crate::{Environment, Runtime, SolanaBroadcaster, SolanaChainTracking, SolanaThresholdSigner};
use cf_chains::{
instances::ChainInstanceAlias,
sol::{SolAddress, SolAmount, SolHash, SolSignature, SolTrackedData, SolanaCrypto},
Expand All @@ -9,6 +9,7 @@ use cf_traits::{
AdjustedFeeEstimationApi, ElectionEgressWitnesser, GetBlockHeight, IngressSource,
SolanaNonceWatch,
};

use codec::{Decode, Encode};
use pallet_cf_elections::{
electoral_system::{ElectoralReadAccess, ElectoralSystem},
Expand All @@ -17,6 +18,7 @@ use pallet_cf_elections::{
change::OnChangeHook,
composite::{tuple_5_impls::Hooks, Composite, Translator},
egress_success::OnEgressSuccess,
monotonic_median::MedianChangeHook,
},
CorruptStorageError, ElectionIdentifier, InitialState, InitialStateOf,
};
Expand Down Expand Up @@ -66,8 +68,11 @@ pub fn initial_state(
}
}

pub type SolanaBlockHeightTracking =
electoral_systems::monotonic_median::MonotonicMedian<<Solana as Chain>::ChainBlockNumber, ()>;
pub type SolanaBlockHeightTracking = electoral_systems::monotonic_median::MonotonicMedian<
<Solana as Chain>::ChainBlockNumber,
(),
SolanaBlockHeightTrackingHook,
>;
pub type SolanaFeeTracking = electoral_systems::unsafe_median::UnsafeMedian<
<Solana as Chain>::ChainAmount,
SolanaFeeUnsynchronisedSettings,
Expand Down Expand Up @@ -125,6 +130,21 @@ impl OnChangeHook<SolAddress, SolHash> for SolanaNonceTrackingHook {
}
}

pub struct SolanaBlockHeightTrackingHook;

impl MedianChangeHook<<Solana as Chain>::ChainBlockNumber> for SolanaBlockHeightTrackingHook {
fn on_change(block_height: <Solana as Chain>::ChainBlockNumber) {
if let Err(err) = SolanaChainTracking::inner_update_chain_state(cf_chains::ChainState {
block_height,
tracked_data: SolTrackedData {
priority_fee: SolanaChainTrackingProvider::priority_fee().unwrap_or_default(),
},
}) {
log::error!("Failed to update chain state: {:?}", err);
}
}
}

pub struct SolanaElectionHooks;

impl
Expand Down Expand Up @@ -234,8 +254,8 @@ pub struct SolanaIngressSettings {
pub usdc_token_mint_pubkey: SolAddress,
}

pub struct SolanaChainTracking;
impl GetBlockHeight<Solana> for SolanaChainTracking {
pub struct SolanaChainTrackingProvider;
impl GetBlockHeight<Solana> for SolanaChainTrackingProvider {
fn get_block_height() -> <Solana as Chain>::ChainBlockNumber {
pallet_cf_elections::Pallet::<Runtime, Instance>::with_electoral_access(
|electoral_access| {
Expand All @@ -256,7 +276,7 @@ impl GetBlockHeight<Solana> for SolanaChainTracking {
})
}
}
impl SolanaChainTracking {
impl SolanaChainTrackingProvider {
pub fn priority_fee() -> Option<<Solana as Chain>::ChainAmount> {
pallet_cf_elections::Pallet::<Runtime, Instance>::with_electoral_access(
|electoral_access| {
Expand Down Expand Up @@ -297,7 +317,7 @@ impl SolanaChainTracking {
})
}
}
impl AdjustedFeeEstimationApi<Solana> for SolanaChainTracking {
impl AdjustedFeeEstimationApi<Solana> for SolanaChainTrackingProvider {
fn estimate_ingress_fee(
asset: <Solana as Chain>::ChainAsset,
) -> <Solana as Chain>::ChainAmount {
Expand Down
24 changes: 16 additions & 8 deletions state-chain/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::{
chainflip::{
calculate_account_apy,
solana_elections::{
SolanaChainTracking, SolanaEgressWitnessingTrigger, SolanaIngress,
SolanaChainTrackingProvider, SolanaEgressWitnessingTrigger, SolanaIngress,
SolanaNonceTrackingTrigger,
},
Offence,
Expand Down Expand Up @@ -338,7 +338,7 @@ impl pallet_cf_vaults::Config<Instance5> for Runtime {
type SetAggKeyWithAggKey = cf_chains::sol::api::SolanaApi<SolEnvironment>;
type Broadcaster = SolanaBroadcaster;
type WeightInfo = pallet_cf_vaults::weights::PalletWeight<Runtime>;
type ChainTracking = SolanaChainTracking;
type ChainTracking = SolanaChainTrackingProvider;
type SafeMode = RuntimeSafeMode;
type CfeMultisigRequest = CfeInterface;
}
Expand Down Expand Up @@ -459,7 +459,7 @@ impl pallet_cf_ingress_egress::Config<Instance5> for Runtime {
type Broadcaster = SolanaBroadcaster;
type WeightInfo = pallet_cf_ingress_egress::weights::PalletWeight<Runtime>;
type DepositHandler = chainflip::DepositHandler;
type ChainTracking = SolanaChainTracking;
type ChainTracking = SolanaChainTrackingProvider;
type NetworkEnvironment = Environment;
type AssetConverter = Swapping;
type FeePayment = Flip;
Expand Down Expand Up @@ -961,7 +961,7 @@ impl pallet_cf_broadcast::Config<Instance5> for Runtime {
type WeightInfo = pallet_cf_broadcast::weights::PalletWeight<Runtime>;
type SafeMode = RuntimeSafeMode;
type SafeModeBlockMargin = ConstU32<10>;
type ChainTracking = SolanaChainTracking;
type ChainTracking = SolanaChainTrackingProvider;
type RetryPolicy = DefaultRetryPolicy;
type LiabilityTracker = AssetBalances;
type CfeBroadcastRequest = CfeInterface;
Expand Down Expand Up @@ -992,6 +992,12 @@ impl pallet_cf_chain_tracking::Config<Instance4> for Runtime {
type WeightInfo = pallet_cf_chain_tracking::weights::PalletWeight<Runtime>;
}

impl pallet_cf_chain_tracking::Config<Instance5> for Runtime {
type RuntimeEvent = RuntimeEvent;
type TargetChain = Solana;
type WeightInfo = pallet_cf_chain_tracking::weights::PalletWeight<Runtime>;
}

impl pallet_cf_elections::Config<Instance5> for Runtime {
type RuntimeEvent = RuntimeEvent;
type ElectoralSystem = chainflip::solana_elections::SolanaElectoralSystem;
Expand Down Expand Up @@ -1058,6 +1064,7 @@ construct_runtime!(
SolanaBroadcaster: pallet_cf_broadcast::<Instance5>,
SolanaIngressEgress: pallet_cf_ingress_egress::<Instance5>,
SolanaElections: pallet_cf_elections::<Instance5>,
SolanaChainTracking: pallet_cf_chain_tracking::<Instance5>,

AssetBalances: pallet_cf_asset_balances,
}
Expand Down Expand Up @@ -1140,6 +1147,7 @@ pub type PalletExecutionOrder = (
PolkadotChainTracking,
BitcoinChainTracking,
ArbitrumChainTracking,
SolanaChainTracking,
// Elections
SolanaElections,
// Vaults
Expand Down Expand Up @@ -1638,7 +1646,7 @@ impl_runtime_apis! {
pallet_cf_chain_tracking::Pallet::<Runtime, ArbitrumInstance>::estimate_ingress_fee(asset)
)
},
ForeignChainAndAsset::Solana(asset) => Some(SolanaChainTracking::
ForeignChainAndAsset::Solana(asset) => Some(SolanaChainTrackingProvider::
estimate_ingress_fee(asset).into()),
}
}
Expand All @@ -1659,7 +1667,7 @@ impl_runtime_apis! {
pallet_cf_chain_tracking::Pallet::<Runtime, ArbitrumInstance>::estimate_egress_fee(asset)
)
},
ForeignChainAndAsset::Solana(asset) => Some(SolanaChainTracking::
ForeignChainAndAsset::Solana(asset) => Some(SolanaChainTrackingProvider::
estimate_egress_fee(asset).into()),
}
}
Expand Down Expand Up @@ -2030,7 +2038,7 @@ impl_runtime_apis! {
let eth = pallet_cf_chain_tracking::CurrentChainState::<Runtime, EthereumInstance>::get().unwrap();
let dot = pallet_cf_chain_tracking::CurrentChainState::<Runtime, PolkadotInstance>::get().unwrap();
let arb = pallet_cf_chain_tracking::CurrentChainState::<Runtime, ArbitrumInstance>::get().unwrap();
let sol = SolanaChainTracking::get_block_height();
let sol = SolanaChainTrackingProvider::get_block_height();

ExternalChainsBlockHeight {
bitcoin: btc.block_height,
Expand Down Expand Up @@ -2119,7 +2127,7 @@ impl_runtime_apis! {
bitcoin: open_channels::<pallet_cf_chain_tracking::Pallet<Runtime, BitcoinInstance>, BitcoinInstance>(),
polkadot: open_channels::<pallet_cf_chain_tracking::Pallet<Runtime, PolkadotInstance>, PolkadotInstance>(),
arbitrum: open_channels::<pallet_cf_chain_tracking::Pallet<Runtime, ArbitrumInstance>, ArbitrumInstance>(),
solana: open_channels::<SolanaChainTracking, SolanaInstance>(),
solana: open_channels::<SolanaChainTrackingProvider, SolanaInstance>(),
}
}
fn cf_fee_imbalance() -> FeeImbalance<AssetAmount> {
Expand Down
Loading
Loading