diff --git a/crates/common/src/job.rs b/crates/common/src/job.rs index 16755e1..97e96b2 100644 --- a/crates/common/src/job.rs +++ b/crates/common/src/job.rs @@ -52,14 +52,12 @@ pub struct JobData { } impl JobData { - pub fn new(reward: u64, cairo_pie_compressed: Vec, registry_address: FieldElement) -> Self { + pub fn new(tip: u64, cairo_pie_compressed: Vec, registry_address: FieldElement) -> Self { let pie = Self::decompress_cairo_pie(&cairo_pie_compressed); - Self { - reward, - num_of_steps: pie.execution_resources.n_steps as u64, - cairo_pie_compressed, - registry_address, - } + let num_of_steps = pie.execution_resources.n_steps as u64; + // TODO - calculate reward based on the number of steps and the tip + let reward = num_of_steps * 100 + tip; + Self { reward, num_of_steps, cairo_pie_compressed, registry_address } } fn decompress_cairo_pie(cairo_pie_compressed: &[u8]) -> CairoPie { diff --git a/crates/common/src/node_account.rs b/crates/common/src/node_account.rs index 2fe873f..dd5ac18 100644 --- a/crates/common/src/node_account.rs +++ b/crates/common/src/node_account.rs @@ -1,6 +1,9 @@ +use std::error::Error; + use starknet::{ - accounts::{ConnectedAccount, ExecutionEncoding, SingleOwnerAccount}, + accounts::{Account, Call, ConnectedAccount, ExecutionEncoding, SingleOwnerAccount}, core::types::FieldElement, + macros::selector, providers::Provider, signers::{LocalWallet, SigningKey, VerifyingKey}, }; @@ -62,4 +65,46 @@ where pub fn get_verifying_key(&self) -> VerifyingKey { self.signing_key.verifying_key() } + + pub async fn stake( + &self, + amount: FieldElement, + registry_address: FieldElement, + ) -> Result<(), Box> { + let result = self + .account + .execute(vec![Call { + to: registry_address, + selector: selector!("stake"), + calldata: vec![amount], + }]) + .send() + .await + .unwrap(); + + println!("Stake result: {:?}", result); + Ok(()) + } + + pub async fn balance_of( + &self, + registry_address: FieldElement, + ) -> Result, Box> { + let account_address = self.account.address(); + // let call_result = self + // .get_provider() + // .call( + // FunctionCall { + // contract_address: registry_address, + // entry_point_selector: selector!("balanceOf"), + // calldata: vec![account_address], + // }, + // BlockId::Tag(BlockTag::Latest), + // ) + // .await + // .expect("failed to call contract"); + + // println!("Stake result: {:?}", call_result); + Ok(vec![FieldElement::from(100u64)]) + } } diff --git a/crates/compiler/src/cairo_compiler/mod.rs b/crates/compiler/src/cairo_compiler/mod.rs index db67146..a888ee4 100644 --- a/crates/compiler/src/cairo_compiler/mod.rs +++ b/crates/compiler/src/cairo_compiler/mod.rs @@ -3,11 +3,8 @@ use async_process::Stdio; use futures::Future; use rand::{thread_rng, Rng}; use serde_json::json; -use sharp_p2p_common::job::JobData; use sharp_p2p_common::layout::Layout; -use sharp_p2p_common::{job::Job, process::Process}; -use starknet::signers::SigningKey; -use starknet_crypto::FieldElement; +use sharp_p2p_common::process::Process; use std::io::Write; use std::path::PathBuf; use std::{io::Read, pin::Pin}; @@ -17,25 +14,28 @@ use tracing::debug; pub mod tests; -pub struct CairoCompiler<'identity> { - signing_key: &'identity SigningKey, - registry_contract: FieldElement, +pub struct CairoCompiler {} + +impl CairoCompiler { + pub fn new() -> Self { + Self {} + } } -impl<'identity> CairoCompiler<'identity> { - pub fn new(signing_key: &'identity SigningKey, registry_contract: FieldElement) -> Self { - Self { signing_key, registry_contract } +impl Default for CairoCompiler { + fn default() -> Self { + Self::new() } } -impl<'identity> CompilerController for CairoCompiler<'identity> { +impl CompilerController for CairoCompiler { fn run( &self, program_path: PathBuf, _program_input_path: PathBuf, - ) -> Result>, CompilerControllerError> { + ) -> Result, CompilerControllerError>>, CompilerControllerError> { let (terminate_tx, mut terminate_rx) = mpsc::channel::<()>(10); - let future: Pin> + '_>> = + let future: Pin, CompilerControllerError>> + '_>> = Box::pin(async move { let layout: &str = Layout::RecursiveWithPoseidon.into(); @@ -118,10 +118,7 @@ impl<'identity> CompilerController for CairoCompiler<'identity> { let mut cairo_pie_compressed = Vec::new(); cairo_pie.read_to_end(&mut cairo_pie_compressed)?; - Ok(Job::try_from_job_data( - JobData::new(0, cairo_pie_compressed, self.registry_contract), - self.signing_key, - )) + Ok(cairo_pie_compressed) }); Ok(Process::new(future, terminate_tx)) diff --git a/crates/compiler/src/cairo_compiler/tests/single_job.rs b/crates/compiler/src/cairo_compiler/tests/single_job.rs index 7fb8f73..730d0b6 100644 --- a/crates/compiler/src/cairo_compiler/tests/single_job.rs +++ b/crates/compiler/src/cairo_compiler/tests/single_job.rs @@ -3,21 +3,20 @@ use crate::{ traits::CompilerController, }; use starknet::signers::SigningKey; -use starknet_crypto::FieldElement; #[tokio::test] async fn run_single_job() { let fixture = fixture(); - let identity = SigningKey::from_random(); - let compiler = CairoCompiler::new(&identity, FieldElement::ZERO); + let _identity = SigningKey::from_random(); + let compiler = CairoCompiler::new(); compiler.run(fixture.program_path, fixture.program_input_path).unwrap().await.unwrap(); } #[tokio::test] async fn abort_single_jobs() { let fixture = fixture(); - let identity = SigningKey::from_random(); - let compiler = CairoCompiler::new(&identity, FieldElement::ZERO); + let _identity = SigningKey::from_random(); + let compiler = CairoCompiler::new(); let job = compiler.run(fixture.program_path, fixture.program_input_path).unwrap(); job.abort().await.unwrap(); job.await.unwrap_err(); diff --git a/crates/compiler/src/traits.rs b/crates/compiler/src/traits.rs index 30aeb81..c6a20e1 100644 --- a/crates/compiler/src/traits.rs +++ b/crates/compiler/src/traits.rs @@ -1,13 +1,12 @@ use crate::errors::CompilerControllerError; -use sharp_p2p_common::{job::Job, process::Process}; +use sharp_p2p_common::process::Process; use std::path::PathBuf; /* The `CompilerController` trait is responsible for taking a user's program and preparing a `Job` object. This process involves compiling the user's code and creating a Cairo PIE (Proof-of-Inclusion-Execution) object from it. - The resulting `Job` object encapsulates the necessary information for later execution by a `RunnerController`. - The `run` method accepts the paths to the program and its input, returning a `Result` containing a `Process` object. - Upon successful completion, it yields a `Job` object, ready to be utilized by a `RunnerController` to execute the program. + The resulting `Vec` object that represents the Cairo PIE is then compressed and stored in the `JobData` object. + Later, the `Job` object is then signed by the delegator's private key and sent to the network for execution. */ pub trait CompilerController { @@ -15,5 +14,5 @@ pub trait CompilerController { &self, program_path: PathBuf, program_input_path: PathBuf, - ) -> Result>, CompilerControllerError>; + ) -> Result, CompilerControllerError>>, CompilerControllerError>; } diff --git a/crates/delegator/src/main.rs b/crates/delegator/src/main.rs index d450828..86314b7 100644 --- a/crates/delegator/src/main.rs +++ b/crates/delegator/src/main.rs @@ -4,7 +4,7 @@ use futures::{stream::FuturesUnordered, StreamExt}; use libp2p::gossipsub::Event; use sharp_p2p_common::{ hash, - job::Job, + job::{Job, JobData}, network::Network, node_account::NodeAccount, process::Process, @@ -60,13 +60,15 @@ async fn main() -> Result<(), Box> { let mut message_stream = swarm_runner.run(new_job_topic, send_topic_rx); let mut event_stream = registry_handler.subscribe_events(vec!["0x0".to_string()]); - let compiler = CairoCompiler::new(node_account.get_signing_key(), registry_address); + let compiler = CairoCompiler::new(); let mut compiler_scheduler = - FuturesUnordered::>>::new(); + FuturesUnordered::, CompilerControllerError>>>::new(); // Read cairo program path from stdin let mut stdin = BufReader::new(stdin()).lines(); + // TODO: Accept dynamic tip + let tip = 10; loop { tokio::select! { @@ -104,7 +106,18 @@ async fn main() -> Result<(), Box> { Some(Ok(event_vec)) = event_stream.next() => { debug!("{:?}", event_vec); }, - Some(Ok(job)) = compiler_scheduler.next() => { + Some(Ok(cairo_pie_compressed)) = compiler_scheduler.next() => { + let job_data = JobData::new(tip, cairo_pie_compressed,registry_address); + let expected_reward = job_data.reward; + let staked_amount = node_account.balance_of(registry_address).await?; + // TODO: handle error better way + if staked_amount[0] < expected_reward.into() { + // return error + return Err("Staked amount is less than expected reward".into()); + } + let job = Job::try_from_job_data(job_data, node_account.get_signing_key()); + // info!("Job: {:?}", job.job_data.reward); + // info!("Job: {:?}", job.job_data.num_of_steps); let serialized_job = serde_json::to_string(&job).unwrap(); send_topic_tx.send(serialized_job.into()).await?; info!("Sent a new job: {}", hash!(&job)); diff --git a/crates/peer/src/registry.rs b/crates/peer/src/registry.rs index 342ec86..452eaf8 100644 --- a/crates/peer/src/registry.rs +++ b/crates/peer/src/registry.rs @@ -1,13 +1,8 @@ use async_stream::try_stream; use futures::stream::Stream; use starknet::{ - accounts::{Account, Call, SingleOwnerAccount}, - core::{ - types::{BlockId, EmittedEvent, EventFilter, FieldElement}, - utils::get_selector_from_name, - }, + core::types::{BlockId, EmittedEvent, EventFilter, FieldElement}, providers::Provider, - signers::Signer, }; use std::{error::Error, pin::Pin}; use tracing::trace; @@ -78,26 +73,4 @@ where }; Box::pin(stream) } - - pub async fn stake( - &self, - amount: FieldElement, - account: SingleOwnerAccount, - ) -> Result<(), Box> - where - S: Signer + Sync + Send + 'static, - { - let result = account - .execute(vec![Call { - to: self.registry_address, - selector: get_selector_from_name("stake").unwrap(), - calldata: vec![amount], - }]) - .send() - .await - .unwrap(); - - trace!("Stake result: {:?}", result); - Ok(()) - } }