Skip to content

Commit

Permalink
feat: L2 network cannot filter transactions (#79)
Browse files Browse the repository at this point in the history
  • Loading branch information
JayT106 committed Oct 25, 2024
1 parent 0d78228 commit be5873e
Show file tree
Hide file tree
Showing 22 changed files with 283 additions and 31 deletions.
4 changes: 3 additions & 1 deletion core/bin/zksync_server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use zksync_config::{
fri_prover_group::FriProverGroupConfig,
house_keeper::HouseKeeperConfig,
secrets::DataAvailabilitySecrets,
tx_sink::TxSinkConfig,
BasicWitnessInputProducerConfig, ContractsConfig, DatabaseSecrets, ExperimentalVmConfig,
ExternalPriceApiClientConfig, FriProofCompressorConfig, FriProverConfig,
FriProverGatewayConfig, FriWitnessGeneratorConfig, FriWitnessVectorGeneratorConfig,
Expand Down Expand Up @@ -45,7 +46,7 @@ struct Cli {
/// Comma-separated list of components to launch.
#[arg(
long,
default_value = "api,tree,eth,state_keeper,housekeeper,commitment_generator,da_dispatcher,vm_runner_protective_reads"
default_value = "api,tree,eth,state_keeper,housekeeper,commitment_generator,da_dispatcher,vm_runner_protective_reads,deny_list"
)]
components: ComponentsToRun,
/// Path to the yaml config. If set, it will be used instead of env vars.
Expand Down Expand Up @@ -196,5 +197,6 @@ fn load_env_config() -> anyhow::Result<TempConfigStore> {
external_proof_integration_api_config: ExternalProofIntegrationApiConfig::from_env().ok(),
experimental_vm_config: ExperimentalVmConfig::from_env().ok(),
prover_job_monitor_config: None,
tx_sink_config: TxSinkConfig::from_env().ok(),
})
}
27 changes: 21 additions & 6 deletions core/bin/zksync_server/src/node_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ use zksync_node_framework::{
server::{Web3ServerLayer, Web3ServerOptionalConfig},
tree_api_client::TreeApiClientLayer,
tx_sender::{PostgresStorageCachesConfig, TxSenderLayer},
tx_sink::MasterPoolSinkLayer,
tx_sink::{DenyListPoolSinkLayer, MasterPoolSinkLayer},
},
},
service::{ZkStackService, ZkStackServiceBuilder},
Expand Down Expand Up @@ -300,7 +300,7 @@ impl MainNodeBuilder {
Ok(self)
}

