Skip to content

Commit a864009

Browse files
committed
feat: progress with top down manager
1 parent da28dd0 commit a864009

File tree

5 files changed

+352
-102
lines changed

5 files changed

+352
-102
lines changed

fendermint/vm/interpreter/src/fvm/interpreter.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -347,13 +347,15 @@ where
347347
for msg in msgs {
348348
match fvm_ipld_encoding::from_slice::<ChainMessage>(&msg) {
349349
Ok(chain_msg) => match chain_msg {
350-
ChainMessage::Ipc(IpcMessage::ParentFinalityWithProof(bundle)) => {
350+
ChainMessage::Ipc(IpcMessage::TopDownWithProof(bundle)) => {
351351
// DETERMINISTIC VERIFICATION - all validators reach same decision
352-
match self.top_down_manager.verify_proof_bundle(&bundle).await {
352+
match self
353+
.top_down_manager
354+
.verify_proof_bundle_attestation(&bundle)
355+
{
353356
Ok(()) => {
354357
tracing::debug!(
355358
instance = bundle.certificate.instance_id,
356-
height = bundle.finality.height,
357359
"proof bundle verified - accepting"
358360
);
359361
}
@@ -489,7 +491,7 @@ where
489491
})
490492
}
491493
ChainMessage::Ipc(ipc_msg) => match ipc_msg {
492-
IpcMessage::ParentFinalityWithProof(bundle) => {
494+
IpcMessage::TopDownWithProof(bundle) => {
493495
// NEW: Execute proof-based topdown finality (v2)
494496
let applied_message = self
495497
.top_down_manager

fendermint/vm/interpreter/src/fvm/state/ipc.rs

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@ use fendermint_crypto::{PublicKey, SecretKey};
1212
use fendermint_vm_actor_interface::ipc;
1313
use fendermint_vm_actor_interface::{
1414
eam::EthAddress,
15+
f3_light_client,
1516
init::builtin_actor_eth_addr,
1617
ipc::{AbiHash, ValidatorMerkleTree, GATEWAY_ACTOR_ID},
1718
};
1819
use fendermint_vm_genesis::{Collateral, Power, PowerScale, Validator, ValidatorKey};
1920
use fendermint_vm_message::conv::{from_eth, from_fvm};
2021
use fendermint_vm_message::signed::sign_secp256k1;
2122
use fendermint_vm_topdown::IPCParentFinality;
23+
use fvm_ipld_encoding::RawBytes;
2224

2325
use ipc_actors_abis::checkpointing_facet::CheckpointingFacet;
2426
use ipc_actors_abis::gateway_getter_facet::GatewayGetterFacet;
@@ -385,3 +387,110 @@ fn membership_to_power_table(
385387

386388
pt
387389
}
390+
391+
/// Caller for F3 Light Client actor operations.
392+
///
393+
/// The F3 Light Client actor maintains F3 light client state including:
394+
/// - Current F3 instance ID
395+
/// - Finalized epochs chain
396+
/// - Validator power table
397+
#[derive(Clone)]
398+
pub struct F3LightClientCaller {
399+
actor_id: ActorID,
400+
}
401+
402+
impl Default for F3LightClientCaller {
403+
fn default() -> Self {
404+
Self::new(f3_light_client::F3_LIGHT_CLIENT_ACTOR_ID)
405+
}
406+
}
407+
408+
impl F3LightClientCaller {
409+
pub fn new(actor_id: ActorID) -> Self {
410+
Self { actor_id }
411+
}
412+
}
413+
414+
impl<DB: Blockstore + Clone> F3LightClientCaller {
415+
/// Get the current F3 light client state.
416+
///
417+
/// Returns the instance ID, finalized epochs, and power table.
418+
pub fn get_state(
419+
&self,
420+
state: &mut FvmExecState<DB>,
421+
) -> anyhow::Result<f3_light_client::GetStateResponse> {
422+
let method_num = f3_light_client::Method::GetState as u64;
423+
let params = RawBytes::default(); // No params needed for GetState
424+
425+
let msg = fvm_shared::message::Message {
426+
from: fvm_shared::address::Address::new_id(fvm_shared::SYSTEM_ACTOR_ID),
427+
to: fvm_shared::address::Address::new_id(self.actor_id),
428+
sequence: 0,
429+
gas_limit: 10_000_000_000,
430+
method_num,
431+
params,
432+
value: TokenAmount::zero(),
433+
version: 0,
434+
gas_fee_cap: TokenAmount::zero(),
435+
gas_premium: TokenAmount::zero(),
436+
};
437+
438+
let ret = state
439+
.execute_implicit(msg)
440+
.context("failed to call F3LightClientActor GetState")?;
441+
442+
if !ret.msg_receipt.exit_code.is_success() {
443+
bail!(
444+
"F3LightClientActor GetState returned exit code: {:?}",
445+
ret.msg_receipt.exit_code
446+
);
447+
}
448+
449+
let response: f3_light_client::GetStateResponse =
450+
fvm_ipld_encoding::from_slice(&ret.msg_receipt.return_data)
451+
.context("failed to decode GetStateResponse")?;
452+
453+
Ok(response)
454+
}
455+
456+
/// Update the F3 light client state with a new certificate.
457+
///
458+
/// This should be called after successfully executing a proof-based topdown finality message.
459+
pub fn update_state(
460+
&self,
461+
state: &mut FvmExecState<DB>,
462+
new_state: f3_light_client::LightClientState,
463+
) -> anyhow::Result<()> {
464+
let method_num = f3_light_client::Method::UpdateState as u64;
465+
466+
let params = f3_light_client::UpdateStateParams { state: new_state };
467+
let params = fvm_ipld_encoding::RawBytes::serialize(params)
468+
.context("failed to serialize UpdateStateParams")?;
469+
470+
let msg = fvm_shared::message::Message {
471+
from: fvm_shared::address::Address::new_id(fvm_shared::SYSTEM_ACTOR_ID),
472+
to: fvm_shared::address::Address::new_id(self.actor_id),
473+
sequence: 0,
474+
gas_limit: 10_000_000_000,
475+
method_num,
476+
params,
477+
value: TokenAmount::zero(),
478+
version: 0,
479+
gas_fee_cap: TokenAmount::zero(),
480+
gas_premium: TokenAmount::zero(),
481+
};
482+
483+
let ret = state
484+
.execute_implicit(msg)
485+
.context("failed to call F3LightClientActor UpdateState")?;
486+
487+
if !ret.msg_receipt.exit_code.is_success() {
488+
bail!(
489+
"F3LightClientActor UpdateState returned exit code: {:?}",
490+
ret.msg_receipt.exit_code
491+
);
492+
}
493+
494+
Ok(())
495+
}
496+
}

0 commit comments

Comments
 (0)