diff --git a/fendermint/app/settings/src/lib.rs b/fendermint/app/settings/src/lib.rs index fa33f8a610..1230b3b818 100644 --- a/fendermint/app/settings/src/lib.rs +++ b/fendermint/app/settings/src/lib.rs @@ -1,9 +1,10 @@ // Copyright 2022-2024 Protocol Labs // SPDX-License-Identifier: Apache-2.0, MIT -use anyhow::{anyhow, Context}; +use anyhow::{anyhow, bail, Context}; use config::{Config, ConfigError, Environment, File}; use fvm_shared::address::Address; +use fvm_shared::bigint::Zero; use fvm_shared::econ::TokenAmount; use ipc_api::subnet_id::SubnetID; use serde::{Deserialize, Serialize}; @@ -212,9 +213,16 @@ pub struct IpcSettings { impl IpcSettings { pub fn topdown_config(&self) -> anyhow::Result<&TopDownSettings> { - self.topdown + let ret = self + .topdown .as_ref() - .ok_or_else(|| anyhow!("top down config missing")) + .ok_or_else(|| anyhow!("top down config missing"))?; + + if ret.chain_head_delay.is_zero() { + bail!("unsafe top-down chain head delay: zero value not accepted") + }; + + Ok(ret) } } diff --git a/fendermint/vm/interpreter/src/chain.rs b/fendermint/vm/interpreter/src/chain.rs index ae4d6af24a..4284c34ecf 100644 --- a/fendermint/vm/interpreter/src/chain.rs +++ b/fendermint/vm/interpreter/src/chain.rs @@ -317,12 +317,17 @@ where "chain interpreter committed topdown finality", ); - // The commitment of the finality for block `N` triggers - // the execution of all side-effects up till `N-1`, as for - // deferred execution chains, this is the latest state that - // we know for sure that we have available. - let execution_fr = prev_height; - let execution_to = finality.height - 1; + // The height range we pull top-down effects from. This _includes_ the proposed + // finality, as we assume that the interface we query publishes only fully + // executed blocks as the head of the chain. This is certainly the case for + // Ethereum-compatible JSON-RPC APIs, like Filecoin's. It should be the case + // too for future Filecoin light clients. + // + // Another factor to take into account is the chain_head_delay, which must be + // non-zero. So even in the case where deferred execution leaks through our + // query mechanism, it should not be problematic because we're guaranteed to + // be _at least_ 1 height behind. + let (execution_fr, execution_to) = (prev_height + 1, finality.height); // error happens if we cannot get the validator set from ipc agent after retries let validator_changes = env