fn add_tx_sender_layer(mut self) -> anyhow::Result<Self> {
fn add_tx_sender_layer(mut self, deny_list_enabled: bool) -> anyhow::Result<Self> {
let sk_config = try_load_config!(self.configs.state_keeper_config);
let rpc_config = try_load_config!(self.configs.api_config).web3_json_rpc;
let postgres_storage_caches_config = PostgresStorageCachesConfig {
Expand All @@ -310,8 +310,17 @@ impl MainNodeBuilder {
latest_values_max_block_lag: rpc_config.latest_values_max_block_lag(),
};

// On main node we always use master pool sink.
self.node.add_layer(MasterPoolSinkLayer);
let tx_sink_config = try_load_config!(self.configs.tx_sink_config);
if deny_list_enabled && tx_sink_config.deny_list().is_some() {
tracing::info!("run DenyListPoolSinkLayer {:?}", tx_sink_config.deny_list());
self.node.add_layer(DenyListPoolSinkLayer::new(
tx_sink_config.deny_list().unwrap(),
));
} else {
tracing::info!("run MasterPoolSinkLayer");
self.node.add_layer(MasterPoolSinkLayer);
}

self.node.add_layer(TxSenderLayer::new(
TxSenderConfig::new(
&sk_config,
Expand Down Expand Up @@ -667,6 +676,8 @@ impl MainNodeBuilder {
_ => 0,
});

let mut deny_list_enabled = false;

// Add "component-specific" layers.
// Note that the layers are added only once, so it's fine to add the same layer multiple times.
for component in &components {
Expand All @@ -683,15 +694,15 @@ impl MainNodeBuilder {
Component::HttpApi => {
self = self
.add_l1_gas_layer()?
.add_tx_sender_layer()?
.add_tx_sender_layer(deny_list_enabled)?
.add_tree_api_client_layer()?
.add_api_caches_layer()?
.add_http_web3_api_layer()?;
}
Component::WsApi => {
self = self
.add_l1_gas_layer()?
.add_tx_sender_layer()?
.add_tx_sender_layer(deny_list_enabled)?
.add_tree_api_client_layer()?
.add_api_caches_layer()?
.add_ws_web3_api_layer()?;
Expand Down Expand Up @@ -756,6 +767,10 @@ impl MainNodeBuilder {
Component::ExternalProofIntegrationApi => {
self = self.add_external_proof_integration_api_layer()?;
}
Component::TxSinkDenyList => {
tracing::info!("L2 denylist enabled.");
deny_list_enabled = true;
}
}
}
Ok(self.node.build())
Expand Down
2 changes: 2 additions & 0 deletions core/lib/config/src/configs/general.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::{
prover_job_monitor::ProverJobMonitorConfig,
pruning::PruningConfig,
snapshot_recovery::SnapshotRecoveryConfig,
tx_sink::TxSinkConfig,
vm_runner::{BasicWitnessInputProducerConfig, ProtectiveReadsWriterConfig},
CommitmentGeneratorConfig, ExperimentalVmConfig, ExternalPriceApiClientConfig,
FriProofCompressorConfig, FriProverConfig, FriProverGatewayConfig,
Expand Down Expand Up @@ -56,4 +57,5 @@ pub struct GeneralConfig {
pub external_proof_integration_api_config: Option<ExternalProofIntegrationApiConfig>,
pub experimental_vm_config: Option<ExperimentalVmConfig>,
pub prover_job_monitor_config: Option<ProverJobMonitorConfig>,
pub tx_sink_config: Option<TxSinkConfig>,
}
2 changes: 2 additions & 0 deletions core/lib/config/src/configs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub use self::{
secrets::{DatabaseSecrets, L1Secrets, Secrets},
snapshot_recovery::SnapshotRecoveryConfig,
snapshots_creator::SnapshotsCreatorConfig,
tx_sink::TxSinkConfig,
utils::PrometheusConfig,
vm_runner::{BasicWitnessInputProducerConfig, ProtectiveReadsWriterConfig},
};
Expand Down Expand Up @@ -66,6 +67,7 @@ pub mod pruning;
pub mod secrets;
pub mod snapshot_recovery;
pub mod snapshots_creator;
pub mod tx_sink;
pub mod utils;
pub mod vm_runner;
pub mod wallets;
Expand Down
19 changes: 19 additions & 0 deletions core/lib/config/src/configs/tx_sink.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use std::{collections::HashSet, str::FromStr};

use serde::Deserialize;
use zksync_basic_types::Address;

#[derive(Debug, Deserialize, Clone, PartialEq)]
pub struct TxSinkConfig {
pub deny_list: Option<String>,
}

impl TxSinkConfig {
pub fn deny_list(&self) -> Option<HashSet<Address>> {
self.deny_list.as_ref().map(|list| {
list.split(',')
.map(|element| Address::from_str(element).unwrap())
.collect()
})
}
}
9 changes: 9 additions & 0 deletions core/lib/config/src/testonly.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1166,6 +1166,15 @@ impl Distribution<configs::GeneralConfig> for EncodeDist {
external_proof_integration_api_config: self.sample(rng),
experimental_vm_config: self.sample(rng),
prover_job_monitor_config: self.sample(rng),
tx_sink_config: self.sample(rng),
}
}
}

impl Distribution<configs::TxSinkConfig> for EncodeDist {
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> configs::TxSinkConfig {
configs::TxSinkConfig {
deny_list: self.sample(rng),
}
}
}
1 change: 1 addition & 0 deletions core/lib/env_config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub mod object_store;
mod observability;
mod proof_data_handler;
mod snapshots_creator;
mod tx_sink;
mod utils;

mod base_token_adjuster;
Expand Down
35 changes: 35 additions & 0 deletions core/lib/env_config/src/tx_sink.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use zksync_config::configs::TxSinkConfig;

use crate::{envy_load, FromEnv};

impl FromEnv for TxSinkConfig {
fn from_env() -> anyhow::Result<Self> {
envy_load("tx_sink", "TX_SINK_")
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::test_utils::EnvMutex;

static MUTEX: EnvMutex = EnvMutex::new();

fn expected_config() -> TxSinkConfig {
TxSinkConfig {
deny_list: Some("0x1234567890abcdef".to_string()),
}
}

#[test]
fn from_env() {
let mut lock = MUTEX.lock();
let config = r#"
TX_SINK_DENY_LIST="0x1234567890abcdef"
"#;
lock.set_env(config);

let actual = TxSinkConfig::from_env().unwrap();
assert_eq!(actual, expected_config());
}
}
2 changes: 2 additions & 0 deletions core/lib/protobuf_config/src/general.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ impl ProtoRepr for proto::GeneralConfig {
),
experimental_vm_config: read_optional_repr(&self.experimental_vm),
prover_job_monitor_config: read_optional_repr(&self.prover_job_monitor),
tx_sink_config: read_optional_repr(&self.tx_sink),
})
}

Expand Down Expand Up @@ -106,6 +107,7 @@ impl ProtoRepr for proto::GeneralConfig {
.prover_job_monitor_config
.as_ref()
.map(ProtoRepr::build),
tx_sink: this.tx_sink_config.as_ref().map(ProtoRepr::build),
}
}
}
1 change: 1 addition & 0 deletions core/lib/protobuf_config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ mod snapshot_recovery;
mod snapshots_creator;
#[cfg(test)]
mod tests;
mod tx_sink;
mod utils;
mod vm_runner;
mod wallets;
Expand Down
2 changes: 2 additions & 0 deletions core/lib/protobuf_config/src/proto/config/general.proto
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import "zksync/config/external_proof_integration_api.proto";
import "zksync/core/consensus.proto";
import "zksync/config/prover_job_monitor.proto";
import "zksync/config/da_client.proto";
import "zksync/config/tx_sink.proto";

message GeneralConfig {
optional database.Postgres postgres = 1;
Expand Down Expand Up @@ -62,4 +63,5 @@ message GeneralConfig {
optional experimental.Vm experimental_vm = 44;
optional prover_job_monitor.ProverJobMonitor prover_job_monitor = 45;
optional da_client.DataAvailabilityClient da_client = 46;
optional tx_sink.TxSink tx_sink = 100;
}
7 changes: 7 additions & 0 deletions core/lib/protobuf_config/src/proto/config/tx_sink.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
syntax = "proto3";

package zksync.config.tx_sink;

message TxSink {
optional string deny_list = 1; // optional
}
1 change: 1 addition & 0 deletions core/lib/protobuf_config/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ fn test_encoding() {
rng,
);
test_encode_all_formats::<ReprConv<proto::general::GeneralConfig>>(rng);
test_encode_all_formats::<ReprConv<proto::tx_sink::TxSink>>(rng);
}

#[test]
Expand Down
19 changes: 19 additions & 0 deletions core/lib/protobuf_config/src/tx_sink.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use zksync_config::configs;
use zksync_protobuf::repr::ProtoRepr;

use crate::proto::tx_sink as proto;

impl ProtoRepr for proto::TxSink {
type Type = configs::tx_sink::TxSinkConfig;
fn read(&self) -> anyhow::Result<Self::Type> {
Ok(Self::Type {
deny_list: self.deny_list.clone(),
})
}

fn build(this: &Self::Type) -> Self {
Self {
deny_list: this.deny_list.clone(),
}
}
}
3 changes: 3 additions & 0 deletions core/lib/zksync_core_leftovers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ pub enum Component {
ExternalProofIntegrationApi,
/// VM runner-based component that allows to test experimental VM features. Doesn't save any data to Postgres.
VmPlayground,
/// Component for filtering L2 transactions by denylist
TxSinkDenyList,
}

#[derive(Debug)]
Expand Down Expand Up @@ -108,6 +110,7 @@ impl FromStr for Components {
"external_proof_integration_api" => {
Ok(Components(vec![Component::ExternalProofIntegrationApi]))
}
"deny_list" => Ok(Components(vec![Component::TxSinkDenyList])),
other => Err(format!("{} is not a valid component name", other)),
}
}
Expand Down
4 changes: 4 additions & 0 deletions core/lib/zksync_core_leftovers/src/temp_config_store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use zksync_config::{
FriProverGatewayConfig, FriWitnessGeneratorConfig, FriWitnessVectorGeneratorConfig,
GeneralConfig, ObservabilityConfig, PrometheusConfig, ProofDataHandlerConfig,
ProtectiveReadsWriterConfig, ProverJobMonitorConfig, PruningConfig, SnapshotRecoveryConfig,
TxSinkConfig,
},
ApiConfig, BaseTokenAdjusterConfig, ContractVerifierConfig, DAClientConfig, DADispatcherConfig,
DBConfig, EthConfig, EthWatchConfig, ExternalProofIntegrationApiConfig, GasAdjusterConfig,
Expand Down Expand Up @@ -81,6 +82,7 @@ pub struct TempConfigStore {
pub external_proof_integration_api_config: Option<ExternalProofIntegrationApiConfig>,
pub experimental_vm_config: Option<ExperimentalVmConfig>,
pub prover_job_monitor_config: Option<ProverJobMonitorConfig>,
pub tx_sink_config: Option<TxSinkConfig>,
}

impl TempConfigStore {
Expand Down Expand Up @@ -122,6 +124,7 @@ impl TempConfigStore {
.clone(),
experimental_vm_config: self.experimental_vm_config.clone(),
prover_job_monitor_config: self.prover_job_monitor_config.clone(),
tx_sink_config: self.tx_sink_config.clone(),
}
}

Expand Down Expand Up @@ -203,6 +206,7 @@ fn load_env_config() -> anyhow::Result<TempConfigStore> {
external_proof_integration_api_config: ExternalProofIntegrationApiConfig::from_env().ok(),
experimental_vm_config: ExperimentalVmConfig::from_env().ok(),
prover_job_monitor_config: ProverJobMonitorConfig::from_env().ok(),
tx_sink_config: TxSinkConfig::from_env().ok(),
})
}

