Skip to content

Commit

Permalink
Merge branch 'master' into v2.0-stable-merge
Browse files Browse the repository at this point in the history
  • Loading branch information
peilun-conflux committed Dec 15, 2023
2 parents 77ac3d6 + 770036f commit f4c0dc9
Show file tree
Hide file tree
Showing 9 changed files with 225 additions and 19 deletions.
21 changes: 14 additions & 7 deletions cfx_types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub use ethereum_types::{
};
use rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream};
use rlp_derive::{RlpDecodable, RlpEncodable};
use serde::ser::SerializeMap;
use serde_derive::{Deserialize, Serialize};

pub use self::space_util::AddressSpaceUtil;
Expand Down Expand Up @@ -120,8 +121,8 @@ impl AddressWithSpace {

#[derive(Default, Clone)]
pub struct SpaceMap<T> {
pub native: T,
pub evm: T,
native: T,
evm: T,
}

impl<T> SpaceMap<T> {
Expand All @@ -141,11 +142,7 @@ impl<T> SpaceMap<T> {
}
}

pub fn iter(&self) -> impl Iterator<Item = &T> {
vec![&self.native, &self.evm].into_iter()
}

pub fn map_sum<F: Fn(&T) -> usize>(&self, f: F) -> usize {
pub fn map_sum<F: FnMut(&T) -> usize>(&self, mut f: F) -> usize {
f(&self.native) + f(&self.evm)
}

Expand All @@ -161,6 +158,16 @@ impl<T> SpaceMap<T> {
}
}

impl<T: serde::Serialize> serde::Serialize for SpaceMap<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: serde::Serializer {
let mut map = serializer.serialize_map(Some(self.size()))?;
map.serialize_entry("core", &self.native)?;
map.serialize_entry("espace", &self.evm)?;
map.end()
}
}

pub mod space_util {
use super::{Address, AddressWithSpace, Space};

Expand Down
16 changes: 16 additions & 0 deletions client/src/rpc/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,22 @@ pub fn invalid_params<T: fmt::Debug>(param: &str, details: T) -> Error {
}
}

pub fn invalid_params_msg(param: &str) -> Error {
Error {
code: ErrorCode::InvalidParams,
message: format!("Invalid parameters: {}", param),
data: None,
}
}

pub fn internal_error_msg(param: &str) -> Error {
Error {
code: ErrorCode::InternalError,
message: format!("Internal error: {}", param),
data: None,
}
}

