Skip to content

Commit

Permalink
feat: solana chain tracking events (#5195)
Browse files Browse the repository at this point in the history
* feat: solana chain tracking events

* fix: initial chain state in migration

* chore: add initial chain spec values
  • Loading branch information
kylezs authored Aug 24, 2024
1 parent 8c5ccff commit 08fd873
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 52 deletions.
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

0 comments on commit 08fd873

Please sign in to comment.