diff --git a/rusk/src/lib/http.rs b/rusk/src/lib/http.rs index d3431c0f52..64a437c1ff 100644 --- a/rusk/src/lib/http.rs +++ b/rusk/src/lib/http.rs @@ -649,7 +649,6 @@ async fn handle_request_rues( let event = RuesDispatchEvent::from_request(req).await?; let is_binary = event.is_binary(); let mut resp_headers = event.x_headers(); - unimplemented!("Handle rues dispatch here"); let (responder, mut receiver) = mpsc::unbounded_channel(); handle_execution_rues(handler, event, responder).await; @@ -853,15 +852,11 @@ pub trait HandleRequest: Send + Sync + 'static { request: &MessageRequest, ) -> anyhow::Result; - fn can_handle_rues(&self, request: &RuesDispatchEvent) -> bool { - true - } + fn can_handle_rues(&self, request: &RuesDispatchEvent) -> bool; async fn handle_rues( &self, request: &RuesDispatchEvent, - ) -> anyhow::Result { - unimplemented!() - } + ) -> anyhow::Result; } // #[async_trait] // pub trait HandleRequestRues: Send + Sync + 'static { diff --git a/rusk/src/lib/http/chain.rs b/rusk/src/lib/http/chain.rs index 220fc3e0a6..d601c5a7e6 100644 --- a/rusk/src/lib/http/chain.rs +++ b/rusk/src/lib/http/chain.rs @@ -22,7 +22,7 @@ use graphql::{DBContext, Query}; use async_graphql::{ EmptyMutation, EmptySubscription, Name, Schema, Variables, }; -use serde_json::json; +use serde_json::{json, Map, Value}; use super::*; use crate::node::RuskNode; @@ -30,10 +30,9 @@ use crate::{VERSION, VERSION_BUILD}; const GQL_VAR_PREFIX: &str = "rusk-gqlvar-"; -fn variables_from_request(request: &MessageRequest) -> Variables { +fn variables_from_headers(headers: &Map) -> Variables { let mut var = Variables::default(); - request - .headers + headers .iter() .filter_map(|(h, v)| { let h = h.to_lowercase(); @@ -47,17 +46,52 @@ fn variables_from_request(request: &MessageRequest) -> Variables { var } + #[async_trait] impl HandleRequest for RuskNode { fn can_handle(&self, request: &MessageRequest) -> bool { matches!(request.event.to_route(), (Target::Host(_), "Chain", _)) } + + fn can_handle_rues(&self, request: &RuesDispatchEvent) -> bool { + matches!(request.uri.inner(), ("Chain", ..)) + } + async fn handle_rues( + &self, + request: &RuesDispatchEvent, + ) -> anyhow::Result { + match request.uri.inner() { + ("Chain", _, "gql") => { + self.handle_gql(&request.data, &request.headers).await + } + ("Chain", _, "propagate_tx") => { + self.propagate_tx(request.data.as_bytes()).await + } + ("Chain", _, "alive_nodes") => { + let amount = request.data.as_string().trim().parse()?; + self.alive_nodes(amount).await + } + ("Chain", _, "info") => self.get_info().await, + ("Chain", _, "gas") => { + let max_transactions = request + .data + .as_string() + .trim() + .parse::() + .unwrap_or(usize::MAX); + self.get_gas_price(max_transactions).await + } + _ => anyhow::bail!("Unsupported"), + } + } async fn handle( &self, request: &MessageRequest, ) -> anyhow::Result { match &request.event.to_route() { - (Target::Host(_), "Chain", "gql") => self.handle_gql(request).await, + (Target::Host(_), "Chain", "gql") => { + self.handle_gql(&request.event.data, &request.headers).await + } (Target::Host(_), "Chain", "propagate_tx") => { self.propagate_tx(request.event_data()).await } @@ -83,9 +117,10 @@ impl HandleRequest for RuskNode { impl RuskNode { async fn handle_gql( &self, - request: &MessageRequest, + data: &RequestData, + headers: &serde_json::Map, ) -> anyhow::Result { - let gql_query = request.event.data.as_string(); + let gql_query = data.as_string(); let schema = Schema::build(Query, EmptyMutation, EmptySubscription) .data(self.db()) @@ -95,7 +130,7 @@ impl RuskNode { return Ok(ResponseData::new(schema.sdl())); } - let variables = variables_from_request(request); + let variables = variables_from_headers(headers); let gql_query = async_graphql::Request::new(gql_query).variables(variables); diff --git a/rusk/src/lib/http/event.rs b/rusk/src/lib/http/event.rs index 208f1873ff..f731e7e513 100644 --- a/rusk/src/lib/http/event.rs +++ b/rusk/src/lib/http/event.rs @@ -755,6 +755,14 @@ impl Display for RuesEventUri { } impl RuesEventUri { + pub fn inner(&self) -> (&str, Option<&String>, &str) { + ( + self.component.as_ref(), + self.entity.as_ref(), + self.topic.as_ref(), + ) + } + pub fn parse_from_path(path: &str) -> Option { if !path.starts_with(RUES_LOCATION_PREFIX) { return None; diff --git a/rusk/src/lib/http/prover.rs b/rusk/src/lib/http/prover.rs index 936b624d74..363763d9ae 100644 --- a/rusk/src/lib/http/prover.rs +++ b/rusk/src/lib/http/prover.rs @@ -16,6 +16,22 @@ impl HandleRequest for LocalProver { fn can_handle(&self, request: &MessageRequest) -> bool { matches!(request.event.to_route(), (_, "rusk", topic) | (_, "prover", topic) if topic.starts_with("prove_")) } + fn can_handle_rues(&self, request: &RuesDispatchEvent) -> bool { + matches!(request.uri.inner(), ("prover", ..)) + } + async fn handle_rues( + &self, + request: &RuesDispatchEvent, + ) -> anyhow::Result { + let data = request.data.as_bytes(); + let response = match request.uri.inner() { + ("prover", _, "prove_execute") => { + LocalProver::prove(data).map_err(|e| anyhow!(e))? + } + _ => anyhow::bail!("Unsupported"), + }; + Ok(ResponseData::new(response)) + } async fn handle( &self, diff --git a/rusk/src/lib/http/rusk.rs b/rusk/src/lib/http/rusk.rs index 665443816e..849b9eedd4 100644 --- a/rusk/src/lib/http/rusk.rs +++ b/rusk/src/lib/http/rusk.rs @@ -14,6 +14,7 @@ use serde::Serialize; use std::sync::{mpsc, Arc}; use std::thread; use tokio::task; +use tungstenite::http::request; use execution_core::ContractId; @@ -29,6 +30,27 @@ impl HandleRequest for Rusk { (Target::Contract(_), ..) | (Target::Host(_), "rusk", _) ) } + fn can_handle_rues(&self, request: &RuesDispatchEvent) -> bool { + matches!(request.uri.inner(), ("contracts", ..) | ("rusk", ..)) + } + async fn handle_rues( + &self, + request: &RuesDispatchEvent, + ) -> anyhow::Result { + match request.uri.inner() { + ("contracts", Some(contract_id), method) => { + let feeder = request.header(RUSK_FEEDER_HEADER).is_some(); + let data = request.data.as_bytes(); + self.handle_contract_query(contract_id, method, data, feeder) + } + ("rusk", _, "preverify") => { + self.handle_preverify(request.data.as_bytes()) + } + ("rusk", _, "provisioners") => self.get_provisioners(), + ("rusk", _, "crs") => self.get_crs(), + _ => Err(anyhow::anyhow!("Unsupported")), + } + } async fn handle( &self, @@ -37,7 +59,7 @@ impl HandleRequest for Rusk { match &request.event.to_route() { (Target::Contract(_), ..) => { let feeder = request.header(RUSK_FEEDER_HEADER).is_some(); - self.handle_contract_query(&request.event, feeder) + self.handle_contract_query_legacy(&request.event, feeder) } (Target::Host(_), "rusk", "preverify") => { self.handle_preverify(request.event_data()) @@ -52,41 +74,44 @@ impl HandleRequest for Rusk { } impl Rusk { - fn handle_contract_query( + fn handle_contract_query_legacy( &self, event: &Event, feeder: bool, ) -> anyhow::Result { let contract = event.target.inner(); + let topic = &event.topic; + let data = event.data.as_bytes(); + + self.handle_contract_query(contract, topic, data, feeder) + } + fn handle_contract_query( + &self, + contract: &str, + topic: &str, + data: &[u8], + feeder: bool, + ) -> anyhow::Result { let contract_bytes = hex::decode(contract)?; let contract_bytes = contract_bytes .try_into() .map_err(|_| anyhow::anyhow!("Invalid contract bytes"))?; - + let contract_id = ContractId::from_bytes(contract_bytes); + let fn_name = topic.to_string(); + let data = data.to_vec(); if feeder { let (sender, receiver) = mpsc::channel(); let rusk = self.clone(); - let topic = event.topic.clone(); - let arg = event.data.as_bytes().to_vec(); thread::spawn(move || { - rusk.feeder_query_raw( - ContractId::from_bytes(contract_bytes), - topic, - arg, - sender, - ); + rusk.feeder_query_raw(contract_id, fn_name, data, sender); }); Ok(ResponseData::new(receiver)) } else { let data = self - .query_raw( - ContractId::from_bytes(contract_bytes), - event.topic.clone(), - event.data.as_bytes(), - ) + .query_raw(contract_id, fn_name, data) .map_err(|e| anyhow::anyhow!("{e}"))?; Ok(ResponseData::new(data)) }