Skip to content

Commit

Permalink
[API] Add filter support for view and simulate
Browse files Browse the repository at this point in the history
  • Loading branch information
banool committed Jan 16, 2024
1 parent 3ab2c17 commit bd75d6f
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 4 deletions.
7 changes: 4 additions & 3 deletions api/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ use crate::{
log::middleware_log, set_failpoints, state::StateApi, transactions::TransactionsApi,
view_function::ViewFunctionApi,
};
use anyhow::Context as AnyhowContext;
use aptos_config::config::{ApiConfig, NodeConfig};
use anyhow::{bail, Context as AnyhowContext};
use aptos_api_types::EntryFunctionId;
use aptos_config::config::{ApiConfig, NodeConfig, ViewFilter};
use aptos_logger::info;
use aptos_mempool::MempoolClientSender;
use aptos_storage_interface::DbReader;
Expand All @@ -23,7 +24,7 @@ use poem::{
EndpointExt, Route, Server,
};
use poem_openapi::{ContactObject, LicenseObject, OpenApiService};
use std::{net::SocketAddr, sync::Arc};
use std::{net::SocketAddr, str::FromStr, sync::Arc};
use tokio::runtime::{Handle, Runtime};

const VERSION: &str = include_str!("../doc/.version");
Expand Down
17 changes: 17 additions & 0 deletions api/src/view_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use aptos_api_types::{
U64,
};
use aptos_bcs_utils::serialize_uleb128;
use aptos_config::config::ViewFilter;
use aptos_vm::{data_cache::AsMoveResolver, AptosVM};
use itertools::Itertools;
use move_core_types::language_storage::TypeTag;
Expand Down Expand Up @@ -120,6 +121,22 @@ fn view_request(
},
};

// todo
if !context.node_config.api.view_filter.is_allowed(
&view_function.module.address(),
&view_function.module.name().as_str(),
&view_function.function.as_str(),
) {
return Err(BasicErrorWith404::bad_request_with_code_no_info(
format!(
"Function {}::{} is not allowed",
view_function.module,
view_function.function
),
AptosErrorCode::InvalidInput,
));
}

let return_vals = AptosVM::execute_view_function(
&state_view,
view_function.module.clone(),
Expand Down
51 changes: 50 additions & 1 deletion config/src/config/api_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
// Parts of the project are originally copyright © Meta Platforms, Inc.
// SPDX-License-Identifier: Apache-2.0

use super::transaction_filter_type::Filter;
use crate::{
config::{
config_sanitizer::ConfigSanitizer, gas_estimation_config::GasEstimationConfig,
node_config_loader::NodeType, Error, NodeConfig,
},
utils,
};
use aptos_types::chain_id::ChainId;
use aptos_types::{account_address::AccountAddress, chain_id::ChainId};
use serde::{Deserialize, Serialize};
use std::net::SocketAddr;

Expand Down Expand Up @@ -74,6 +75,10 @@ pub struct ApiConfig {
pub gas_estimation: GasEstimationConfig,
/// Periodically call gas estimation
pub periodic_gas_estimation_ms: Option<u64>,
/// Configuration to filter simulation requests.
pub simulation_filter: Filter,
/// Configuration to filter view function requests.
pub view_filter: ViewFilter,
}

const DEFAULT_ADDRESS: &str = "127.0.0.1";
Expand Down Expand Up @@ -119,6 +124,8 @@ impl Default for ApiConfig {
runtime_worker_multiplier: 2,
gas_estimation: GasEstimationConfig::default(),
periodic_gas_estimation_ms: Some(30_000),
simulation_filter: Filter::default(),
view_filter: ViewFilter::default(),
}
}
}
Expand Down Expand Up @@ -175,6 +182,48 @@ impl ConfigSanitizer for ApiConfig {
}
}

// This is necessary because we can't import the EntryFunctionId type from the API types.
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(rename_all = "snake_case")]
pub struct ViewFunctionId {
pub address: AccountAddress,
pub module: String,
pub function_name: String,
}

// We just accept Strings here because we can't import EntryFunctionId. We sanitize
// the values later.
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum ViewFilter {
/// Allowlist of functions. If a function is not found here, the API will refuse to
/// service the view / simulation request.
Allowlist(Vec<ViewFunctionId>),
/// Blocklist of functions. If a function is found here, the API will refuse to
/// service the view / simulation request.
Blocklist(Vec<ViewFunctionId>),
}

impl Default for ViewFilter {
fn default() -> Self {
ViewFilter::Blocklist(vec![])
}
}

impl ViewFilter {
/// Returns true if the given function is allowed by the filter.
pub fn is_allowed(&self, address: &AccountAddress, module: &str, function: &str) -> bool {
match self {
ViewFilter::Allowlist(ids) => ids.iter().any(|id| {
&id.address == address && id.module == module && id.function_name == function
}),
ViewFilter::Blocklist(ids) => !ids.iter().any(|id| {
&id.address == address && id.module == module && id.function_name == function
}),
}
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down

0 comments on commit bd75d6f

Please sign in to comment.