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

proper delegator behavior #17

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ async-stream = "0.3.5"
bincode = "1.3"
cairo-proof-parser = { git = "https://github.com/Okm165/cairo-proof-parser", rev = "97a04bbee07330311b38d6f4cecfed3acb237626" }
cairo-vm = { git = "https://github.com/lambdaclass/cairo-vm.git" }
crypto-bigint = { version = "0.5.3", features = ["serde", "alloc"] }
futures = "0.3.30"
futures-core = "0.3.30"
futures-util = "0.3.30"
Expand Down
3 changes: 2 additions & 1 deletion crates/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ license-file.workspace = true

[dependencies]
cairo-vm.workspace = true
crypto-bigint.workspace = true
futures.workspace = true
hex.workspace = true
libp2p.workspace = true
Expand All @@ -22,4 +23,4 @@ starknet.workspace = true
strum.workspace = true
tempfile.workspace = true
thiserror.workspace = true
tokio.workspace = true
tokio.workspace = true
19 changes: 11 additions & 8 deletions crates/common/src/job.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::hash;
use cairo_vm::vm::runners::cairo_pie::CairoPie;
use crypto_bigint::U256;
use serde::{Deserialize, Serialize};
use starknet::signers::{SigningKey, VerifyingKey};
use starknet_crypto::{poseidon_hash_many, FieldElement, Signature};
Expand Down Expand Up @@ -40,26 +41,28 @@ impl Job {
.verify(&message_hash, &Signature { r: self.signature_r, s: self.signature_s })
.unwrap()
}

pub fn reward(&self) -> U256 {
self.job_data.reward
}
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct JobData {
pub reward: u64,
pub reward: U256,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had switched the type into U256 as it's compatible with deposit function call amount input. Wondering if we could also use U256 in bootloader input type @Okm165

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rkdud007 I agree.
I also confirmed that on other starknet smart-contracts values/amounts are u256 so it stays this way for sure.
Feel free to change it and other necessary things on a rust side.
I will handle the bootloader compatibility in this PR.

pub num_of_steps: u64,
#[serde(with = "chunk_felt_array")]
pub cairo_pie_compressed: Vec<u8>,
pub registry_address: FieldElement,
}

