diff --git a/Cargo.lock b/Cargo.lock index a592f88913..5066d3858b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2895,6 +2895,12 @@ dependencies = [ "serde_json", ] +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + [[package]] name = "dotenvy" version = "0.15.7" @@ -5776,8 +5782,10 @@ version = "0.5.1-alpha.0" dependencies = [ "anyhow", "assert_matches", + "base64 0.13.1", "cairo-lang-starknet", "dojo-test-utils", + "dotenv", "flate2", "futures", "hex", diff --git a/crates/katana/core/src/sequencer.rs b/crates/katana/core/src/sequencer.rs index 3aad4f65a1..08dd567ef5 100644 --- a/crates/katana/core/src/sequencer.rs +++ b/crates/katana/core/src/sequencer.rs @@ -562,4 +562,3 @@ fn filter_events_by_params( } (filtered_events, index) } - diff --git a/crates/katana/rpc/rpc-api/src/katana.rs b/crates/katana/rpc/rpc-api/src/katana.rs index 81837d256f..c4e91d90c7 100644 --- a/crates/katana/rpc/rpc-api/src/katana.rs +++ b/crates/katana/rpc/rpc-api/src/katana.rs @@ -1,14 +1,14 @@ use jsonrpsee::core::RpcResult; use jsonrpsee::proc_macros::rpc; use katana_core::accounts::Account; -use katana_primitives::FieldElement; use katana_core::hooker::HookerAddresses; +use katana_primitives::FieldElement; #[cfg_attr(not(feature = "client"), rpc(server, namespace = "katana"))] #[cfg_attr(feature = "client", rpc(client, server, namespace = "katana"))] pub trait KatanaApi { #[method(name = "setSolisAddresses")] - async fn set_addresses(&self, addresses: HookerAddresses) -> RpcResult<()>; + async fn set_addresses(&self, addresses: HookerAddresses, basic_auth: String) -> RpcResult<()>; #[method(name = "generateBlock")] async fn generate_block(&self) -> RpcResult<()>; diff --git a/crates/katana/rpc/rpc-types/src/error/katana.rs b/crates/katana/rpc/rpc-types/src/error/katana.rs index 24013845bb..2ede56823a 100644 --- a/crates/katana/rpc/rpc-types/src/error/katana.rs +++ b/crates/katana/rpc/rpc-types/src/error/katana.rs @@ -11,6 +11,8 @@ pub enum KatanaApiError { FailedToDumpState = 2, #[error("Failed to update storage.")] FailedToUpdateStorage = 3, + #[error("Authentication failed.")] + AuthenticationFailed = 4, } impl From for Error { diff --git a/crates/katana/rpc/rpc/Cargo.toml b/crates/katana/rpc/rpc/Cargo.toml index 99051c2006..25a2beb769 100644 --- a/crates/katana/rpc/rpc/Cargo.toml +++ b/crates/katana/rpc/rpc/Cargo.toml @@ -17,6 +17,7 @@ katana-rpc-types-builder = { path = "../rpc-types-builder" } katana-tasks = { path = "../../tasks" } anyhow.workspace = true +base64 = "0.13.0" cairo-lang-starknet = "2.3.1" flate2.workspace = true futures.workspace = true diff --git a/crates/katana/rpc/rpc/src/config.rs b/crates/katana/rpc/rpc/src/config.rs index fd8c0848b2..7e6ddc3526 100644 --- a/crates/katana/rpc/rpc/src/config.rs +++ b/crates/katana/rpc/rpc/src/config.rs @@ -6,6 +6,8 @@ pub struct ServerConfig { pub host: String, pub max_connections: u32, pub apis: Vec, + pub rpc_user: String, + pub rpc_password: String, } impl ServerConfig { diff --git a/crates/katana/rpc/rpc/src/katana.rs b/crates/katana/rpc/rpc/src/katana.rs index 20de07c4f7..4fb0877f7f 100644 --- a/crates/katana/rpc/rpc/src/katana.rs +++ b/crates/katana/rpc/rpc/src/katana.rs @@ -1,5 +1,5 @@ -use std::sync::Arc; - +use crate::config::ServerConfig; +use base64::decode; use jsonrpsee::core::{async_trait, Error}; use katana_core::accounts::Account; use katana_core::hooker::HookerAddresses; @@ -7,20 +7,44 @@ use katana_core::sequencer::KatanaSequencer; use katana_primitives::FieldElement; use katana_rpc_api::katana::KatanaApiServer; use katana_rpc_types::error::katana::KatanaApiError; +use std::sync::Arc; pub struct KatanaApi { sequencer: Arc, + config: ServerConfig, } impl KatanaApi { - pub fn new(sequencer: Arc) -> Self { - Self { sequencer } + pub fn new(sequencer: Arc, config: ServerConfig) -> Self { + Self { sequencer, config } + } + + fn verify_basic_auth(&self, encoded_credentials: &str) -> bool { + if let Ok(credentials) = decode(encoded_credentials) { + if let Ok(credentials_str) = String::from_utf8(credentials) { + let parts: Vec<&str> = credentials_str.split(':').collect(); + if parts.len() == 2 { + let (username, password) = (parts[0], parts[1]); + return username == self.config.rpc_user + && password == self.config.rpc_password; + } + } + } + false } } #[async_trait] impl KatanaApiServer for KatanaApi { - async fn set_addresses(&self, addresses: HookerAddresses) -> Result<(), Error> { + async fn set_addresses( + &self, + addresses: HookerAddresses, + basic_auth: String, + ) -> Result<(), Error> { + if !self.verify_basic_auth(&basic_auth) { + panic!("authentication failed"); + } + self.sequencer.set_addresses(addresses).await; Ok(()) } diff --git a/crates/katana/rpc/rpc/src/lib.rs b/crates/katana/rpc/rpc/src/lib.rs index 68383be7c6..441808085e 100644 --- a/crates/katana/rpc/rpc/src/lib.rs +++ b/crates/katana/rpc/rpc/src/lib.rs @@ -34,7 +34,7 @@ pub async fn spawn(sequencer: Arc, config: ServerConfig) -> Res methods.merge(StarknetApi::new(sequencer.clone()).into_rpc())?; } ApiKind::Katana => { - methods.merge(KatanaApi::new(sequencer.clone()).into_rpc())?; + methods.merge(KatanaApi::new(sequencer.clone(), config.clone()).into_rpc())?; } } }