pub fn unknown_block() -> Error {
Error {
code: ErrorCode::InvalidParams,
Expand Down
147 changes: 143 additions & 4 deletions client/src/rpc/impls/cfx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@
// Conflux is free software and distributed under GNU General Public License.
// See http://www.gnu.org/licenses/

use crate::rpc::types::{
call_request::rpc_call_request_network, errors::check_rpc_address_network,
pos::PoSEpochReward, PoSEconomics, RpcAddress, SponsorInfo,
TokenSupplyInfo, VoteParamsInfo, WrapTransaction,
use crate::rpc::{
error_codes::{internal_error_msg, invalid_params_msg},
types::{
call_request::rpc_call_request_network,
errors::check_rpc_address_network, pos::PoSEpochReward, PoSEconomics,
RpcAddress, SponsorInfo, StatOnGasLoad, TokenSupplyInfo,
VoteParamsInfo, WrapTransaction,
},
};
use blockgen::BlockGenerator;
use cfx_statedb::{
Expand Down Expand Up @@ -1789,6 +1793,140 @@ impl RpcImpl {
Ok(Some(epoch_receipt_proof))
}

fn stat_on_gas_load(
&self, last_epoch: EpochNumber, time_window: U64,
) -> RpcResult<Option<StatOnGasLoad>> {
let mut stat = StatOnGasLoad::default();
stat.time_elapsed = time_window;

let block_not_found_error = || {
internal_error_msg(
"Cannot find the block by a ConsensusGraph provided hash",
)
};

let machine = self.tx_pool.machine();
let consensus = self.consensus_graph();

let mut epoch_number = match last_epoch {
EpochNumber::Earliest => {
bail!(invalid_params_msg("Cannot stat genesis"))
}
EpochNumber::Num(num) if num.is_zero() => {
bail!(invalid_params_msg("Cannot stat genesis"))
}
EpochNumber::LatestMined => bail!(invalid_params_msg(
"Epoch number is earilier than 'latest_state'"
)),
EpochNumber::Num(num) => {
let pivot_hash = consensus.get_hash_from_epoch_number(
primitives::EpochNumber::LatestState,
)?;
let epoch_number = consensus
.get_block_epoch_number(&pivot_hash)
.ok_or_else(block_not_found_error)?;
if epoch_number < num.as_u64() {
bail!(invalid_params_msg(
"Epoch number is earilier than 'latest_state'"
))
}
num.as_u64()
}
EpochNumber::LatestCheckpoint
| EpochNumber::LatestFinalized
| EpochNumber::LatestConfirmed
| EpochNumber::LatestState => {
let pivot_hash =
consensus.get_hash_from_epoch_number(last_epoch.into())?;
consensus
.get_block_epoch_number(&pivot_hash)
.ok_or_else(block_not_found_error)?
}
};

let mut last_timestamp: Option<u64> = None;

loop {
// Step 1: fetch block data
let block_hashes = consensus.get_block_hashes_by_epoch(
primitives::EpochNumber::Number(epoch_number),
)?;
let blocks = consensus
.get_data_manager()
.blocks_by_hash_list(&block_hashes, false)
.ok_or_else(block_not_found_error)?;
let pivot_block = blocks
.last()
.ok_or(internal_error_msg("Epoch without block"))?;

// Step 2: update timestamp
let timestamp = pivot_block.block_header.timestamp();
if last_timestamp.is_none() {
last_timestamp = Some(timestamp)
}
// Stop if the epoch does not in the query window.
if last_timestamp.unwrap().saturating_sub(time_window.as_u64())
> timestamp
{
break;
}

// Step 3: Stat blocks
let params = machine.params();
stat.epoch_num += 1.into();
for b in &blocks {
stat.total_block_num += 1.into();
stat.total_gas_limit += *b.block_header.gas_limit();
if params.can_pack_evm_transaction(b.block_header.height()) {
stat.espace_block_num += 1.into();
stat.espace_gas_limit += *b.block_header.gas_limit()
/ params.evm_transaction_gas_ratio;
}
}

// Step 4: Stat transactions
for b in &blocks {
// Fetch execution info or return not found.
let exec_info =
match consensus.get_block_execution_info(&b.hash()) {
None => bail!(internal_error_msg(
"Cannot fetch block receipt with checked input params"
)),
Some((res, _)) => res.1,
};

for (receipt, tx) in exec_info
.block_receipts
.receipts
.iter()
.zip(&b.transactions)
{
let space = tx.space();
if receipt.outcome_status == TransactionOutcome::Skipped {
*stat.skipped_tx_count.in_space_mut(space) += 1.into();
*stat.skipped_tx_gas_limit.in_space_mut(space) +=
*tx.gas_limit();
} else {
*stat.confirmed_tx_count.in_space_mut(space) +=
1.into();
*stat.confirmed_tx_gas_limit.in_space_mut(space) +=
*tx.gas_limit();
*stat.tx_gas_charged.in_space_mut(space) +=
receipt.gas_fee / tx.gas_price();
}
}
}

// Goto Next Epoch
if epoch_number > 0 {
epoch_number -= 1;
} else {
break;
}
}
Ok(Some(stat))
}

fn transactions_by_epoch(
&self, epoch_number: U64,
) -> JsonRpcResult<Vec<WrapTransaction>> {
Expand Down Expand Up @@ -2265,6 +2403,7 @@ impl LocalRpc for LocalRpcImpl {
fn consensus_graph_state(&self) -> JsonRpcResult<ConsensusGraphStates>;
fn epoch_receipts(&self, epoch: BlockHashOrEpochNumber, include_eth_recepits: Option<bool>,) -> JsonRpcResult<Option<Vec<Vec<RpcReceipt>>>>;
fn epoch_receipt_proof_by_transaction(&self, tx_hash: H256) -> JsonRpcResult<Option<EpochReceiptProof>>;
fn stat_on_gas_load(&self, last_epoch: EpochNumber, time_window: U64) -> JsonRpcResult<Option<StatOnGasLoad>>;
fn sync_graph_state(&self) -> JsonRpcResult<SyncGraphStates>;
fn send_transaction(
&self, tx: SendTxRequest, password: Option<String>) -> BoxFuture<H256>;
Expand Down
8 changes: 5 additions & 3 deletions client/src/rpc/impls/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,10 @@ use crate::{
CheckBalanceAgainstTransactionResponse, ConsensusGraphStates,
EpochNumber, EstimateGasAndCollateralResponse, Log as RpcLog,
PoSEconomics, Receipt as RpcReceipt, RewardInfo as RpcRewardInfo,
RpcAddress, SendTxRequest, SponsorInfo, Status as RpcStatus,
StorageCollateralInfo, SyncGraphStates, TokenSupplyInfo,
Transaction as RpcTransaction, VoteParamsInfo, WrapTransaction,
RpcAddress, SendTxRequest, SponsorInfo, StatOnGasLoad,
Status as RpcStatus, StorageCollateralInfo, SyncGraphStates,
TokenSupplyInfo, Transaction as RpcTransaction, VoteParamsInfo,
WrapTransaction,
},
RpcBoxFuture, RpcResult,
},
Expand Down Expand Up @@ -1256,6 +1257,7 @@ impl LocalRpc for DebugRpcImpl {
fn current_sync_phase(&self) -> JsonRpcResult<String>;
fn epoch_receipts(&self, epoch: BlockHashOrEpochNumber, include_eth_recepits: Option<bool>) -> JsonRpcResult<Option<Vec<Vec<RpcReceipt>>>>;
fn epoch_receipt_proof_by_transaction(&self, tx_hash: H256) -> JsonRpcResult<Option<EpochReceiptProof>>;
fn stat_on_gas_load(&self, epoch: EpochNumber, time_window: U64) -> JsonRpcResult<Option<StatOnGasLoad>>;
fn sign_transaction(&self, tx: SendTxRequest, password: Option<String>) -> JsonRpcResult<String>;
fn sync_graph_state(&self) -> JsonRpcResult<SyncGraphStates>;
fn transactions_by_epoch(&self, epoch_number: U64) -> JsonRpcResult<Vec<WrapTransaction>>;
Expand Down
10 changes: 8 additions & 2 deletions client/src/rpc/traits/cfx_space/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@

use crate::rpc::types::{
BlockHashOrEpochNumber, Bytes as RpcBytes, ConsensusGraphStates,
Receipt as RpcReceipt, RpcAddress, SendTxRequest, SyncGraphStates,
Transaction as RpcTransaction, WrapTransaction,
EpochNumber, Receipt as RpcReceipt, RpcAddress, SendTxRequest,
StatOnGasLoad, SyncGraphStates, Transaction as RpcTransaction,
WrapTransaction,
};
use cfx_types::{H256, H520, U128, U64};
use cfxcore::verification::EpochReceiptProof;
Expand Down Expand Up @@ -112,6 +113,11 @@ pub trait LocalRpc {
include_eth_recepits: Option<bool>,
) -> JsonRpcResult<Option<Vec<Vec<RpcReceipt>>>>;

#[rpc(name = "debug_statOnGasLoad")]
fn stat_on_gas_load(
&self, last_epoch: EpochNumber, time_window: U64,
) -> JsonRpcResult<Option<StatOnGasLoad>>;

#[rpc(name = "debug_getEpochReceiptProofByTransaction")]
fn epoch_receipt_proof_by_transaction(
&self, tx_hash: H256,
Expand Down
2 changes: 2 additions & 0 deletions client/src/rpc/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub mod pubsub;
mod receipt;
mod reward_info;
mod sponsor_info;
mod stat_on_gas_load;
mod status;
mod storage_collateral_info;
mod sync_graph_states;
Expand Down Expand Up @@ -52,6 +53,7 @@ pub use self::{
receipt::Receipt,
reward_info::RewardInfo,
sponsor_info::SponsorInfo,
stat_on_gas_load::StatOnGasLoad,
status::Status,
storage_collateral_info::StorageCollateralInfo,
sync_graph_states::SyncGraphStates,
Expand Down
20 changes: 20 additions & 0 deletions client/src/rpc/types/stat_on_gas_load.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use cfx_types::{SpaceMap, U256, U64};
use serde_derive::Serialize;

#[derive(Default, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct StatOnGasLoad {
pub time_elapsed: U64,

pub epoch_num: U64,
pub total_block_num: U64,
pub espace_block_num: U64,
pub total_gas_limit: U256,
pub espace_gas_limit: U256,

pub skipped_tx_count: SpaceMap<U64>,
pub confirmed_tx_count: SpaceMap<U64>,
pub skipped_tx_gas_limit: SpaceMap<U256>,
pub confirmed_tx_gas_limit: SpaceMap<U256>,
pub tx_gas_charged: SpaceMap<U256>,
}
Loading

0 comments on commit f4c0dc9

Please sign in to comment.