From 239bf6d9e50ca549d1957974e6db68883785c971 Mon Sep 17 00:00:00 2001 From: Sergey Ukustov Date: Wed, 16 Oct 2024 19:39:51 +0300 Subject: [PATCH 01/18] aha --- fendermint/vm/interpreter/src/chain.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fendermint/vm/interpreter/src/chain.rs b/fendermint/vm/interpreter/src/chain.rs index 5664cbd08..4333f90fc 100644 --- a/fendermint/vm/interpreter/src/chain.rs +++ b/fendermint/vm/interpreter/src/chain.rs @@ -746,7 +746,7 @@ where &self, (env, state): Self::State, ) -> anyhow::Result<(Self::State, Self::EndOutput)> { - let (state, out) = self.inner.end(state).await?; + let (mut state, out) = self.inner.end(state).await?; // Update any component that needs to know about changes in the power table. if !out.0 .0.is_empty() { @@ -766,6 +766,8 @@ where .update_power_table(power_updates.clone()) }) .await; + + // TODO Continue update power table in blobs actor } Ok(((env, state), out)) From 8c3345accde0456605cf18439bd9ad7549c3d972 Mon Sep 17 00:00:00 2001 From: Sergey Ukustov Date: Wed, 16 Oct 2024 20:08:48 +0300 Subject: [PATCH 02/18] add powertable --- fendermint/actors/blobs/shared/src/state.rs | 18 ++++++++++++++++++ fendermint/actors/blobs/src/shared.rs | 2 +- fendermint/actors/blobs/src/state.rs | 7 ++++--- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/fendermint/actors/blobs/shared/src/state.rs b/fendermint/actors/blobs/shared/src/state.rs index 99b54ed34..0a2a927cd 100644 --- a/fendermint/actors/blobs/shared/src/state.rs +++ b/fendermint/actors/blobs/shared/src/state.rs @@ -146,3 +146,21 @@ pub struct Subscription { /// The delegate origin and caller that may have created the subscription via a credit approval. pub delegate: Option<(Address, Address)>, } + +// --- Copied from fendermint_vm_interpreter: PowerTable and friends --- // + +/// Total voting power of a validator. +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +pub struct Power(pub u64); + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +pub struct PowerTable(pub Vec>); + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +pub struct ValidatorKey(pub PublicKey); + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +pub struct Validator

{ + pub public_key: ValidatorKey, + pub power: P, +} diff --git a/fendermint/actors/blobs/src/shared.rs b/fendermint/actors/blobs/src/shared.rs index 4e97735a3..11c424764 100644 --- a/fendermint/actors/blobs/src/shared.rs +++ b/fendermint/actors/blobs/src/shared.rs @@ -15,4 +15,4 @@ pub struct ConstructorParams { pub capacity: u64, /// The byte-blocks per atto token rate. pub debit_rate: u64, -} +} \ No newline at end of file diff --git a/fendermint/actors/blobs/src/state.rs b/fendermint/actors/blobs/src/state.rs index 05c86bc48..12ecfc57a 100644 --- a/fendermint/actors/blobs/src/state.rs +++ b/fendermint/actors/blobs/src/state.rs @@ -6,9 +6,7 @@ use std::collections::{BTreeMap, HashMap, HashSet}; use std::ops::Bound::{Included, Unbounded}; use fendermint_actor_blobs_shared::params::GetStatsReturn; -use fendermint_actor_blobs_shared::state::{ - Account, Blob, BlobStatus, CreditApproval, Hash, PublicKey, Subscription, -}; +use fendermint_actor_blobs_shared::state::{Account, Blob, BlobStatus, CreditApproval, Hash, PowerTable, PublicKey, Subscription}; use fil_actors_runtime::ActorError; use fvm_ipld_encoding::tuple::*; use fvm_shared::address::Address; @@ -47,6 +45,8 @@ pub struct State { pub expiries: BTreeMap>>, /// Map of currently pending blob hashes to account and source Iroh node IDs. pub pending: BTreeMap>, + /// Power table cache + pub power_table: PowerTable, } /// Helper for handling credit approvals. @@ -77,6 +77,7 @@ impl State { blobs: HashMap::new(), expiries: BTreeMap::new(), pending: BTreeMap::new(), + power_table: PowerTable(vec![]), } } From bedf07050f2528b1e2c208f4653d3b31e75d5363 Mon Sep 17 00:00:00 2001 From: Sergey Ukustov Date: Wed, 16 Oct 2024 20:56:37 +0300 Subject: [PATCH 03/18] maybe save the powertable --- fendermint/actors/blobs/shared/src/lib.rs | 1 + fendermint/actors/blobs/shared/src/params.rs | 7 ++- fendermint/actors/blobs/shared/src/state.rs | 11 ++--- fendermint/actors/blobs/src/actor.rs | 14 +++--- fendermint/actors/blobs/src/state.rs | 5 +++ fendermint/vm/interpreter/src/chain.rs | 46 ++++++++++++++++++-- 6 files changed, 67 insertions(+), 17 deletions(-) diff --git a/fendermint/actors/blobs/shared/src/lib.rs b/fendermint/actors/blobs/shared/src/lib.rs index 1a26225ab..a0ff9dc53 100644 --- a/fendermint/actors/blobs/shared/src/lib.rs +++ b/fendermint/actors/blobs/shared/src/lib.rs @@ -36,6 +36,7 @@ pub enum Method { GetPendingBlobs = frc42_dispatch::method_hash!("GetPendingBlobs"), FinalizeBlob = frc42_dispatch::method_hash!("FinalizeBlob"), DeleteBlob = frc42_dispatch::method_hash!("DeleteBlob"), + UpdatePowerTable = frc42_dispatch::method_hash!("UpdatePowerTable"), } pub fn buy_credit(rt: &impl Runtime, recipient: Address) -> Result { diff --git a/fendermint/actors/blobs/shared/src/params.rs b/fendermint/actors/blobs/shared/src/params.rs index d48c02788..4a368f276 100644 --- a/fendermint/actors/blobs/shared/src/params.rs +++ b/fendermint/actors/blobs/shared/src/params.rs @@ -9,13 +9,18 @@ use fvm_shared::clock::ChainEpoch; use fvm_shared::econ::TokenAmount; use serde::{Deserialize, Serialize}; -use crate::state::{BlobStatus, Hash, PublicKey}; +use crate::state::{BlobStatus, Hash, PowerTable, PublicKey}; /// Params for buying credits. #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(transparent)] pub struct BuyCreditParams(pub Address); +/// Push the power table to the actor. +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(transparent)] +pub struct UpdatePowerTableParams(pub PowerTable); + /// Params for approving credit. #[derive(Clone, Debug, Serialize_tuple, Deserialize_tuple)] pub struct ApproveCreditParams { diff --git a/fendermint/actors/blobs/shared/src/state.rs b/fendermint/actors/blobs/shared/src/state.rs index 0a2a927cd..f41375737 100644 --- a/fendermint/actors/blobs/shared/src/state.rs +++ b/fendermint/actors/blobs/shared/src/state.rs @@ -154,13 +154,10 @@ pub struct Subscription { pub struct Power(pub u64); #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] -pub struct PowerTable(pub Vec>); +pub struct PowerTable(pub Vec); #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] -pub struct ValidatorKey(pub PublicKey); - -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] -pub struct Validator

{ - pub public_key: ValidatorKey, - pub power: P, +pub struct Validator { + pub address: Address, + pub power: Power, } diff --git a/fendermint/actors/blobs/src/actor.rs b/fendermint/actors/blobs/src/actor.rs index 45f22c075..c8625face 100644 --- a/fendermint/actors/blobs/src/actor.rs +++ b/fendermint/actors/blobs/src/actor.rs @@ -4,11 +4,7 @@ use std::collections::HashSet; -use fendermint_actor_blobs_shared::params::{ - AddBlobParams, ApproveCreditParams, BuyCreditParams, DeleteBlobParams, FinalizeBlobParams, - GetAccountParams, GetBlobParams, GetBlobStatusParams, GetPendingBlobsParams, GetStatsReturn, - RevokeCreditParams, -}; +use fendermint_actor_blobs_shared::params::{AddBlobParams, ApproveCreditParams, BuyCreditParams, DeleteBlobParams, FinalizeBlobParams, GetAccountParams, GetBlobParams, GetBlobStatusParams, GetPendingBlobsParams, GetStatsReturn, RevokeCreditParams, UpdatePowerTableParams}; use fendermint_actor_blobs_shared::state::{ Account, Blob, BlobStatus, CreditApproval, Hash, PublicKey, Subscription, }; @@ -116,6 +112,13 @@ impl BlobsActor { }) } + fn update_power_table(rt: &impl Runtime, params: UpdatePowerTableParams) -> Result<(), ActorError> { + rt.validate_immediate_caller_is(std::iter::once(&SYSTEM_ACTOR_ADDR))?; + rt.transaction(|st: &mut State, _rt| { + st.update_power_table(params.0) + }) + } + fn revoke_credit(rt: &impl Runtime, params: RevokeCreditParams) -> Result<(), ActorError> { rt.validate_immediate_caller_accept_any()?; let (from, actor_type) = resolve_external(rt, params.from)?; @@ -328,6 +331,7 @@ impl ActorCode for BlobsActor { GetPendingBlobs => get_pending_blobs, FinalizeBlob => finalize_blob, DeleteBlob => delete_blob, + UpdatePowerTable => update_power_table, _ => fallback, } } diff --git a/fendermint/actors/blobs/src/state.rs b/fendermint/actors/blobs/src/state.rs index 12ecfc57a..e1546a95d 100644 --- a/fendermint/actors/blobs/src/state.rs +++ b/fendermint/actors/blobs/src/state.rs @@ -167,6 +167,11 @@ impl State { Ok(approval.clone()) } + pub fn update_power_table(&mut self, power_table: PowerTable) -> anyhow::Result<(), ActorError> { + self.power_table = power_table; + Ok(()) + } + pub fn revoke_credit( &mut self, from: Address, diff --git a/fendermint/vm/interpreter/src/chain.rs b/fendermint/vm/interpreter/src/chain.rs index 4333f90fc..9af9fb8b4 100644 --- a/fendermint/vm/interpreter/src/chain.rs +++ b/fendermint/vm/interpreter/src/chain.rs @@ -17,9 +17,9 @@ use crate::{ use anyhow::{anyhow, bail, Context}; use async_stm::atomically; use async_trait::async_trait; -use fendermint_actor_blobs_shared::params::{GetBlobStatusParams, GetPendingBlobsParams}; -use fendermint_actor_blobs_shared::state::BlobStatus; -use fendermint_actor_blobs_shared::Method::DebitAccounts; +use fendermint_actor_blobs_shared::params::{GetBlobStatusParams, GetPendingBlobsParams, UpdatePowerTableParams}; +use fendermint_actor_blobs_shared::state::{BlobStatus, Power, PowerTable, Validator}; +use fendermint_actor_blobs_shared::Method::{DebitAccounts, UpdatePowerTable}; use fendermint_actor_blobs_shared::{ params::FinalizeBlobParams, Method::{FinalizeBlob, GetBlobStatus, GetPendingBlobs}, @@ -44,7 +44,7 @@ use fendermint_vm_topdown::{ }; use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::RawBytes; -use fvm_shared::address::Address; +use fvm_shared::address::{Address, Error}; use fvm_shared::clock::ChainEpoch; use fvm_shared::econ::TokenAmount; use fvm_shared::message::Message; @@ -601,6 +601,41 @@ where .map(|id| hex::encode(id.serialize_compressed())); let proposer_ref = proposer.as_deref(); + let (_configuration_number, powers) = self.gateway_caller.current_power_table(&mut state)?; + let power_table = PowerTable(powers.iter().filter_map(|validator| { + let public_key = validator.public_key.0.serialize(); + let address = Address::new_secp256k1(&public_key); + match address { + Ok(address) => { + let validator = Validator { + power: Power(validator.power.0), + address, + }; + Some(validator) + } + Err(_) => { + tracing::debug!( + "can not construct secp256k1 address from public key" + ); + None + } + } + }).collect()); + let params = RawBytes::serialize(UpdatePowerTableParams(power_table))?; + let msg = Message { + version: Default::default(), + from: system::SYSTEM_ACTOR_ADDR, + to: blobs::BLOBS_ACTOR_ADDR, + sequence: 0, + value: Default::default(), + method_num: UpdatePowerTable as u64, + params: params, + gas_limit: fvm_shared::BLOCK_GAS_LIMIT, + gas_fee_cap: Default::default(), + gas_premium: Default::default(), + }; + state.execute_implicit(msg)?; + atomically(|| { env.parent_finality_provider .set_new_finality(finality.clone(), prev_finality.clone())?; @@ -748,6 +783,9 @@ where ) -> anyhow::Result<(Self::State, Self::EndOutput)> { let (mut state, out) = self.inner.end(state).await?; + // TODO SU Wrong + let a = self.gateway_caller.current_power_table(&mut state); + // Update any component that needs to know about changes in the power table. if !out.0 .0.is_empty() { let power_updates = out From ab4033248af1af0aa525c7d9d21700ccc9c7cf16 Mon Sep 17 00:00:00 2001 From: Sergey Ukustov Date: Mon, 21 Oct 2024 11:53:01 +0400 Subject: [PATCH 04/18] drop dev comments --- fendermint/vm/interpreter/src/chain.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/fendermint/vm/interpreter/src/chain.rs b/fendermint/vm/interpreter/src/chain.rs index 9af9fb8b4..a0f7d2056 100644 --- a/fendermint/vm/interpreter/src/chain.rs +++ b/fendermint/vm/interpreter/src/chain.rs @@ -783,9 +783,6 @@ where ) -> anyhow::Result<(Self::State, Self::EndOutput)> { let (mut state, out) = self.inner.end(state).await?; - // TODO SU Wrong - let a = self.gateway_caller.current_power_table(&mut state); - // Update any component that needs to know about changes in the power table. if !out.0 .0.is_empty() { let power_updates = out @@ -804,8 +801,6 @@ where .update_power_table(power_updates.clone()) }) .await; - - // TODO Continue update power table in blobs actor } Ok(((env, state), out)) From f5ff19d10225b0e79325aee45d7196c943e45be5 Mon Sep 17 00:00:00 2001 From: Sergey Ukustov Date: Mon, 21 Oct 2024 11:53:32 +0400 Subject: [PATCH 05/18] drop dev comments --- fendermint/vm/interpreter/src/chain.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fendermint/vm/interpreter/src/chain.rs b/fendermint/vm/interpreter/src/chain.rs index a0f7d2056..0e424a625 100644 --- a/fendermint/vm/interpreter/src/chain.rs +++ b/fendermint/vm/interpreter/src/chain.rs @@ -781,7 +781,7 @@ where &self, (env, state): Self::State, ) -> anyhow::Result<(Self::State, Self::EndOutput)> { - let (mut state, out) = self.inner.end(state).await?; + let (state, out) = self.inner.end(state).await?; // Update any component that needs to know about changes in the power table. if !out.0 .0.is_empty() { From a45e47a3560ccc403eee47a1a2d1142d31c56d28 Mon Sep 17 00:00:00 2001 From: Sergey Ukustov Date: Mon, 21 Oct 2024 11:57:13 +0400 Subject: [PATCH 06/18] lint --- fendermint/actors/blobs/src/actor.rs | 15 ++++++++++----- fendermint/actors/blobs/src/state.rs | 9 +++++++-- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/fendermint/actors/blobs/src/actor.rs b/fendermint/actors/blobs/src/actor.rs index c8625face..a48c2a32e 100644 --- a/fendermint/actors/blobs/src/actor.rs +++ b/fendermint/actors/blobs/src/actor.rs @@ -4,7 +4,11 @@ use std::collections::HashSet; -use fendermint_actor_blobs_shared::params::{AddBlobParams, ApproveCreditParams, BuyCreditParams, DeleteBlobParams, FinalizeBlobParams, GetAccountParams, GetBlobParams, GetBlobStatusParams, GetPendingBlobsParams, GetStatsReturn, RevokeCreditParams, UpdatePowerTableParams}; +use fendermint_actor_blobs_shared::params::{ + AddBlobParams, ApproveCreditParams, BuyCreditParams, DeleteBlobParams, FinalizeBlobParams, + GetAccountParams, GetBlobParams, GetBlobStatusParams, GetPendingBlobsParams, GetStatsReturn, + RevokeCreditParams, UpdatePowerTableParams +}; use fendermint_actor_blobs_shared::state::{ Account, Blob, BlobStatus, CreditApproval, Hash, PublicKey, Subscription, }; @@ -112,11 +116,12 @@ impl BlobsActor { }) } - fn update_power_table(rt: &impl Runtime, params: UpdatePowerTableParams) -> Result<(), ActorError> { + fn update_power_table( + rt: &impl Runtime, + params: UpdatePowerTableParams + ) -> Result<(), ActorError> { rt.validate_immediate_caller_is(std::iter::once(&SYSTEM_ACTOR_ADDR))?; - rt.transaction(|st: &mut State, _rt| { - st.update_power_table(params.0) - }) + rt.transaction(|st: &mut State, _rt| st.update_power_table(params.0)) } fn revoke_credit(rt: &impl Runtime, params: RevokeCreditParams) -> Result<(), ActorError> { diff --git a/fendermint/actors/blobs/src/state.rs b/fendermint/actors/blobs/src/state.rs index e1546a95d..82b820b14 100644 --- a/fendermint/actors/blobs/src/state.rs +++ b/fendermint/actors/blobs/src/state.rs @@ -6,7 +6,9 @@ use std::collections::{BTreeMap, HashMap, HashSet}; use std::ops::Bound::{Included, Unbounded}; use fendermint_actor_blobs_shared::params::GetStatsReturn; -use fendermint_actor_blobs_shared::state::{Account, Blob, BlobStatus, CreditApproval, Hash, PowerTable, PublicKey, Subscription}; +use fendermint_actor_blobs_shared::state::{ + Account, Blob, BlobStatus, CreditApproval, Hash, PowerTable, PublicKey, Subscription, +}; use fil_actors_runtime::ActorError; use fvm_ipld_encoding::tuple::*; use fvm_shared::address::Address; @@ -167,7 +169,10 @@ impl State { Ok(approval.clone()) } - pub fn update_power_table(&mut self, power_table: PowerTable) -> anyhow::Result<(), ActorError> { + pub fn update_power_table( + &mut self, + power_table: PowerTable + ) -> anyhow::Result<(), ActorError> { self.power_table = power_table; Ok(()) } From b3702ce417d925e3e4f51b1129fd61fa10099e39 Mon Sep 17 00:00:00 2001 From: Sergey Ukustov Date: Mon, 21 Oct 2024 14:35:41 +0400 Subject: [PATCH 07/18] wip end block power table update --- .../vm/interpreter/src/fvm/checkpoint.rs | 12 ++--- fendermint/vm/interpreter/src/fvm/exec.rs | 45 +++++++++++++++++-- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/fendermint/vm/interpreter/src/fvm/checkpoint.rs b/fendermint/vm/interpreter/src/fvm/checkpoint.rs index ab9b2c0d5..90912b396 100644 --- a/fendermint/vm/interpreter/src/fvm/checkpoint.rs +++ b/fendermint/vm/interpreter/src/fvm/checkpoint.rs @@ -50,7 +50,7 @@ pub struct PowerUpdates(pub Vec>); pub fn maybe_create_checkpoint( gateway: &GatewayCaller, state: &mut FvmExecState, -) -> anyhow::Result> +) -> anyhow::Result> where DB: Blockstore + Sync + Send + Clone + 'static, { @@ -130,7 +130,7 @@ where config_number: next_configuration_number, }); - Ok(Some((checkpoint, power_updates))) + Ok(Some((checkpoint, curr_power_table, power_updates))) } /// Wait until CometBFT has reached a specific block height. @@ -422,7 +422,7 @@ where /// Calculate the difference between the current and the next power table, to return to CometBFT only what changed: /// * include any new validator, or validators whose power has been updated /// * include validators to be removed with a power of 0, as [expected](https://github.com/informalsystems/tendermint-rs/blob/bcc0b377812b8e53a02dff156988569c5b3c81a2/rpc/src/dialect/end_block.rs#L12-L14) by CometBFT -fn power_diff(current: PowerTable, next: PowerTable) -> PowerUpdates { +fn power_diff(current: &PowerTable, next: &PowerTable) -> PowerUpdates { let current = into_power_map(current); let next = into_power_map(next); @@ -457,10 +457,10 @@ fn power_diff(current: PowerTable, next: PowerTable) -> PowerUpdates { /// /// Unfortunately in their raw format the [`PublicKey`] does not implement `Hash`, /// so we have to use the serialized format. -fn into_power_map(value: PowerTable) -> HashMap<[u8; 65], Validator> { +fn into_power_map(value: &PowerTable) -> HashMap<[u8; 65], Validator> { value .0 - .into_iter() + .iter() .map(|v| { let k = v.public_key.0.serialize(); (k, v) @@ -478,7 +478,7 @@ mod tests { use super::{PowerTable, PowerUpdates}; fn power_update(current: PowerTable, updates: PowerUpdates) -> PowerTable { - let mut current = into_power_map(current); + let mut current = into_power_map(¤t); for v in updates.0 { let k = v.public_key.0.serialize(); diff --git a/fendermint/vm/interpreter/src/fvm/exec.rs b/fendermint/vm/interpreter/src/fvm/exec.rs index 0d84e888d..ff38f6c64 100644 --- a/fendermint/vm/interpreter/src/fvm/exec.rs +++ b/fendermint/vm/interpreter/src/fvm/exec.rs @@ -5,13 +5,17 @@ use anyhow::Context; use async_trait::async_trait; use std::collections::HashMap; -use fendermint_vm_actor_interface::{chainmetadata, cron, system}; +use fendermint_vm_actor_interface::{blobs, chainmetadata, cron, system}; use fvm::executor::ApplyRet; use fvm_ipld_blockstore::Blockstore; +use fvm_ipld_encoding::RawBytes; use fvm_shared::{address::Address, ActorID, MethodNum, BLOCK_GAS_LIMIT}; +use fvm_shared::message::Message; use ipc_observability::{emit, measure_time, observe::TracingError, Traceable}; use tendermint_rpc::Client; - +use fendermint_actor_blobs_shared::Method::UpdatePowerTable; +use fendermint_actor_blobs_shared::params::UpdatePowerTableParams; +use fendermint_actor_blobs_shared::state::{Power, PowerTable, Validator}; use crate::ExecInterpreter; use super::{ @@ -203,10 +207,45 @@ where }); }); - let updates = if let Some((checkpoint, updates)) = + let updates = if let Some((checkpoint, power_table, updates)) = checkpoint::maybe_create_checkpoint(&self.gateway, &mut state) .context("failed to create checkpoint")? { + + let power_table = PowerTable(power_table.0.iter().filter_map(|validator| { + let public_key = validator.public_key.0.serialize(); + let address = Address::new_secp256k1(&public_key); + match address { + Ok(address) => { + let validator = Validator { + power: Power(validator.power.0), + address, + }; + Some(validator) + } + Err(_) => { + tracing::debug!( + "can not construct secp256k1 address from public key" + ); + None + } + } + }).collect()); + let params = RawBytes::serialize(UpdatePowerTableParams(power_table))?; + let msg = Message { + version: Default::default(), + from: system::SYSTEM_ACTOR_ADDR, + to: blobs::BLOBS_ACTOR_ADDR, + sequence: 0, + value: Default::default(), + method_num: UpdatePowerTable as u64, + params: params, + gas_limit: fvm_shared::BLOCK_GAS_LIMIT, + gas_fee_cap: Default::default(), + gas_premium: Default::default(), + }; + state.execute_implicit(msg)?; + // Asynchronously broadcast signature, if validating. if let Some(ref ctx) = self.validator_ctx { // Do not resend past signatures. From aa0c6e09716dc35c546159dd14de554bb7903bb0 Mon Sep 17 00:00:00 2001 From: Sergey Ukustov Date: Mon, 21 Oct 2024 15:21:37 +0400 Subject: [PATCH 08/18] wip end block power table update --- fendermint/vm/interpreter/src/fvm/exec.rs | 46 ++++++++++++----------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/fendermint/vm/interpreter/src/fvm/exec.rs b/fendermint/vm/interpreter/src/fvm/exec.rs index ff38f6c64..8353abf8d 100644 --- a/fendermint/vm/interpreter/src/fvm/exec.rs +++ b/fendermint/vm/interpreter/src/fvm/exec.rs @@ -15,9 +15,9 @@ use ipc_observability::{emit, measure_time, observe::TracingError, Traceable}; use tendermint_rpc::Client; use fendermint_actor_blobs_shared::Method::UpdatePowerTable; use fendermint_actor_blobs_shared::params::UpdatePowerTableParams; -use fendermint_actor_blobs_shared::state::{Power, PowerTable, Validator}; +use fendermint_actor_blobs_shared::state::{Power, PowerTable as BlobsPowerTable, Validator}; use crate::ExecInterpreter; - +use crate::fvm::checkpoint::PowerTable; use super::{ checkpoint::{self, PowerUpdates}, observe::{CheckpointFinalized, MsgExec, MsgExecPurpose}, @@ -212,25 +212,7 @@ where .context("failed to create checkpoint")? { - let power_table = PowerTable(power_table.0.iter().filter_map(|validator| { - let public_key = validator.public_key.0.serialize(); - let address = Address::new_secp256k1(&public_key); - match address { - Ok(address) => { - let validator = Validator { - power: Power(validator.power.0), - address, - }; - Some(validator) - } - Err(_) => { - tracing::debug!( - "can not construct secp256k1 address from public key" - ); - None - } - } - }).collect()); + let power_table = prepare_blobs_power_table(power_table); let params = RawBytes::serialize(UpdatePowerTableParams(power_table))?; let msg = Message { version: Default::default(), @@ -295,3 +277,25 @@ where Ok((state, ret)) } } + +fn prepare_blobs_power_table(input: PowerTable) -> BlobsPowerTable { + BlobsPowerTable(input.0.iter().filter_map(|validator| { + let public_key = validator.public_key.0.serialize(); + let address = Address::new_secp256k1(&public_key); + match address { + Ok(address) => { + let validator = Validator { + power: Power(validator.power.0), + address, + }; + Some(validator) + } + Err(_) => { + tracing::debug!( + "can not construct secp256k1 address from public key" + ); + None + } + } + }).collect()) +} From e63e71227e3a61e514663a80ca41d56b18ef4489 Mon Sep 17 00:00:00 2001 From: Sergey Ukustov Date: Mon, 21 Oct 2024 15:40:09 +0400 Subject: [PATCH 09/18] moved powertable around --- fendermint/vm/interpreter/src/chain.rs | 43 ++----------------- .../vm/interpreter/src/fvm/checkpoint.rs | 10 ++--- 2 files changed, 9 insertions(+), 44 deletions(-) diff --git a/fendermint/vm/interpreter/src/chain.rs b/fendermint/vm/interpreter/src/chain.rs index 0e424a625..5664cbd08 100644 --- a/fendermint/vm/interpreter/src/chain.rs +++ b/fendermint/vm/interpreter/src/chain.rs @@ -17,9 +17,9 @@ use crate::{ use anyhow::{anyhow, bail, Context}; use async_stm::atomically; use async_trait::async_trait; -use fendermint_actor_blobs_shared::params::{GetBlobStatusParams, GetPendingBlobsParams, UpdatePowerTableParams}; -use fendermint_actor_blobs_shared::state::{BlobStatus, Power, PowerTable, Validator}; -use fendermint_actor_blobs_shared::Method::{DebitAccounts, UpdatePowerTable}; +use fendermint_actor_blobs_shared::params::{GetBlobStatusParams, GetPendingBlobsParams}; +use fendermint_actor_blobs_shared::state::BlobStatus; +use fendermint_actor_blobs_shared::Method::DebitAccounts; use fendermint_actor_blobs_shared::{ params::FinalizeBlobParams, Method::{FinalizeBlob, GetBlobStatus, GetPendingBlobs}, @@ -44,7 +44,7 @@ use fendermint_vm_topdown::{ }; use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::RawBytes; -use fvm_shared::address::{Address, Error}; +use fvm_shared::address::Address; use fvm_shared::clock::ChainEpoch; use fvm_shared::econ::TokenAmount; use fvm_shared::message::Message; @@ -601,41 +601,6 @@ where .map(|id| hex::encode(id.serialize_compressed())); let proposer_ref = proposer.as_deref(); - let (_configuration_number, powers) = self.gateway_caller.current_power_table(&mut state)?; - let power_table = PowerTable(powers.iter().filter_map(|validator| { - let public_key = validator.public_key.0.serialize(); - let address = Address::new_secp256k1(&public_key); - match address { - Ok(address) => { - let validator = Validator { - power: Power(validator.power.0), - address, - }; - Some(validator) - } - Err(_) => { - tracing::debug!( - "can not construct secp256k1 address from public key" - ); - None - } - } - }).collect()); - let params = RawBytes::serialize(UpdatePowerTableParams(power_table))?; - let msg = Message { - version: Default::default(), - from: system::SYSTEM_ACTOR_ADDR, - to: blobs::BLOBS_ACTOR_ADDR, - sequence: 0, - value: Default::default(), - method_num: UpdatePowerTable as u64, - params: params, - gas_limit: fvm_shared::BLOCK_GAS_LIMIT, - gas_fee_cap: Default::default(), - gas_premium: Default::default(), - }; - state.execute_implicit(msg)?; - atomically(|| { env.parent_finality_provider .set_new_finality(finality.clone(), prev_finality.clone())?; diff --git a/fendermint/vm/interpreter/src/fvm/checkpoint.rs b/fendermint/vm/interpreter/src/fvm/checkpoint.rs index 90912b396..0cabf422c 100644 --- a/fendermint/vm/interpreter/src/fvm/checkpoint.rs +++ b/fendermint/vm/interpreter/src/fvm/checkpoint.rs @@ -120,7 +120,7 @@ where debug_assert_eq!(next_power_configuration_number, next_configuration_number); - power_diff(curr_power_table, next_power_table) + power_diff(curr_power_table.clone(), next_power_table) }; emit(CheckpointCreated { @@ -422,7 +422,7 @@ where /// Calculate the difference between the current and the next power table, to return to CometBFT only what changed: /// * include any new validator, or validators whose power has been updated /// * include validators to be removed with a power of 0, as [expected](https://github.com/informalsystems/tendermint-rs/blob/bcc0b377812b8e53a02dff156988569c5b3c81a2/rpc/src/dialect/end_block.rs#L12-L14) by CometBFT -fn power_diff(current: &PowerTable, next: &PowerTable) -> PowerUpdates { +fn power_diff(current: PowerTable, next: PowerTable) -> PowerUpdates { let current = into_power_map(current); let next = into_power_map(next); @@ -457,10 +457,10 @@ fn power_diff(current: &PowerTable, next: &PowerTable) -> PowerUpdates { /// /// Unfortunately in their raw format the [`PublicKey`] does not implement `Hash`, /// so we have to use the serialized format. -fn into_power_map(value: &PowerTable) -> HashMap<[u8; 65], Validator> { +fn into_power_map(value: PowerTable) -> HashMap<[u8; 65], Validator> { value .0 - .iter() + .into_iter() .map(|v| { let k = v.public_key.0.serialize(); (k, v) @@ -478,7 +478,7 @@ mod tests { use super::{PowerTable, PowerUpdates}; fn power_update(current: PowerTable, updates: PowerUpdates) -> PowerTable { - let mut current = into_power_map(¤t); + let mut current = into_power_map(current); for v in updates.0 { let k = v.public_key.0.serialize(); From e6404a00964021ea29c3f0075d0eaf3f4512cd19 Mon Sep 17 00:00:00 2001 From: Sergey Ukustov Date: Mon, 21 Oct 2024 15:54:22 +0400 Subject: [PATCH 10/18] linter --- fendermint/actors/blobs/src/actor.rs | 4 +- fendermint/actors/blobs/src/shared.rs | 2 +- fendermint/actors/blobs/src/state.rs | 2 +- fendermint/vm/interpreter/src/fvm/exec.rs | 57 ++++++++++++----------- 4 files changed, 35 insertions(+), 30 deletions(-) diff --git a/fendermint/actors/blobs/src/actor.rs b/fendermint/actors/blobs/src/actor.rs index a48c2a32e..7a2b5abfe 100644 --- a/fendermint/actors/blobs/src/actor.rs +++ b/fendermint/actors/blobs/src/actor.rs @@ -7,7 +7,7 @@ use std::collections::HashSet; use fendermint_actor_blobs_shared::params::{ AddBlobParams, ApproveCreditParams, BuyCreditParams, DeleteBlobParams, FinalizeBlobParams, GetAccountParams, GetBlobParams, GetBlobStatusParams, GetPendingBlobsParams, GetStatsReturn, - RevokeCreditParams, UpdatePowerTableParams + RevokeCreditParams, UpdatePowerTableParams, }; use fendermint_actor_blobs_shared::state::{ Account, Blob, BlobStatus, CreditApproval, Hash, PublicKey, Subscription, @@ -118,7 +118,7 @@ impl BlobsActor { fn update_power_table( rt: &impl Runtime, - params: UpdatePowerTableParams + params: UpdatePowerTableParams, ) -> Result<(), ActorError> { rt.validate_immediate_caller_is(std::iter::once(&SYSTEM_ACTOR_ADDR))?; rt.transaction(|st: &mut State, _rt| st.update_power_table(params.0)) diff --git a/fendermint/actors/blobs/src/shared.rs b/fendermint/actors/blobs/src/shared.rs index 11c424764..4e97735a3 100644 --- a/fendermint/actors/blobs/src/shared.rs +++ b/fendermint/actors/blobs/src/shared.rs @@ -15,4 +15,4 @@ pub struct ConstructorParams { pub capacity: u64, /// The byte-blocks per atto token rate. pub debit_rate: u64, -} \ No newline at end of file +} diff --git a/fendermint/actors/blobs/src/state.rs b/fendermint/actors/blobs/src/state.rs index 82b820b14..996763e6d 100644 --- a/fendermint/actors/blobs/src/state.rs +++ b/fendermint/actors/blobs/src/state.rs @@ -171,7 +171,7 @@ impl State { pub fn update_power_table( &mut self, - power_table: PowerTable + power_table: PowerTable, ) -> anyhow::Result<(), ActorError> { self.power_table = power_table; Ok(()) diff --git a/fendermint/vm/interpreter/src/fvm/exec.rs b/fendermint/vm/interpreter/src/fvm/exec.rs index 8353abf8d..e3c33877d 100644 --- a/fendermint/vm/interpreter/src/fvm/exec.rs +++ b/fendermint/vm/interpreter/src/fvm/exec.rs @@ -5,19 +5,18 @@ use anyhow::Context; use async_trait::async_trait; use std::collections::HashMap; +use fendermint_actor_blobs_shared::params::UpdatePowerTableParams; +use fendermint_actor_blobs_shared::state::{Power, PowerTable as BlobsPowerTable, Validator}; +use fendermint_actor_blobs_shared::Method::UpdatePowerTable; use fendermint_vm_actor_interface::{blobs, chainmetadata, cron, system}; use fvm::executor::ApplyRet; use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::RawBytes; -use fvm_shared::{address::Address, ActorID, MethodNum, BLOCK_GAS_LIMIT}; use fvm_shared::message::Message; +use fvm_shared::{address::Address, ActorID, MethodNum, BLOCK_GAS_LIMIT}; use ipc_observability::{emit, measure_time, observe::TracingError, Traceable}; use tendermint_rpc::Client; -use fendermint_actor_blobs_shared::Method::UpdatePowerTable; -use fendermint_actor_blobs_shared::params::UpdatePowerTableParams; -use fendermint_actor_blobs_shared::state::{Power, PowerTable as BlobsPowerTable, Validator}; -use crate::ExecInterpreter; -use crate::fvm::checkpoint::PowerTable; + use super::{ checkpoint::{self, PowerUpdates}, observe::{CheckpointFinalized, MsgExec, MsgExecPurpose}, @@ -25,6 +24,9 @@ use super::{ BlockGasLimit, FvmMessage, FvmMessageInterpreter, }; +use crate::fvm::checkpoint::PowerTable; +use crate::ExecInterpreter; + /// The return value extended with some things from the message that /// might not be available to the caller, because of the message lookups /// and transformations that happen along the way, e.g. where we need @@ -211,7 +213,6 @@ where checkpoint::maybe_create_checkpoint(&self.gateway, &mut state) .context("failed to create checkpoint")? { - let power_table = prepare_blobs_power_table(power_table); let params = RawBytes::serialize(UpdatePowerTableParams(power_table))?; let msg = Message { @@ -279,23 +280,27 @@ where } fn prepare_blobs_power_table(input: PowerTable) -> BlobsPowerTable { - BlobsPowerTable(input.0.iter().filter_map(|validator| { - let public_key = validator.public_key.0.serialize(); - let address = Address::new_secp256k1(&public_key); - match address { - Ok(address) => { - let validator = Validator { - power: Power(validator.power.0), - address, - }; - Some(validator) - } - Err(_) => { - tracing::debug!( - "can not construct secp256k1 address from public key" - ); - None - } - } - }).collect()) + BlobsPowerTable( + input + .0 + .iter() + .filter_map(|validator| { + let public_key = validator.public_key.0.serialize(); + let address = Address::new_secp256k1(&public_key); + match address { + Ok(address) => { + let validator = Validator { + power: Power(validator.power.0), + address, + }; + Some(validator) + } + Err(_) => { + tracing::debug!("can not construct secp256k1 address from public key"); + None + } + } + }) + .collect() + ) } From ae5fa388d3d1e8127a8f5f5f9ab579d6e05a1fcf Mon Sep 17 00:00:00 2001 From: Sergey Ukustov Date: Mon, 21 Oct 2024 21:22:23 +0400 Subject: [PATCH 11/18] update power table entries --- fendermint/actors/blobs/shared/src/params.rs | 4 ++-- fendermint/actors/blobs/shared/src/state.rs | 9 ++++++++- fendermint/actors/blobs/src/state.rs | 18 ++++++++++++++---- .../vm/interpreter/src/fvm/checkpoint.rs | 4 ++-- fendermint/vm/interpreter/src/fvm/exec.rs | 13 ++++++------- 5 files changed, 32 insertions(+), 16 deletions(-) diff --git a/fendermint/actors/blobs/shared/src/params.rs b/fendermint/actors/blobs/shared/src/params.rs index 4a368f276..fec25ead6 100644 --- a/fendermint/actors/blobs/shared/src/params.rs +++ b/fendermint/actors/blobs/shared/src/params.rs @@ -9,7 +9,7 @@ use fvm_shared::clock::ChainEpoch; use fvm_shared::econ::TokenAmount; use serde::{Deserialize, Serialize}; -use crate::state::{BlobStatus, Hash, PowerTable, PublicKey}; +use crate::state::{BlobStatus, Hash, PowerTableUpdates, PublicKey}; /// Params for buying credits. #[derive(Clone, Debug, Serialize, Deserialize)] @@ -19,7 +19,7 @@ pub struct BuyCreditParams(pub Address); /// Push the power table to the actor. #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(transparent)] -pub struct UpdatePowerTableParams(pub PowerTable); +pub struct UpdatePowerTableParams(pub PowerTableUpdates); /// Params for approving credit. #[derive(Clone, Debug, Serialize_tuple, Deserialize_tuple)] diff --git a/fendermint/actors/blobs/shared/src/state.rs b/fendermint/actors/blobs/shared/src/state.rs index f41375737..c8326c452 100644 --- a/fendermint/actors/blobs/shared/src/state.rs +++ b/fendermint/actors/blobs/shared/src/state.rs @@ -153,8 +153,15 @@ pub struct Subscription { #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct Power(pub u64); +/// Power table weights stored in Blobs actor state +pub type PowerTable = HashMap; + +/// Updates of the power table: +/// - new entries, +/// - changed entries contain the current value for `power`, +/// - deleted entries contain zero for `power`. #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] -pub struct PowerTable(pub Vec); +pub struct PowerTableUpdates(pub Vec); #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct Validator { diff --git a/fendermint/actors/blobs/src/state.rs b/fendermint/actors/blobs/src/state.rs index 996763e6d..5483ab25b 100644 --- a/fendermint/actors/blobs/src/state.rs +++ b/fendermint/actors/blobs/src/state.rs @@ -7,7 +7,8 @@ use std::ops::Bound::{Included, Unbounded}; use fendermint_actor_blobs_shared::params::GetStatsReturn; use fendermint_actor_blobs_shared::state::{ - Account, Blob, BlobStatus, CreditApproval, Hash, PowerTable, PublicKey, Subscription, + Account, Blob, BlobStatus, CreditApproval, Hash, PowerTable, PowerTableUpdates, PublicKey, + Subscription, }; use fil_actors_runtime::ActorError; use fvm_ipld_encoding::tuple::*; @@ -79,7 +80,7 @@ impl State { blobs: HashMap::new(), expiries: BTreeMap::new(), pending: BTreeMap::new(), - power_table: PowerTable(vec![]), + power_table: HashMap::new(), } } @@ -171,9 +172,18 @@ impl State { pub fn update_power_table( &mut self, - power_table: PowerTable, + power_table_updates: PowerTableUpdates, ) -> anyhow::Result<(), ActorError> { - self.power_table = power_table; + power_table_updates.0.iter().for_each(|validator| { + if validator.power.0.is_zero() { + // Remove if zero + self.power_table.remove(&validator.address); + } else { + // Update or insert if nonzero + self.power_table + .insert(validator.address.clone(), validator.power.clone()); + } + }); Ok(()) } diff --git a/fendermint/vm/interpreter/src/fvm/checkpoint.rs b/fendermint/vm/interpreter/src/fvm/checkpoint.rs index 0cabf422c..797bf8eb4 100644 --- a/fendermint/vm/interpreter/src/fvm/checkpoint.rs +++ b/fendermint/vm/interpreter/src/fvm/checkpoint.rs @@ -50,7 +50,7 @@ pub struct PowerUpdates(pub Vec>); pub fn maybe_create_checkpoint( gateway: &GatewayCaller, state: &mut FvmExecState, -) -> anyhow::Result> +) -> anyhow::Result> where DB: Blockstore + Sync + Send + Clone + 'static, { @@ -130,7 +130,7 @@ where config_number: next_configuration_number, }); - Ok(Some((checkpoint, curr_power_table, power_updates))) + Ok(Some((checkpoint, power_updates))) } /// Wait until CometBFT has reached a specific block height. diff --git a/fendermint/vm/interpreter/src/fvm/exec.rs b/fendermint/vm/interpreter/src/fvm/exec.rs index e3c33877d..ebd35a28f 100644 --- a/fendermint/vm/interpreter/src/fvm/exec.rs +++ b/fendermint/vm/interpreter/src/fvm/exec.rs @@ -6,7 +6,7 @@ use async_trait::async_trait; use std::collections::HashMap; use fendermint_actor_blobs_shared::params::UpdatePowerTableParams; -use fendermint_actor_blobs_shared::state::{Power, PowerTable as BlobsPowerTable, Validator}; +use fendermint_actor_blobs_shared::state::{Power, PowerTableUpdates, Validator}; use fendermint_actor_blobs_shared::Method::UpdatePowerTable; use fendermint_vm_actor_interface::{blobs, chainmetadata, cron, system}; use fvm::executor::ApplyRet; @@ -24,7 +24,6 @@ use super::{ BlockGasLimit, FvmMessage, FvmMessageInterpreter, }; -use crate::fvm::checkpoint::PowerTable; use crate::ExecInterpreter; /// The return value extended with some things from the message that @@ -209,11 +208,11 @@ where }); }); - let updates = if let Some((checkpoint, power_table, updates)) = + let updates = if let Some((checkpoint, updates)) = checkpoint::maybe_create_checkpoint(&self.gateway, &mut state) .context("failed to create checkpoint")? { - let power_table = prepare_blobs_power_table(power_table); + let power_table = prepare_blobs_power_table(&updates); let params = RawBytes::serialize(UpdatePowerTableParams(power_table))?; let msg = Message { version: Default::default(), @@ -279,8 +278,8 @@ where } } -fn prepare_blobs_power_table(input: PowerTable) -> BlobsPowerTable { - BlobsPowerTable( +fn prepare_blobs_power_table(input: &PowerUpdates) -> PowerTableUpdates { + PowerTableUpdates( input .0 .iter() @@ -301,6 +300,6 @@ fn prepare_blobs_power_table(input: PowerTable) -> BlobsPowerTable { } } }) - .collect() + .collect(), ) } From 816adb860a7f392d17348e9c6b0eefe2c3253152 Mon Sep 17 00:00:00 2001 From: Sergey Ukustov Date: Mon, 21 Oct 2024 21:24:18 +0400 Subject: [PATCH 12/18] wip --- fendermint/vm/interpreter/src/fvm/checkpoint.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fendermint/vm/interpreter/src/fvm/checkpoint.rs b/fendermint/vm/interpreter/src/fvm/checkpoint.rs index 797bf8eb4..ab9b2c0d5 100644 --- a/fendermint/vm/interpreter/src/fvm/checkpoint.rs +++ b/fendermint/vm/interpreter/src/fvm/checkpoint.rs @@ -50,7 +50,7 @@ pub struct PowerUpdates(pub Vec>); pub fn maybe_create_checkpoint( gateway: &GatewayCaller, state: &mut FvmExecState, -) -> anyhow::Result> +) -> anyhow::Result> where DB: Blockstore + Sync + Send + Clone + 'static, { @@ -120,7 +120,7 @@ where debug_assert_eq!(next_power_configuration_number, next_configuration_number); - power_diff(curr_power_table.clone(), next_power_table) + power_diff(curr_power_table, next_power_table) }; emit(CheckpointCreated { From 2f276a2700b1aba1ce34e459afff781794bfe10b Mon Sep 17 00:00:00 2001 From: Sergey Ukustov Date: Mon, 21 Oct 2024 21:34:03 +0400 Subject: [PATCH 13/18] wip --- fendermint/vm/interpreter/src/fvm/exec.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fendermint/vm/interpreter/src/fvm/exec.rs b/fendermint/vm/interpreter/src/fvm/exec.rs index ebd35a28f..dc04d5292 100644 --- a/fendermint/vm/interpreter/src/fvm/exec.rs +++ b/fendermint/vm/interpreter/src/fvm/exec.rs @@ -17,6 +17,8 @@ use fvm_shared::{address::Address, ActorID, MethodNum, BLOCK_GAS_LIMIT}; use ipc_observability::{emit, measure_time, observe::TracingError, Traceable}; use tendermint_rpc::Client; +use crate::ExecInterpreter; + use super::{ checkpoint::{self, PowerUpdates}, observe::{CheckpointFinalized, MsgExec, MsgExecPurpose}, @@ -24,8 +26,6 @@ use super::{ BlockGasLimit, FvmMessage, FvmMessageInterpreter, }; -use crate::ExecInterpreter; - /// The return value extended with some things from the message that /// might not be available to the caller, because of the message lookups /// and transformations that happen along the way, e.g. where we need From b24651567510e622a9f8675addf217104ea80a23 Mon Sep 17 00:00:00 2001 From: Sergey Ukustov Date: Mon, 28 Oct 2024 13:10:47 +0300 Subject: [PATCH 14/18] chore: eth address --- fendermint/vm/interpreter/src/fvm/exec.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fendermint/vm/interpreter/src/fvm/exec.rs b/fendermint/vm/interpreter/src/fvm/exec.rs index dc04d5292..f31d1b212 100644 --- a/fendermint/vm/interpreter/src/fvm/exec.rs +++ b/fendermint/vm/interpreter/src/fvm/exec.rs @@ -16,7 +16,7 @@ use fvm_shared::message::Message; use fvm_shared::{address::Address, ActorID, MethodNum, BLOCK_GAS_LIMIT}; use ipc_observability::{emit, measure_time, observe::TracingError, Traceable}; use tendermint_rpc::Client; - +use fendermint_vm_actor_interface::eam::{EthAddress, EAM_ACTOR_ID}; use crate::ExecInterpreter; use super::{ @@ -285,8 +285,9 @@ fn prepare_blobs_power_table(input: &PowerUpdates) -> PowerTableUpdates { .iter() .filter_map(|validator| { let public_key = validator.public_key.0.serialize(); - let address = Address::new_secp256k1(&public_key); - match address { + let eth_address = EthAddress::from(public_key); + let delegated = Address::new_delegated(EAM_ACTOR_ID, ð_address.0); + match delegated { Ok(address) => { let validator = Validator { power: Power(validator.power.0), From cdfa26bda6a5af0bd4a926ddbb5735cd23138dcb Mon Sep 17 00:00:00 2001 From: Sergey Ukustov Date: Mon, 28 Oct 2024 19:35:55 +0300 Subject: [PATCH 15/18] chore: eth address, mapped --- fendermint/vm/interpreter/src/fvm/exec.rs | 30 ++++++++++++++--------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/fendermint/vm/interpreter/src/fvm/exec.rs b/fendermint/vm/interpreter/src/fvm/exec.rs index f31d1b212..2ca9fb991 100644 --- a/fendermint/vm/interpreter/src/fvm/exec.rs +++ b/fendermint/vm/interpreter/src/fvm/exec.rs @@ -4,7 +4,7 @@ use anyhow::Context; use async_trait::async_trait; use std::collections::HashMap; - +use ethers::abi::ParamType::Address; use fendermint_actor_blobs_shared::params::UpdatePowerTableParams; use fendermint_actor_blobs_shared::state::{Power, PowerTableUpdates, Validator}; use fendermint_actor_blobs_shared::Method::UpdatePowerTable; @@ -14,6 +14,7 @@ use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::RawBytes; use fvm_shared::message::Message; use fvm_shared::{address::Address, ActorID, MethodNum, BLOCK_GAS_LIMIT}; +use fvm_shared::address::Error; use ipc_observability::{emit, measure_time, observe::TracingError, Traceable}; use tendermint_rpc::Client; use fendermint_vm_actor_interface::eam::{EthAddress, EAM_ACTOR_ID}; @@ -285,18 +286,25 @@ fn prepare_blobs_power_table(input: &PowerUpdates) -> PowerTableUpdates { .iter() .filter_map(|validator| { let public_key = validator.public_key.0.serialize(); - let eth_address = EthAddress::from(public_key); - let delegated = Address::new_delegated(EAM_ACTOR_ID, ð_address.0); - match delegated { - Ok(address) => { - let validator = Validator { - power: Power(validator.power.0), - address, - }; - Some(validator) + match EthAddress::new_secp256k1(&public_key) { + Ok(eth_address) => { + let delegated = Address::new_delegated(EAM_ACTOR_ID, ð_address.0); + match delegated { + Ok(address) => { + let validator = Validator { + power: Power(validator.power.0), + address, + }; + Some(validator) + } + Err(_) => { + tracing::debug!("can not construct delegated address from eth_address {}", eth_address); + None + } + } } Err(_) => { - tracing::debug!("can not construct secp256k1 address from public key"); + tracing::debug!("can not construct EthAddress address from public key"); None } } From 54b3e235ad769dc4491998ace9bd2c7e39d858af Mon Sep 17 00:00:00 2001 From: Sergey Ukustov Date: Mon, 28 Oct 2024 19:40:25 +0300 Subject: [PATCH 16/18] respect linter --- fendermint/vm/interpreter/src/fvm/exec.rs | 36 +++++++---------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/fendermint/vm/interpreter/src/fvm/exec.rs b/fendermint/vm/interpreter/src/fvm/exec.rs index 2ca9fb991..a1ffe5450 100644 --- a/fendermint/vm/interpreter/src/fvm/exec.rs +++ b/fendermint/vm/interpreter/src/fvm/exec.rs @@ -3,21 +3,22 @@ use anyhow::Context; use async_trait::async_trait; -use std::collections::HashMap; -use ethers::abi::ParamType::Address; use fendermint_actor_blobs_shared::params::UpdatePowerTableParams; use fendermint_actor_blobs_shared::state::{Power, PowerTableUpdates, Validator}; use fendermint_actor_blobs_shared::Method::UpdatePowerTable; +use fendermint_vm_actor_interface::eam::{EthAddress, EAM_ACTOR_ID}; use fendermint_vm_actor_interface::{blobs, chainmetadata, cron, system}; +use futures_util::FutureExt; use fvm::executor::ApplyRet; use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::RawBytes; +use fvm_shared::address::Error; use fvm_shared::message::Message; use fvm_shared::{address::Address, ActorID, MethodNum, BLOCK_GAS_LIMIT}; -use fvm_shared::address::Error; use ipc_observability::{emit, measure_time, observe::TracingError, Traceable}; +use std::collections::HashMap; use tendermint_rpc::Client; -use fendermint_vm_actor_interface::eam::{EthAddress, EAM_ACTOR_ID}; + use crate::ExecInterpreter; use super::{ @@ -286,28 +287,13 @@ fn prepare_blobs_power_table(input: &PowerUpdates) -> PowerTableUpdates { .iter() .filter_map(|validator| { let public_key = validator.public_key.0.serialize(); - match EthAddress::new_secp256k1(&public_key) { - Ok(eth_address) => { - let delegated = Address::new_delegated(EAM_ACTOR_ID, ð_address.0); - match delegated { - Ok(address) => { - let validator = Validator { - power: Power(validator.power.0), - address, - }; - Some(validator) - } - Err(_) => { - tracing::debug!("can not construct delegated address from eth_address {}", eth_address); - None - } - } - } - Err(_) => { - tracing::debug!("can not construct EthAddress address from public key"); + EthAddress::new_secp256k1(&public_key) + .and_then(|eth_address| Address::new_delegated(EAM_ACTOR_ID, ð_address.0)) + .map(Some) + .unwrap_or_else(|_error| { + tracing::debug!("can not construct delegated address from public key"); None - } - } + }) }) .collect(), ) From 76dc1e0f2dda1e4bc6a3916c343619a2954d6ce5 Mon Sep 17 00:00:00 2001 From: Sergey Ukustov Date: Tue, 29 Oct 2024 13:59:04 +0300 Subject: [PATCH 17/18] collect validator --- fendermint/vm/interpreter/src/fvm/exec.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/fendermint/vm/interpreter/src/fvm/exec.rs b/fendermint/vm/interpreter/src/fvm/exec.rs index a1ffe5450..9508a6132 100644 --- a/fendermint/vm/interpreter/src/fvm/exec.rs +++ b/fendermint/vm/interpreter/src/fvm/exec.rs @@ -8,11 +8,9 @@ use fendermint_actor_blobs_shared::state::{Power, PowerTableUpdates, Validator}; use fendermint_actor_blobs_shared::Method::UpdatePowerTable; use fendermint_vm_actor_interface::eam::{EthAddress, EAM_ACTOR_ID}; use fendermint_vm_actor_interface::{blobs, chainmetadata, cron, system}; -use futures_util::FutureExt; use fvm::executor::ApplyRet; use fvm_ipld_blockstore::Blockstore; use fvm_ipld_encoding::RawBytes; -use fvm_shared::address::Error; use fvm_shared::message::Message; use fvm_shared::{address::Address, ActorID, MethodNum, BLOCK_GAS_LIMIT}; use ipc_observability::{emit, measure_time, observe::TracingError, Traceable}; @@ -286,6 +284,7 @@ fn prepare_blobs_power_table(input: &PowerUpdates) -> PowerTableUpdates { .0 .iter() .filter_map(|validator| { + let power = validator.power.0; let public_key = validator.public_key.0.serialize(); EthAddress::new_secp256k1(&public_key) .and_then(|eth_address| Address::new_delegated(EAM_ACTOR_ID, ð_address.0)) @@ -293,7 +292,12 @@ fn prepare_blobs_power_table(input: &PowerUpdates) -> PowerTableUpdates { .unwrap_or_else(|_error| { tracing::debug!("can not construct delegated address from public key"); None - }) + }).map(|address| { + Validator { + power: Power(power), + address + } + }) }) .collect(), ) From 4031262bdddaf468e5f80489afa87efb8353f3c5 Mon Sep 17 00:00:00 2001 From: Sergey Ukustov Date: Mon, 4 Nov 2024 12:31:24 +0300 Subject: [PATCH 18/18] lint --- fendermint/actors/blobs/src/state.rs | 2 +- fendermint/vm/interpreter/src/chain.rs | 63 +++++++++++++++++++++-- fendermint/vm/interpreter/src/fvm/exec.rs | 49 +----------------- 3 files changed, 61 insertions(+), 53 deletions(-) diff --git a/fendermint/actors/blobs/src/state.rs b/fendermint/actors/blobs/src/state.rs index 5483ab25b..a2371576a 100644 --- a/fendermint/actors/blobs/src/state.rs +++ b/fendermint/actors/blobs/src/state.rs @@ -181,7 +181,7 @@ impl State { } else { // Update or insert if nonzero self.power_table - .insert(validator.address.clone(), validator.power.clone()); + .insert(validator.address, validator.power.clone()); } }); Ok(()) diff --git a/fendermint/vm/interpreter/src/chain.rs b/fendermint/vm/interpreter/src/chain.rs index 5664cbd08..c25a84d5a 100644 --- a/fendermint/vm/interpreter/src/chain.rs +++ b/fendermint/vm/interpreter/src/chain.rs @@ -17,14 +17,17 @@ use crate::{ use anyhow::{anyhow, bail, Context}; use async_stm::atomically; use async_trait::async_trait; -use fendermint_actor_blobs_shared::params::{GetBlobStatusParams, GetPendingBlobsParams}; -use fendermint_actor_blobs_shared::state::BlobStatus; -use fendermint_actor_blobs_shared::Method::DebitAccounts; +use fendermint_actor_blobs_shared::params::{ + GetBlobStatusParams, GetPendingBlobsParams, UpdatePowerTableParams, +}; +use fendermint_actor_blobs_shared::state::{BlobStatus, Power, PowerTableUpdates, Validator}; +use fendermint_actor_blobs_shared::Method::{DebitAccounts, UpdatePowerTable}; use fendermint_actor_blobs_shared::{ params::FinalizeBlobParams, Method::{FinalizeBlob, GetBlobStatus, GetPendingBlobs}, }; use fendermint_tracing::emit; +use fendermint_vm_actor_interface::eam::{EthAddress, EAM_ACTOR_ID}; use fendermint_vm_actor_interface::{blobs, ipc, system}; use fendermint_vm_event::ParentFinalityMissingQuorum; use fendermint_vm_iroh_resolver::pool::{ @@ -746,10 +749,17 @@ where &self, (env, state): Self::State, ) -> anyhow::Result<(Self::State, Self::EndOutput)> { - let (state, out) = self.inner.end(state).await?; + let (mut state, out) = self.inner.end(state).await?; // Update any component that needs to know about changes in the power table. if !out.0 .0.is_empty() { + state.state_tree_mut().begin_transaction(); + update_blobs_power_table(&mut state, &out.0)?; + state + .state_tree_mut() + .end_transaction(true) + .expect("we just started a transaction"); + let power_updates = out .0 .0 @@ -873,6 +883,51 @@ fn relayed_bottom_up_ckpt_to_fvm( Ok(msg) } +fn update_blobs_power_table( + state: &mut FvmExecState, + input_power_updates: &PowerUpdates, +) -> anyhow::Result<()> +where + DB: Blockstore + Clone + 'static + Send + Sync, +{ + let blobs_power_table_updates = PowerTableUpdates( + input_power_updates + .0 + .iter() + .filter_map(|validator| { + let power = validator.power.0; + let public_key = validator.public_key.0.serialize(); + EthAddress::new_secp256k1(&public_key) + .and_then(|eth_address| Address::new_delegated(EAM_ACTOR_ID, ð_address.0)) + .map(Some) + .unwrap_or_else(|_error| { + tracing::debug!("can not construct delegated address from public key"); + None + }) + .map(|address| Validator { + power: Power(power), + address, + }) + }) + .collect::>(), + ); + let params = RawBytes::serialize(UpdatePowerTableParams(blobs_power_table_updates))?; + let msg = Message { + version: Default::default(), + from: system::SYSTEM_ACTOR_ADDR, + to: blobs::BLOBS_ACTOR_ADDR, + sequence: 0, + value: Default::default(), + method_num: UpdatePowerTable as u64, + params, + gas_limit: fvm_shared::BLOCK_GAS_LIMIT, + gas_fee_cap: Default::default(), + gas_premium: Default::default(), + }; + state.execute_implicit(msg)?; + Ok(()) +} + /// Get pending blobs from on chain state. /// This approach uses an implicit FVM transaction to query a read-only blockstore. fn get_pending_blobs( diff --git a/fendermint/vm/interpreter/src/fvm/exec.rs b/fendermint/vm/interpreter/src/fvm/exec.rs index 9508a6132..cb686f309 100644 --- a/fendermint/vm/interpreter/src/fvm/exec.rs +++ b/fendermint/vm/interpreter/src/fvm/exec.rs @@ -3,15 +3,9 @@ use anyhow::Context; use async_trait::async_trait; -use fendermint_actor_blobs_shared::params::UpdatePowerTableParams; -use fendermint_actor_blobs_shared::state::{Power, PowerTableUpdates, Validator}; -use fendermint_actor_blobs_shared::Method::UpdatePowerTable; -use fendermint_vm_actor_interface::eam::{EthAddress, EAM_ACTOR_ID}; -use fendermint_vm_actor_interface::{blobs, chainmetadata, cron, system}; +use fendermint_vm_actor_interface::{chainmetadata, cron, system}; use fvm::executor::ApplyRet; use fvm_ipld_blockstore::Blockstore; -use fvm_ipld_encoding::RawBytes; -use fvm_shared::message::Message; use fvm_shared::{address::Address, ActorID, MethodNum, BLOCK_GAS_LIMIT}; use ipc_observability::{emit, measure_time, observe::TracingError, Traceable}; use std::collections::HashMap; @@ -212,22 +206,6 @@ where checkpoint::maybe_create_checkpoint(&self.gateway, &mut state) .context("failed to create checkpoint")? { - let power_table = prepare_blobs_power_table(&updates); - let params = RawBytes::serialize(UpdatePowerTableParams(power_table))?; - let msg = Message { - version: Default::default(), - from: system::SYSTEM_ACTOR_ADDR, - to: blobs::BLOBS_ACTOR_ADDR, - sequence: 0, - value: Default::default(), - method_num: UpdatePowerTable as u64, - params: params, - gas_limit: fvm_shared::BLOCK_GAS_LIMIT, - gas_fee_cap: Default::default(), - gas_premium: Default::default(), - }; - state.execute_implicit(msg)?; - // Asynchronously broadcast signature, if validating. if let Some(ref ctx) = self.validator_ctx { // Do not resend past signatures. @@ -277,28 +255,3 @@ where Ok((state, ret)) } } - -fn prepare_blobs_power_table(input: &PowerUpdates) -> PowerTableUpdates { - PowerTableUpdates( - input - .0 - .iter() - .filter_map(|validator| { - let power = validator.power.0; - let public_key = validator.public_key.0.serialize(); - EthAddress::new_secp256k1(&public_key) - .and_then(|eth_address| Address::new_delegated(EAM_ACTOR_ID, ð_address.0)) - .map(Some) - .unwrap_or_else(|_error| { - tracing::debug!("can not construct delegated address from public key"); - None - }).map(|address| { - Validator { - power: Power(power), - address - } - }) - }) - .collect(), - ) -}