Skip to content
This repository has been archived by the owner on Jan 11, 2024. It is now read-only.

Commit

Permalink
FM-255: Sign checkpoint (#276)
Browse files Browse the repository at this point in the history
* FM-255: Skeleton for broadcasting the signature

* FM-255: Update ABI

* FM-255: Sign the checkpoint

* FM-255: Skeleton for a broadcaster

* FM-255: Use TxClient

* FM-255: Fix parsing of fee settings

* FM-255: Updates for zeroization
  • Loading branch information
aakoshh authored Sep 26, 2023
1 parent 5fd1f16 commit 67db31f
Show file tree
Hide file tree
Showing 29 changed files with 1,049 additions and 673 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions fendermint/app/config/default.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ gas_search_step = 1.25
# otherwise only the nonces and balances are projected into a partial state.
exec_in_check = true

# Gas fee used when broadcasting transactions.
# TODO: Configure a value once validators are charged for the "miner penalty".
gas_fee_cap = 0
# Gas premium used when broadcasting transactions.
gas_premium = 0

# Ethereum API facade
[eth]
# Maximum time allowed between polls for filter changes, in seconds, before the subscription is canceled.
Expand Down
3 changes: 1 addition & 2 deletions fendermint/app/settings/src/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ use serde::Deserialize;
use serde_with::{serde_as, DurationSeconds};
use std::time::Duration;

use crate::SocketAddress;
use fendermint_vm_encoding::IsHumanReadable;
use crate::{IsHumanReadable, SocketAddress};

/// Ethereum API facade settings.
#[serde_as]
Expand Down
21 changes: 17 additions & 4 deletions fendermint/app/settings/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,30 @@

use anyhow::Context;
use config::{Config, ConfigError, Environment, File};
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_str;
use fendermint_vm_encoding::{human_readable_delegate, human_readable_str};

use self::eth::EthSettings;
use self::resolver::ResolverSettings;

pub mod eth;
pub mod resolver;

/// Marker to be used with the `human_readable_str!` macro.
/// Marker to be used with the `#[serde_as(as = "IsHumanReadable")]` annotations.
///
/// We can't use the one in `fendermint_vm_encoding` because we can't implement traits for it here.
/// We can't just import `fendermint_vm_encoding::IsHumanReadable` because we can't implement traits for it here,
/// however we can use the `human_readable_delegate!` macro to delegate from this to that for the types we need
/// and it will look the same.
struct IsHumanReadable;

human_readable_str!(IsHumanReadable, SubnetID);
human_readable_str!(SubnetID);
human_readable_delegate!(TokenAmount);

#[derive(Debug, Deserialize, Clone)]
pub struct SocketAddress {
Expand Down Expand Up @@ -58,6 +63,7 @@ pub struct DbSettings {
pub state_hist_size: u64,
}

#[serde_as]
#[derive(Debug, Deserialize, Clone)]
pub struct FvmSettings {
/// Overestimation rate applied to gas estimations to ensure that the
Expand All @@ -72,6 +78,13 @@ pub struct FvmSettings {
/// Enabling this option is required to fully support "pending" queries in the Ethereum API,
/// otherwise only the nonces and balances are projected into a partial state.
pub exec_in_check: bool,

/// Gas fee used when broadcasting transactions.
#[serde_as(as = "IsHumanReadable")]
pub gas_fee_cap: TokenAmount,
/// Gas premium used when broadcasting transactions.
#[serde_as(as = "IsHumanReadable")]
pub gas_premium: TokenAmount,
}

#[derive(Debug, Deserialize, Clone)]
Expand Down
3 changes: 1 addition & 2 deletions fendermint/app/settings/src/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ use serde_with::{serde_as, DurationSeconds};
use ipc_sdk::subnet_id::SubnetID;
use multiaddr::Multiaddr;

use super::IsHumanReadable;
use crate::home_relative;
use crate::{home_relative, IsHumanReadable};

#[serde_as]
#[derive(Debug, Clone, Deserialize)]
Expand Down
2 changes: 1 addition & 1 deletion fendermint/app/src/cmd/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ async fn fevm_estimate_gas(

let res = client
.inner
.fevm_estmiate_gas(contract, calldata, value, gas_params, height)
.fevm_estimate_gas(contract, calldata, value, gas_params, height)
.await?;

let json = json!({ "response": res });
Expand Down
20 changes: 16 additions & 4 deletions fendermint/app/src/cmd/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use fendermint_rocksdb::{blockstore::NamespaceBlockstore, namespaces, RocksDb, R
use fendermint_vm_interpreter::{
bytes::{BytesMessageInterpreter, ProposalPrepareMode},
chain::{ChainMessageInterpreter, CheckpointPool},
fvm::FvmMessageInterpreter,
fvm::{Broadcaster, FvmMessageInterpreter, ValidatorContext},
signed::SignedMessageInterpreter,
};
use fendermint_vm_resolver::ipld::IpldResolver;
Expand All @@ -29,8 +29,9 @@ cmd! {
///
/// This method acts as our composition root.
async fn run(settings: Settings) -> anyhow::Result<()> {
let client = tendermint_rpc::HttpClient::new(settings.tendermint_rpc_url()?)
.context("failed to create Tendermint client")?;
let client: tendermint_rpc::HttpClient =
tendermint_rpc::HttpClient::new(settings.tendermint_rpc_url()?)
.context("failed to create Tendermint client")?;

let validator_key = {
let sk = settings.validator_key();
Expand All @@ -42,9 +43,20 @@ async fn run(settings: Settings) -> anyhow::Result<()> {
}
};

let validator_ctx = validator_key.map(|sk| {
// For now we are using the validator key for submitting transactions.
let broadcaster = Broadcaster::new(
client.clone(),
sk.clone(),
settings.fvm.gas_fee_cap.clone(),
settings.fvm.gas_premium.clone(),
);
ValidatorContext::new(sk, broadcaster)
});

let interpreter = FvmMessageInterpreter::<NamespaceBlockstore, _>::new(
client,
validator_key,
validator_ctx,
settings.contracts_dir(),
settings.fvm.gas_overestimation_rate,
settings.fvm.gas_search_step,
Expand Down
4 changes: 4 additions & 0 deletions fendermint/rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ pub mod query;
pub mod response;
pub mod tx;

pub use client::FendermintClient;
pub use query::QueryClient;
pub use tx::TxClient;

/// A [`base64::Engine`] using the [`alphabet::STANDARD`] base64 alphabet
/// padding bytes when writing but requireing no padding when reading.
const B64_ENGINE: base64::engine::GeneralPurpose = GeneralPurpose::new(
Expand Down
2 changes: 1 addition & 1 deletion fendermint/rpc/src/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ pub trait CallClient: QueryClient + BoundClient {
}

/// Estimate the gas limit of a FEVM call.
async fn fevm_estmiate_gas(
async fn fevm_estimate_gas(
&mut self,
contract: Address,
calldata: Bytes,
Expand Down
61 changes: 57 additions & 4 deletions fendermint/vm/encoding/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,20 +74,23 @@ where
///
/// human_readable_str!(Address);
///
/// // Or in full form:
/// human_readable_str!(Address: IsHumanReadable);
///
/// struct MyStruct {
/// #[serde_as(as = "Option<IsHumanReadable>")]
/// pub delegated_address: Option<Address>,
/// }
/// ```
#[macro_export]
macro_rules! human_readable_str {
($mark:ty, $typ: ty) => {
($typ:ty : $mark:ty) => {
impl serde_with::SerializeAs<$typ> for $mark {
fn serialize_as<S>(addr: &$typ, serializer: S) -> Result<S::Ok, S::Error>
fn serialize_as<S>(value: &$typ, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
$crate::serialize_str(addr, serializer)
$crate::serialize_str(value, serializer)
}
}

Expand All @@ -102,7 +105,57 @@ macro_rules! human_readable_str {
};

($typ: ty) => {
human_readable_str!(IsHumanReadable, $typ);
human_readable_str!($typ: IsHumanReadable);
};
}

/// Delegate [`SerializeAs`] and [`DeserializeAs`] to another instance.
///
/// # Example
///
/// ```ignore
/// struct IsHumanReadable;
///
/// human_readable_delegate!(Address);
///
/// // Or in full form:
/// human_readable_delegate!(Address: IsHumanReadable => fendermint_vm_encoding::IsHumanReadable);
///
/// struct MyStruct {
/// #[serde_as(as = "Option<IsHumanReadable>")]
/// pub delegated_address: Option<Address>,
/// }
/// ```
#[macro_export]
macro_rules! human_readable_delegate {
($typ:ty : $mark:ty => $deleg:ty) => {
impl serde_with::SerializeAs<$typ> for $mark {
fn serialize_as<S>(value: &$typ, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
$deleg: serde_with::SerializeAs<$typ>,
{
<$deleg>::serialize_as::<S>(value, serializer)
}
}

impl<'de> serde_with::DeserializeAs<'de, $typ> for $mark {
fn deserialize_as<D>(deserializer: D) -> Result<$typ, D::Error>
where
D: serde::de::Deserializer<'de>,
$deleg: serde_with::DeserializeAs<'de, $typ>,
{
<$deleg>::deserialize_as::<D>(deserializer)
}
}
};

($typ: ty : $mark:ty) => {
human_readable_delegate!($typ : $mark => $crate::IsHumanReadable);
};

($typ: ty) => {
human_readable_delegate!($typ : IsHumanReadable => $crate::IsHumanReadable);
};
}

Expand Down
2 changes: 1 addition & 1 deletion fendermint/vm/genesis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ pub struct Actor {
}

/// Total stake delegated to this validator.
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Copy)]
pub struct Power(pub u64);

/// Secp256k1 public key of the validators.
Expand Down
1 change: 1 addition & 0 deletions fendermint/vm/interpreter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ fendermint_vm_message = { path = "../message" }
fendermint_vm_resolver = { path = "../resolver" }
fendermint_crypto = { path = "../../crypto" }
fendermint_eth_hardhat = { path = "../../eth/hardhat" }
fendermint_rpc = { path = "../../rpc" }

async-trait = { workspace = true }
async-stm = { workspace = true }
Expand Down
Loading

0 comments on commit 67db31f

Please sign in to comment.