Expand Down
40 changes: 40 additions & 0 deletions core/node/api_server/src/tx_sender/deny_list_pool_sink.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use std::collections::HashSet;

use zksync_dal::transactions_dal::L2TxSubmissionResult;
use zksync_multivm::interface::TransactionExecutionMetrics;
use zksync_types::{l2::L2Tx, Address};

use super::{master_pool_sink::MasterPoolSink, tx_sink::TxSink, SubmitTxError};
//use crate::api_server::tx_sender::master_pool_sink::MasterPoolSink;

/// Wrapper for the master DB pool that allows to submit transactions to the mempool.
#[derive(Debug)]
pub struct DenyListPoolSink {
deny_list: HashSet<Address>,
master_pool_sync: MasterPoolSink,
}

impl DenyListPoolSink {
pub fn new(master_pool_sync: MasterPoolSink, deny_list: HashSet<Address>) -> Self {
Self {
master_pool_sync,
deny_list,
}
}
}

#[async_trait::async_trait]
impl TxSink for DenyListPoolSink {
async fn submit_tx(
&self,
tx: &L2Tx,
execution_metrics: TransactionExecutionMetrics,
) -> Result<L2TxSubmissionResult, SubmitTxError> {
let address_and_nonce = (tx.initiator_account(), tx.nonce());
if self.deny_list.contains(&address_and_nonce.0) {
return Err(SubmitTxError::SenderInDenyList(tx.initiator_account()));
}

self.master_pool_sync.submit_tx(tx, execution_metrics).await
}
}
Loading

0 comments on commit be5873e

Please sign in to comment.