-
Notifications
You must be signed in to change notification settings - Fork 10
Topdown finality proposal and execution #310
Changes from 16 commits
5f13dbf
5be01f1
c097c33
84c0a7f
1ce66f6
e0e248f
6d553f1
f84d37f
4f0d20e
f94fb64
e648c2c
62a46c5
20c267d
0672f98
1d75966
f5d2eb7
02ee4a7
4d71552
9daa1b3
92ecf89
368162e
6cad105
8e5f151
9a1b23a
880e2ee
35a3a2d
511650d
e34371b
3b1d687
4b36abe
703a85a
a4566cf
8e33af7
1face0c
aa30534
f088d50
9fb60e4
2c31f16
20c8991
33f0be9
df2e2d8
ffb4301
22082c1
aa4b4b5
3734664
dba7183
dc60f57
bbb307a
f03613b
9880805
6743aec
c95fa24
4b7e311
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,19 +1,23 @@ | ||||||
// Copyright 2022-2023 Protocol Labs | ||||||
// SPDX-License-Identifier: Apache-2.0, MIT | ||||||
|
||||||
use anyhow::Context; | ||||||
use anyhow::{anyhow, Context}; | ||||||
use config::{Config, ConfigError, Environment, File}; | ||||||
use fvm_shared::address::Address; | ||||||
use fvm_shared::econ::TokenAmount; | ||||||
use ipc_sdk::subnet_id::SubnetID; | ||||||
use serde::Deserialize; | ||||||
use serde_with::serde_as; | ||||||
use std::path::{Path, PathBuf}; | ||||||
use tendermint_rpc::Url; | ||||||
|
||||||
use fendermint_vm_encoding::{human_readable_delegate, human_readable_str}; | ||||||
use fendermint_vm_topdown::BlockHeight; | ||||||
|
||||||
use self::eth::EthSettings; | ||||||
use self::fvm::FvmSettings; | ||||||
use self::resolver::ResolverSettings; | ||||||
use ipc_provider::config::deserialize::deserialize_eth_address_from_str; | ||||||
|
||||||
pub mod eth; | ||||||
pub mod fvm; | ||||||
|
@@ -93,6 +97,52 @@ pub struct BroadcastSettings { | |||||
pub max_retries: u8, | ||||||
} | ||||||
|
||||||
#[derive(Debug, Deserialize, Clone)] | ||||||
pub struct TopDownConfig { | ||||||
/// The number of blocks to delay before reporting a height as final on the parent chain. | ||||||
/// To propose a certain number of epochs delayed from the latest height, we see to be | ||||||
/// conservative and avoid other from rejecting the proposal because they don't see the | ||||||
/// height as final yet. | ||||||
pub chain_head_delay: BlockHeight, | ||||||
/// Parent syncing cron period, in seconds | ||||||
pub polling_interval_secs: u64, | ||||||
aakoshh marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
/// Top down exponential back off retry base | ||||||
pub exponential_back_off_secs: u64, | ||||||
/// The max number of retries for exponential backoff before giving up | ||||||
pub exponential_retry_limit: usize, | ||||||
/// The ipc provider url | ||||||
pub ipc_provider_url: String, | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be the endpoint for the parent, right? Not for the whole ipc provider. This is confusing.
Suggested change
|
||||||
/// The parent registry address | ||||||
#[serde(deserialize_with = "deserialize_eth_address_from_str")] | ||||||
pub registry_address: Address, | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe it i a good idea to make it more explicit?
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The gateway and the registry do not have stable addresses on Lotus, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct, that is why we need to offer a config for that (for L2+ subnets this will be easier as we can point to the deterministic address by Fendermint) |
||||||
/// The parent gateway address | ||||||
#[serde(deserialize_with = "deserialize_eth_address_from_str")] | ||||||
pub gateway_address: Address, | ||||||
aakoshh marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
} | ||||||
|
||||||
#[serde_as] | ||||||
#[derive(Debug, Deserialize, Clone)] | ||||||
pub struct IPCSettings { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
So that we match existing capitalization here and [here](https://github.com/consensus-shipyard/fendermint/blob/main/fendermint/vm/genesis/src/lib.rs#L152] for example. |
||||||
#[serde_as(as = "IsHumanReadable")] | ||||||
pub subnet_id: SubnetID, | ||||||
pub network_name: String, | ||||||
/// The config for top down checkpoint. It's None if subnet id is root or not activating | ||||||
/// any top down checkpoint related operations | ||||||
pub topdown: Option<TopDownConfig>, | ||||||
} | ||||||
|
||||||
impl IPCSettings { | ||||||
pub fn is_topdown_enabled(&self) -> bool { | ||||||
!self.subnet_id.is_root() && self.topdown.is_some() | ||||||
} | ||||||
|
||||||
pub fn topdown_config(&self) -> anyhow::Result<&TopDownConfig> { | ||||||
self.topdown | ||||||
.as_ref() | ||||||
.ok_or_else(|| anyhow!("top down config missing")) | ||||||
} | ||||||
} | ||||||
|
||||||
#[derive(Debug, Deserialize, Clone)] | ||||||
pub struct Settings { | ||||||
/// Home directory configured on the CLI, to which all paths in settings can be set relative. | ||||||
|
@@ -115,6 +165,7 @@ pub struct Settings { | |||||
pub fvm: FvmSettings, | ||||||
pub resolver: ResolverSettings, | ||||||
pub broadcast: BroadcastSettings, | ||||||
pub ipc: IPCSettings, | ||||||
} | ||||||
|
||||||
#[macro_export] | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,7 @@ | |
|
||
use anyhow::{anyhow, bail, Context}; | ||
use fendermint_abci::ApplicationService; | ||
use fendermint_app::{App, AppConfig, AppStore, BitswapBlockstore}; | ||
use fendermint_app::{App, AppConfig, AppParentFinalityQuery, AppStore, BitswapBlockstore}; | ||
use fendermint_app_settings::AccountKind; | ||
use fendermint_crypto::SecretKey; | ||
use fendermint_rocksdb::{blockstore::NamespaceBlockstore, namespaces, RocksDb, RocksDbConfig}; | ||
|
@@ -15,14 +15,45 @@ use fendermint_vm_interpreter::{ | |
signed::SignedMessageInterpreter, | ||
}; | ||
use fendermint_vm_resolver::ipld::IpldResolver; | ||
use fendermint_vm_topdown::proxy::IPCProviderProxy; | ||
use fendermint_vm_topdown::sync::launch_polling_syncer; | ||
use fendermint_vm_topdown::{CachedFinalityProvider, Toggle}; | ||
use fvm_shared::address::Address; | ||
use ipc_provider::config::subnet::{EVMSubnet, SubnetConfig}; | ||
use ipc_provider::IpcProvider; | ||
use libp2p::identity::secp256k1; | ||
use libp2p::identity::Keypair; | ||
use std::sync::Arc; | ||
use tracing::info; | ||
|
||
use crate::cmd::key::read_secret_key; | ||
use crate::{cmd, options::run::RunArgs, settings::Settings}; | ||
|
||
fn create_ipc_provider_proxy(settings: &Settings) -> anyhow::Result<IPCProviderProxy> { | ||
let topdown_config = settings.ipc.topdown_config()?; | ||
|
||
let url = topdown_config | ||
.ipc_provider_url | ||
.parse() | ||
.context("invalid agent URL")?; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, no more agent? It would be nice to move this parsing into the |
||
|
||
let ipc_provider = IpcProvider::new_with_subnet( | ||
None, | ||
ipc_provider::config::Subnet { | ||
id: settings.ipc.subnet_id.clone(), | ||
network_name: settings.ipc.network_name.clone(), | ||
config: SubnetConfig::Fevm(EVMSubnet { | ||
provider_http: url, | ||
auth_token: None, | ||
registry_addr: topdown_config.registry_address, | ||
gateway_addr: topdown_config.gateway_address, | ||
accounts: vec![], | ||
}), | ||
}, | ||
)?; | ||
IPCProviderProxy::new(ipc_provider, settings.ipc.subnet_id.clone()) | ||
} | ||
|
||
cmd! { | ||
RunArgs(self, settings) { | ||
run(settings).await | ||
|
@@ -123,6 +154,26 @@ async fn run(settings: Settings) -> anyhow::Result<()> { | |
tracing::info!("IPLD Resolver disabled.") | ||
} | ||
|
||
let (parent_finality_provider, ipc_tuple) = if settings.ipc.is_topdown_enabled() { | ||
info!("topdown finality enabled"); | ||
let topdown_config = settings.ipc.topdown_config()?; | ||
let config = fendermint_vm_topdown::Config { | ||
chain_head_delay: topdown_config.chain_head_delay, | ||
polling_interval_secs: topdown_config.polling_interval_secs, | ||
exponential_back_off_secs: topdown_config.exponential_back_off_secs, | ||
exponential_retry_limit: topdown_config.exponential_retry_limit, | ||
}; | ||
let agent_proxy = Arc::new(create_ipc_provider_proxy(&settings)?); | ||
aakoshh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
let p = Arc::new(Toggle::enabled(CachedFinalityProvider::uninitialized( | ||
config.clone(), | ||
agent_proxy.clone(), | ||
))); | ||
(p, Some((agent_proxy, config))) | ||
} else { | ||
info!("topdown finality disabled"); | ||
(Arc::new(Toggle::disabled()), None) | ||
}; | ||
|
||
let app: App<_, _, AppStore, _> = App::new( | ||
AppConfig { | ||
app_namespace: ns.app, | ||
|
@@ -134,8 +185,26 @@ async fn run(settings: Settings) -> anyhow::Result<()> { | |
state_store, | ||
interpreter, | ||
resolve_pool, | ||
parent_finality_provider.clone(), | ||
)?; | ||
|
||
if let Some((agent_proxy, config)) = ipc_tuple { | ||
let app_parent_finality_query = AppParentFinalityQuery::new(app.clone()); | ||
tokio::spawn(async move { | ||
match launch_polling_syncer( | ||
app_parent_finality_query, | ||
config, | ||
parent_finality_provider, | ||
agent_proxy, | ||
) | ||
.await | ||
{ | ||
Ok(_) => {} | ||
Err(e) => tracing::error!("cannot launch polling syncer: {e}"), | ||
} | ||
}); | ||
} | ||
|
||
let service = ApplicationService(app); | ||
|
||
// Split it into components. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't you need to add here the settings for top-down too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is a
networ_name
? IIRC @dnkolegov said it's the same as the subnet ID.Sorry I can't keep it in my head 😞