Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): adds a get proof endpoint in zks namespace #455

7 changes: 7 additions & 0 deletions core/lib/config/src/configs/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ pub struct Web3JsonRpcConfig {
/// The value is per active connection.
/// Note: For HTTP, rate limiting is expected to be configured on the infra level.
pub websocket_requests_per_minute_limit: Option<u32>,
/// Api of the tree API, currently used to proxy `getProof` calls to the tree
montekki marked this conversation as resolved.
Show resolved Hide resolved
pub tree_api_url: Option<String>,
}

impl Web3JsonRpcConfig {
Expand Down Expand Up @@ -123,6 +125,7 @@ impl Web3JsonRpcConfig {
max_batch_request_size: Default::default(),
max_response_body_size_mb: Default::default(),
websocket_requests_per_minute_limit: Default::default(),
tree_api_url: None,
}
}

Expand Down Expand Up @@ -205,6 +208,10 @@ impl Web3JsonRpcConfig {
// The default limit is chosen to be reasonably permissive.
self.websocket_requests_per_minute_limit.unwrap_or(6000)
}

pub fn tree_api_url(&self) -> Option<String> {
self.tree_api_url.clone()
}
}

#[derive(Debug, Deserialize, Clone, PartialEq)]
Expand Down
1 change: 1 addition & 0 deletions core/lib/env_config/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ mod tests {
max_batch_request_size: Some(200),
max_response_body_size_mb: Some(10),
websocket_requests_per_minute_limit: Some(10),
tree_api_url: None,
},
contract_verification: ContractVerificationApiConfig {
port: 3070,
Expand Down
2 changes: 2 additions & 0 deletions core/lib/web3_decl/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,6 @@ pub enum Web3Error {
InvalidFilterBlockHash,
#[error("Query returned more than {0} results. Try smaller range of blocks")]
TooManyLogs(usize),
#[error("getProofs API is not available")]
GetProofsUnavailable,
montekki marked this conversation as resolved.
Show resolved Hide resolved
}
5 changes: 2 additions & 3 deletions core/lib/zksync_core/src/api_server/tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ struct TreeProofsResponse {
}

#[derive(Debug, Serialize, Deserialize)]
pub(crate) struct TreeEntryWithProof {
pub struct TreeEntryWithProof {
slowli marked this conversation as resolved.
Show resolved Hide resolved
#[serde(default, skip_serializing_if = "H256::is_zero")]
pub value: H256,
#[serde(default, skip_serializing_if = "TreeEntryWithProof::is_zero")]
Expand Down Expand Up @@ -119,14 +119,13 @@ impl TreeApiClient for AsyncTreeReader {

/// [`TreeApiClient`] implementation requesting data from a Merkle tree API server.
#[derive(Debug, Clone)]
pub(crate) struct TreeApiHttpClient {
pub struct TreeApiHttpClient {
inner: reqwest::Client,
info_url: String,
proofs_url: String,
}

impl TreeApiHttpClient {
#[cfg(test)] // temporary measure until `TreeApiClient` is required by other components
pub fn new(url_base: &str) -> Self {
Self {
inner: reqwest::Client::new(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub fn into_jsrpc_error(err: Web3Error) -> Error {
Web3Error::SubmitTransactionError(_, _) | Web3Error::SerializationError(_) => 3.into(),
Web3Error::PubSubTimeout => 4.into(),
Web3Error::RequestTimeout => 5.into(),
Web3Error::GetProofsUnavailable => 6.into(),
},
message: match err {
Web3Error::SubmitTransactionError(_, _) => err.to_string(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use zksync_types::{
use zksync_web3_decl::types::{Filter, Log, Token};

// Local uses
use crate::web3::namespaces::ZksNamespace;
use crate::{api_server::tree::TreeEntryWithProof, web3::namespaces::ZksNamespace};
use crate::{l1_gas_price::L1GasPriceProvider, web3::backend_jsonrpc::error::into_jsrpc_error};

#[rpc]
Expand Down Expand Up @@ -111,6 +111,14 @@ pub trait ZksNamespaceT {

#[rpc(name = "zks_getLogsWithVirtualBlocks")]
fn get_logs_with_virtual_blocks(&self, filter: Filter) -> BoxFuture<Result<Vec<Log>>>;

#[rpc(name = "zks_getProof")]
fn get_proof(
&self,
address: Address,
keys: Vec<H256>,
l1_batch_number: L1BatchNumber,
) -> BoxFuture<Result<Vec<TreeEntryWithProof>>>;
slowli marked this conversation as resolved.
Show resolved Hide resolved
}

impl<G: L1GasPriceProvider + Send + Sync + 'static> ZksNamespaceT for ZksNamespace<G> {
Expand Down Expand Up @@ -308,4 +316,19 @@ impl<G: L1GasPriceProvider + Send + Sync + 'static> ZksNamespaceT for ZksNamespa
.map_err(into_jsrpc_error)
})
}

fn get_proof(
&self,
address: Address,
keys: Vec<H256>,
l1_batch_number: L1BatchNumber,
) -> BoxFuture<Result<Vec<TreeEntryWithProof>>> {
let self_ = self.clone();
Box::pin(async move {
self_
.get_proofs_impl(address, keys, l1_batch_number)
.await
.map_err(into_jsrpc_error)
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub fn into_jsrpc_error(err: Web3Error) -> ErrorObjectOwned {
Web3Error::SubmitTransactionError(_, _) | Web3Error::SerializationError(_) => 3,
Web3Error::PubSubTimeout => 4,
Web3Error::RequestTimeout => 5,
Web3Error::GetProofsUnavailable => 6,
},
match err {
Web3Error::SubmitTransactionError(ref message, _) => message.clone(),
Expand Down
12 changes: 11 additions & 1 deletion core/lib/zksync_core/src/api_server/web3/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use zksync_web3_decl::{

use crate::{
api_server::{
execution_sandbox::VmConcurrencyBarrier, tx_sender::TxSender,
execution_sandbox::VmConcurrencyBarrier, tree::TreeApiHttpClient, tx_sender::TxSender,
web3::backend_jsonrpc::batch_limiter_middleware::RateLimitMetadata,
},
l1_gas_price::L1GasPriceProvider,
Expand Down Expand Up @@ -136,6 +136,7 @@ pub struct ApiBuilder<G> {
polling_interval: Option<Duration>,
namespaces: Option<Vec<Namespace>>,
logs_translator_enabled: bool,
tree_api_url: Option<String>,
}

impl<G> ApiBuilder<G> {
Expand All @@ -159,6 +160,7 @@ impl<G> ApiBuilder<G> {
namespaces: None,
config,
logs_translator_enabled: false,
tree_api_url: None,
}
}

Expand Down Expand Up @@ -255,6 +257,11 @@ impl<G> ApiBuilder<G> {
self.logs_translator_enabled = true;
self
}

pub fn with_tree_api(mut self, tree_api_url: Option<String>) -> Self {
self.tree_api_url = tree_api_url;
self
}
}

impl<G: 'static + Send + Sync + L1GasPriceProvider> ApiBuilder<G> {
Expand All @@ -280,6 +287,9 @@ impl<G: 'static + Send + Sync + L1GasPriceProvider> ApiBuilder<G> {
api_config: self.config,
last_sealed_miniblock,
logs_translator_enabled: self.logs_translator_enabled,
tree_api: self
.tree_api_url
.map(|url| Arc::new(TreeApiHttpClient::new(url.as_str()))),
}
}

Expand Down
36 changes: 32 additions & 4 deletions core/lib/zksync_core/src/api_server/web3/namespaces/zks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,19 @@ use zksync_types::{
l2_to_l1_log::L2ToL1Log,
tokens::ETHEREUM_ADDRESS,
transaction_request::CallRequest,
L1BatchNumber, MiniblockNumber, Transaction, L1_MESSENGER_ADDRESS, L2_ETH_TOKEN_ADDRESS,
MAX_GAS_PER_PUBDATA_BYTE, REQUIRED_L1_TO_L2_GAS_PER_PUBDATA_BYTE, U256, U64,
AccountTreeId, L1BatchNumber, MiniblockNumber, StorageKey, Transaction, L1_MESSENGER_ADDRESS,
L2_ETH_TOKEN_ADDRESS, MAX_GAS_PER_PUBDATA_BYTE, REQUIRED_L1_TO_L2_GAS_PER_PUBDATA_BYTE, U256,
U64,
};
use zksync_utils::{address_to_h256, ratio_to_big_decimal_normalized};
use zksync_web3_decl::{
error::Web3Error,
types::{Address, Filter, Log, Token, H256},
};

use crate::api_server::web3::{
backend_jsonrpc::error::internal_error, metrics::API_METRICS, RpcState,
use crate::api_server::{
tree::{TreeApiClient, TreeEntryWithProof},
web3::{backend_jsonrpc::error::internal_error, metrics::API_METRICS, RpcState},
};
use crate::l1_gas_price::L1GasPriceProvider;

Expand Down Expand Up @@ -620,4 +622,30 @@ impl<G: L1GasPriceProvider> ZksNamespace<G> {
) -> Result<Vec<Log>, Web3Error> {
self.state.translate_get_logs(filter).await
}

#[tracing::instrument(skip_all)]
pub async fn get_proofs_impl(
&self,
address: Address,
keys: Vec<H256>,
l1_batch_number: L1BatchNumber,
slowli marked this conversation as resolved.
Show resolved Hide resolved
) -> Result<Vec<TreeEntryWithProof>, Web3Error> {
const METHOD_NAME: &str = "get_proofs";

let hashed_keys = keys
.into_iter()
.map(|key| StorageKey::new(AccountTreeId::new(address), key).hashed_key_u256())
.collect();

let keys = self
.state
.tree_api
.as_ref()
.ok_or(Web3Error::GetProofsUnavailable)?
.get_proofs(l1_batch_number, hashed_keys)
.await
.map_err(|err| internal_error(METHOD_NAME, err))?;
slowli marked this conversation as resolved.
Show resolved Hide resolved

Ok(keys)
}
}
3 changes: 3 additions & 0 deletions core/lib/zksync_core/src/api_server/web3/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use super::metrics::API_METRICS;
use crate::{
api_server::{
execution_sandbox::BlockArgs,
tree::TreeApiHttpClient,
tx_sender::TxSender,
web3::{
backend_jsonrpc::error::internal_error, namespaces::eth::EVENT_TOPIC_NUMBER_LIMIT,
Expand Down Expand Up @@ -167,6 +168,7 @@ impl SealedMiniblockNumber {
pub struct RpcState<E> {
pub installed_filters: Arc<RwLock<Filters>>,
pub connection_pool: ConnectionPool,
pub tree_api: Option<Arc<TreeApiHttpClient>>,
montekki marked this conversation as resolved.
Show resolved Hide resolved
pub tx_sender: TxSender<E>,
pub sync_state: Option<SyncState>,
pub(super) api_config: InternalApiConfig,
Expand All @@ -185,6 +187,7 @@ impl<E> Clone for RpcState<E> {
installed_filters: self.installed_filters.clone(),
connection_pool: self.connection_pool.clone(),
tx_sender: self.tx_sender.clone(),
tree_api: self.tree_api.clone(),
sync_state: self.sync_state.clone(),
api_config: self.api_config.clone(),
last_sealed_miniblock: self.last_sealed_miniblock.clone(),
Expand Down
1 change: 1 addition & 0 deletions core/lib/zksync_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1371,6 +1371,7 @@ async fn run_ws_api<G: L1GasPriceProvider + Send + Sync + 'static>(
)
.with_polling_interval(api_config.web3_json_rpc.pubsub_interval())
.with_threads(api_config.web3_json_rpc.ws_server_threads())
.with_tree_api(api_config.web3_json_rpc.tree_api_url())
.with_tx_sender(tx_sender, vm_barrier)
.enable_api_namespaces(Namespace::NON_DEBUG.to_vec());

Expand Down