Skip to content

Commit

Permalink
feat: emit checkpoint finalized from fvm & cleanup after merge
Browse files Browse the repository at this point in the history
  • Loading branch information
karlem committed Jul 17, 2024
1 parent d87f767 commit a627c3e
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 35 deletions.
34 changes: 32 additions & 2 deletions fendermint/vm/interpreter/src/fvm/checkpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ use fendermint_vm_genesis::{Power, Validator, ValidatorKey};
use ipc_actors_abis::checkpointing_facet as checkpoint;
use ipc_actors_abis::gateway_getter_facet as getter;
use ipc_api::staking::ConfigurationNumber;
use ipc_observability::emit;
use ipc_observability::{emit, serde::HexEncodableBlockHash};

use super::observe::{CheckpointCreated, CheckpointSigned, HexEncodableBlockHash};
use super::observe::{CheckpointCreated, CheckpointFinalized, CheckpointSigned};
use super::state::ipc::tokens_to_burn;
use super::{
broadcast::Broadcaster,
Expand Down Expand Up @@ -296,6 +296,36 @@ where
Ok(())
}

// Emit a CheckpointFinalized trace event if a checkpoint has been finalized on the current block.
pub fn emit_trace_if_check_checkpoint_finalized<DB>(
gateway: &GatewayCaller<DB>,
state: &mut FvmExecState<DB>,
) -> anyhow::Result<()>
where
DB: Blockstore + Clone,
{
if !gateway.enabled(state)? {
return Ok(());
}

let block_height = state.block_height();
let block_hash = state
.block_hash()
.ok_or_else(|| anyhow!("block hash not set"))?;

// Check if the checkpoint has been finalized.
let checkpoint_quorum = gateway.checkpoint_info(state, block_height)?;

if checkpoint_quorum.reached {
emit(CheckpointFinalized {
height: block_height,
hash: HexEncodableBlockHash(block_hash.to_vec()),
})
}

Ok(())
}

fn convert_tokenizables<Source: Tokenizable, Target: Tokenizable>(
tokenizables: Vec<Source>,
) -> anyhow::Result<Vec<Target>> {
Expand Down
2 changes: 2 additions & 0 deletions fendermint/vm/interpreter/src/fvm/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,8 @@ where
}