impl JobData {
pub fn new(reward: u64, cairo_pie_compressed: Vec<u8>, registry_address: FieldElement) -> Self {
pub fn new(tip: u64, cairo_pie_compressed: Vec<u8>, 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 = U256::from(num_of_steps / 10000 + tip);
Self { reward, num_of_steps, cairo_pie_compressed, registry_address }
}

fn decompress_cairo_pie(cairo_pie_compressed: &[u8]) -> CairoPie {
Expand Down
1 change: 0 additions & 1 deletion crates/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ pub mod job_witness;
pub mod layout;
pub mod macros;
pub mod network;
pub mod node_account;
pub mod process;
pub mod topic;

Expand Down
65 changes: 0 additions & 65 deletions crates/common/src/node_account.rs

This file was deleted.

36 changes: 19 additions & 17 deletions crates/compiler/src/cairo_compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -17,25 +14,33 @@ use tracing::debug;

pub mod tests;

pub struct CairoCompiler<'identity> {
signing_key: &'identity SigningKey,
registry_contract: FieldElement,
/*
Cairo Compiler
This object is responsible for compiling the cairo program and generating the PIE.
It compiles the cairo program and generates the PIE.
*/
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<Process<Result<Job, CompilerControllerError>>, CompilerControllerError> {
) -> Result<Process<Result<Vec<u8>, CompilerControllerError>>, CompilerControllerError> {
let (terminate_tx, mut terminate_rx) = mpsc::channel::<()>(10);
let future: Pin<Box<dyn Future<Output = Result<Job, CompilerControllerError>> + '_>> =
let future: Pin<Box<dyn Future<Output = Result<Vec<u8>, CompilerControllerError>> + '_>> =
Box::pin(async move {
let layout: &str = Layout::RecursiveWithPoseidon.into();

Expand Down Expand Up @@ -118,10 +123,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))
Expand Down
9 changes: 4 additions & 5 deletions crates/compiler/src/cairo_compiler/tests/single_job.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
9 changes: 4 additions & 5 deletions crates/compiler/src/traits.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
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<u8>` 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 {
fn run(
&self,
program_path: PathBuf,
program_input_path: PathBuf,
) -> Result<Process<Result<Job, CompilerControllerError>>, CompilerControllerError>;
) -> Result<Process<Result<Vec<u8>, CompilerControllerError>>, CompilerControllerError>;
}
25 changes: 18 additions & 7 deletions crates/delegator/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ 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,
topic::{gossipsub_ident_topic, Topic},
};
Expand All @@ -15,14 +14,14 @@ use sharp_p2p_compiler::{
errors::CompilerControllerError,
traits::CompilerController,
};
use sharp_p2p_peer::{registry::RegistryHandler, swarm::SwarmRunner};
use sharp_p2p_peer::{node_account::NodeAccount, registry::RegistryHandler, swarm::SwarmRunner};
use starknet::providers::{jsonrpc::HttpTransport, JsonRpcClient, Url};
use std::hash::{DefaultHasher, Hash, Hasher};
use tokio::{
io::{stdin, AsyncBufReadExt, BufReader},
sync::mpsc,
};
use tracing::{debug, info};
use tracing::{debug, error, info};
use tracing_subscriber::EnvFilter;

#[tokio::main]
Expand Down Expand Up @@ -58,15 +57,18 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {

let (send_topic_tx, send_topic_rx) = mpsc::channel::<Vec<u8>>(1000);
let mut message_stream = swarm_runner.run(new_job_topic, send_topic_rx);
// TODO: Subscribe to `WitnessMetadata` event
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::<Process<'_, Result<Job, CompilerControllerError>>>::new();
FuturesUnordered::<Process<'_, Result<Vec<u8>, CompilerControllerError>>>::new();

// Read cairo program path from stdin
let mut stdin = BufReader::new(stdin()).lines();
// TODO: Accept dynamic tip
let tip = 0;

loop {
tokio::select! {
Expand Down Expand Up @@ -104,7 +106,16 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
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 deposit_amount = node_account.balance(registry_address).await?;
if deposit_amount < expected_reward{
error!("Staked amount is less than expected reward");
return Ok(());
}
let job = Job::try_from_job_data(job_data, node_account.get_signing_key());

let serialized_job = serde_json::to_string(&job).unwrap();
send_topic_tx.send(serialized_job.into()).await?;
info!("Sent a new job: {}", hash!(&job));
Expand Down
6 changes: 4 additions & 2 deletions crates/executor/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ use sharp_p2p_common::{
job_trace::JobTrace,
job_witness::JobWitness,
network::Network,
node_account::NodeAccount,
process::Process,
topic::{gossipsub_ident_topic, Topic},
};
use sharp_p2p_peer::{registry::RegistryHandler, swarm::SwarmRunner};
use sharp_p2p_peer::{node_account::NodeAccount, registry::RegistryHandler, swarm::SwarmRunner};
use sharp_p2p_prover::{
errors::ProverControllerError, stone_prover::StoneProver, traits::ProverController,
};
Expand Down Expand Up @@ -51,6 +50,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {

let mut registry_handler =
RegistryHandler::new(JsonRpcClient::new(HttpTransport::new(Url::parse(url)?)));
let registry_address = registry_handler.get_registry_address();
let node_account = NodeAccount::new(
private_key,
account_address,
Expand All @@ -69,6 +69,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {

let (send_topic_tx, send_topic_rx) = mpsc::channel::<Vec<u8>>(1000);
let mut message_stream = swarm_runner.run(picked_job_topic, send_topic_rx);
// TODO: Subscribe to `WitnessMetadata` event
let mut event_stream = registry_handler.subscribe_events(vec!["0x0".to_string()]);

let verifying_key = node_account.get_verifying_key();
Expand Down Expand Up @@ -124,6 +125,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
},
Some(Ok(job_witness)) = prover_scheduler.next() => {
info!("Calculated job_witness: {}", hash!(&job_witness));
node_account.verify_job_witness(registry_address, job_witness).await?;
},
else => break
};
Expand Down
1 change: 1 addition & 0 deletions crates/peer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ license-file.workspace = true

[dependencies]
async-stream.workspace = true
crypto-bigint.workspace = true
futures.workspace = true
libp2p.workspace = true
starknet.workspace = true
Expand Down
1 change: 1 addition & 0 deletions crates/peer/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod node_account;
pub mod registry;
pub mod swarm;
Loading
Loading