async fn end(&self, mut state: Self::State) -> anyhow::Result<(Self::State, Self::EndOutput)> {
checkpoint::emit_trace_if_check_checkpoint_finalized(&self.gateway, &mut state)?;

let updates = if let Some((checkpoint, updates)) =
checkpoint::maybe_create_checkpoint(&self.gateway, &mut state)
.context("failed to create checkpoint")?
Expand Down
35 changes: 18 additions & 17 deletions fendermint/vm/interpreter/src/fvm/observe.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
// Copyright 2022-2024 Protocol Labs
// SPDX-License-Identifier: Apache-2.0, MIT

use hex;
use std::fmt;

use ipc_observability::{
impl_traceable, impl_traceables, lazy_static, register_metrics, Recordable, TraceLevel,
Traceable,
impl_traceable, impl_traceables, lazy_static, register_metrics, serde::HexEncodableBlockHash,
Recordable, TraceLevel, Traceable,
};

use prometheus::{
Expand Down Expand Up @@ -36,6 +33,8 @@ register_metrics! {
"Height of the checkpoint signed",
&["validator"]
);
BOTTOMUP_CHECKPOINT_FINALIZED_HEIGHT: IntGauge
= register_int_gauge!("bottomup_checkpoint_finalized_height", "Height of the checkpoint finalized");
}

impl_traceables!(
Expand All @@ -51,7 +50,8 @@ impl_traceables!(
TraceLevel::Info,
"Bottomup",
CheckpointCreated,
CheckpointSigned<'a>
CheckpointSigned<'a>,
CheckpointFinalized
);

impl Recordable for MsgExecCheck<'_> {
Expand Down Expand Up @@ -102,17 +102,6 @@ macro_rules! message_exec_struct {

message_exec_struct!(MsgExecCheck, MsgExecEstimate, MsgExecApply, MsgExecCall);

/// Hex encoded hash.
pub type HashHex<'a> = &'a str;
// Hex encodable block hash.
pub struct HexEncodableBlockHash(pub Vec<u8>);

impl fmt::Debug for HexEncodableBlockHash {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", hex::encode(&self.0))
}
}

#[derive(Debug)]
pub struct CheckpointCreated {
pub height: u64,
Expand Down Expand Up @@ -145,6 +134,18 @@ impl Recordable for CheckpointSigned<'_> {
}
}

#[derive(Debug)]
pub struct CheckpointFinalized {
pub height: i64,
pub hash: HexEncodableBlockHash,
}

impl Recordable for CheckpointFinalized {
fn record_metrics(&self) {
BOTTOMUP_CHECKPOINT_FINALIZED_HEIGHT.set(self.height);
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
13 changes: 12 additions & 1 deletion fendermint/vm/interpreter/src/fvm/state/ipc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,17 @@ impl<DB: Blockstore + Clone> GatewayCaller<DB> {
self.getter.call(state, |c| c.get_incomplete_checkpoints())
}

/// Retrieve checkpoint info by block height.
pub fn checkpoint_info(
&self,
state: &mut FvmExecState<DB>,
height: i64,
) -> anyhow::Result<getter::QuorumInfo> {
self.getter.call(state, |c| {
c.get_checkpoint_info(ethers::types::U256::from(height))
})
}

/// Apply all pending validator changes, returning the newly adopted configuration number, or 0 if there were no changes.
pub fn apply_validator_changes(&self, state: &mut FvmExecState<DB>) -> anyhow::Result<u64> {
self.topdown.call(state, |c| c.apply_finality_changes())
Expand Down Expand Up @@ -304,7 +315,7 @@ impl<DB: Blockstore + Clone> GatewayCaller<DB> {
height: u64,
) -> anyhow::Result<Vec<EthAddress>> {
let (_, _, addrs, _) = self.getter.call(state, |c| {
c.get_checkpoint_signature_bundle(ethers::types::U256::from(height))
c.get_checkpoint_signature_bundle(et::U256::from(height))
})?;

let addrs = addrs.into_iter().map(|a| a.into()).collect();
Expand Down
4 changes: 2 additions & 2 deletions ipc/provider/src/checkpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
use crate::config::Subnet;
use crate::manager::{BottomUpCheckpointRelayer, EthSubnetManager};
use crate::observe::{CheckpointFinalized, HexEncodableBlockHash};
use crate::observe::CheckpointFinalized;
use anyhow::{anyhow, Result};
use futures_util::future::try_join_all;
use fvm_shared::address::Address;
use fvm_shared::clock::ChainEpoch;
use ipc_api::checkpoint::{BottomUpCheckpointBundle, QuorumReachedEvent};
use ipc_observability::emit;
use ipc_observability::{emit, serde::HexEncodableBlockHash};
use ipc_wallet::{EthKeyAddress, PersistentKeyStore};
use std::cmp::max;
use std::fmt::{Display, Formatter};
Expand Down
15 changes: 2 additions & 13 deletions ipc/provider/src/observe.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
// Copyright 2022-2024 Protocol Labs
// SPDX-License-Identifier: Apache-2.0, MIT

use std::fmt;

use ipc_observability::{
impl_traceable, impl_traceables, lazy_static, register_metrics, Recordable, TraceLevel,
Traceable,
impl_traceable, impl_traceables, lazy_static, register_metrics, serde::HexEncodableBlockHash,
Recordable, TraceLevel, Traceable,
};
use prometheus::{register_int_gauge, IntGauge, Registry};

Expand All @@ -16,15 +14,6 @@ register_metrics! {

impl_traceables!(TraceLevel::Info, "Bottomup", CheckpointFinalized);

// Hex encodable block hash.
pub struct HexEncodableBlockHash(pub Vec<u8>);

impl fmt::Debug for HexEncodableBlockHash {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", hex::encode(&self.0))
}
}

#[derive(Debug)]
pub struct CheckpointFinalized {
pub height: i64,
Expand Down

0 comments on commit a627c3e

Please sign in to comment.