Skip to content

Commit

Permalink
🚧 init nostr subsription
Browse files Browse the repository at this point in the history
  • Loading branch information
AbdelStark committed Jul 16, 2024
1 parent 1b64376 commit 92ccf4c
Show file tree
Hide file tree
Showing 12 changed files with 275 additions and 36 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@ Cargo.lock
# Added by cargo

/target

# Ignore macos specific files
.DS_Store
8 changes: 8 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ resolver = "2"
[workspace.package]
version = "0.1.1"
edition = "2021"
authors = ["@AbdelStark"]
homepage = "https://github.com/AbdelStark/askeladd"
repository = "https://github.com/AbdelStark/askeladd.git"
license = "MIT"


[workspace.dependencies]
stwo-prover = { git = "https://github.com/starkware-libs/stwo.git" }
tokio = { version = "1", default-features = false }
tracing = { version = "0.1", default-features = false }
tracing-subscriber = "0.3"
17 changes: 17 additions & 0 deletions crates/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,20 @@ edition.workspace = true

[dependencies]
askeladd-core = { path = "../core" }
nostr-sdk = "0.32.0"
tokio = { version = "1", default-features = false }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
uuid = { version = "1.3", features = ["v4"] }

[[bin]]
name = "user_cli"
path = "src/user_cli.rs"

[[bin]]
name = "prover_agent"
path = "src/prover_agent.rs"

[dev-dependencies]
tokio = { workspace = true, features = ["macros"] }
tracing-subscriber = { workspace = true, features = ["env-filter"] }
19 changes: 0 additions & 19 deletions crates/cli/src/main.rs

This file was deleted.

69 changes: 69 additions & 0 deletions crates/cli/src/prover_agent.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use askeladd_core::prover_service::ProverService;
use askeladd_core::types::FibonnacciProvingRequest;
use nostr_sdk::prelude::*;

const SUBSCRIBED_RELAYS: &[&str] = &[
"wss://nostr.oxtr.dev",
"wss://relay.damus.io",
"wss://nostr.openchain.fr",
];
const PROVING_REQ_SUB_ID: &str = "askeladd_proving_request";

#[tokio::main]
async fn main() -> Result<()> {
let opts = Options::new().wait_for_send(false);
let client = Client::builder().opts(opts).build();

for relay in SUBSCRIBED_RELAYS {
client.add_relay(Url::parse(relay).unwrap()).await?;
}

client.connect().await;

let proving_req_sub_id = SubscriptionId::new(PROVING_REQ_SUB_ID);
let filter = Filter::new().kind(Kind::TextNote);

client
.subscribe_with_id(proving_req_sub_id.clone(), vec![filter], None)
.await;

let proving_service: ProverService = Default::default();

client
.handle_notifications(|notification| async {
if let RelayPoolNotification::Event {
subscription_id,
event,
..
} = notification
{
if subscription_id == proving_req_sub_id {
println!("Proving request received: {:?}", event);

// Deserialize the request
if let Ok(request) =
serde_json::from_str::<FibonnacciProvingRequest>(&event.content)
{
// Generate the proof
match proving_service.generate_proof(request) {
Ok(response) => {
// Serialize the response to JSON
let response_json = serde_json::to_string(&response)?;

// Publish the proving response
let tags = vec![];
let event_id =
client.publish_text_note(response_json, tags).await?;
println!("Proving response published with event ID: {}", event_id);
}
Err(e) => println!("Proof generation failed: {}", e),
}
}
}
}
Ok(false)
})
.await?;

Ok(())
}
82 changes: 82 additions & 0 deletions crates/cli/src/user_cli.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
use askeladd_core::types::{FibonnacciProvingRequest, FibonnacciProvingResponse};
use askeladd_core::verifier_service::VerifierService;
use nostr_sdk::prelude::*;
use uuid::Uuid;

const SUBSCRIBED_RELAYS: &[&str] = &[
"wss://nostr.oxtr.dev",
"wss://relay.damus.io",
"wss://nostr.openchain.fr",
];
const PROVING_RESP_SUB_ID: &str = "askeladd_proving_response";

#[tokio::main]
async fn main() -> Result<()> {
let opts = Options::new().wait_for_send(false);
let client = Client::builder().opts(opts).build();

for relay in SUBSCRIBED_RELAYS {
client.add_relay(Url::parse(relay).unwrap()).await?;
}

client.connect().await;

// Generate a unique request ID
let request_id = Uuid::new_v4().to_string();

// Create a proving request
let proving_request = FibonnacciProvingRequest {
request_id: request_id.clone(),
log_size: 5,
claim: 443693538,
};

// Serialize the request to JSON
let request_json = serde_json::to_string(&proving_request)?;

// Publish the proving request
let event_id = client.publish_text_note(request_json, []).await?;

println!("Proving request published with event ID: {}", event_id);

// Subscribe to proving responses
let proving_resp_sub_id = SubscriptionId::new(PROVING_RESP_SUB_ID);
let filter = Filter::new().kind(Kind::TextNote).since(Timestamp::now());

client
.subscribe_with_id(proving_resp_sub_id.clone(), vec![filter], None)
.await;

// Handle subscription notifications
client
.handle_notifications(|notification| async {
if let RelayPoolNotification::Event {
subscription_id,
event,
..
} = notification
{
if subscription_id == proving_resp_sub_id {
println!("Proving response received: {:?}", event);

// Deserialize the response
if let Ok(response) =
serde_json::from_str::<FibonnacciProvingResponse>(&event.content)
{
// Verify the proof
let verifier_service: VerifierService = Default::default();
match verifier_service.verify_proof(response) {
Ok(_) => println!("Proof successfully verified"),
Err(e) => println!("Proof verification failed: {}", e),
}
return Ok(true); // Stop listening after receiving and verifying the
// response
}
}
}
Ok(false)
})
.await?;

Ok(())
}
3 changes: 3 additions & 0 deletions crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@ edition.workspace = true

[dependencies]
stwo-prover.workspace = true
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
thiserror = "1.0.62"
1 change: 1 addition & 0 deletions crates/core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod prover_service;
pub mod types;
pub mod verifier_service;
pub mod wrappers;
9 changes: 5 additions & 4 deletions crates/core/src/prover_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ impl ProverService {
) -> Result<FibonnacciProvingResponse, ProvingError> {
let fib = Fibonacci::new(request.log_size, BaseField::from(request.claim));
match fib.prove() {
Ok(proof) => Ok(FibonnacciProvingResponse {
Ok(proof) => Ok(FibonnacciProvingResponse::new(
request.request_id,
request.log_size,
request.claim,
proof,
log_size: request.log_size,
claim: request.claim,
}),
)),
Err(e) => Err(e),
}
}
Expand Down
31 changes: 24 additions & 7 deletions crates/core/src/types.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,35 @@
use serde::{Deserialize, Serialize};
use stwo_prover::core::prover::StarkProof;

/// A request to generate a proof for a Fibonnacci sequence.
use crate::wrappers::{ConversionError, StarkProofWrapper};

#[derive(Debug, Serialize, Deserialize)]
pub struct FibonnacciProvingRequest {
/// The size of the log to generate.
pub request_id: String,
pub log_size: u32,
/// The claim to be proved.
pub claim: u32,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct FibonnacciProvingResponse {
/// The size of the log to generate.
pub request_id: String,
pub log_size: u32,
/// The claim to be proved.
pub claim: u32,
/// The proof generated for the request.
pub proof: StarkProof,
pub proof: StarkProofWrapper,
}

impl FibonnacciProvingResponse {
pub fn new(request_id: String, log_size: u32, claim: u32, proof: StarkProof) -> Self {
Self {
request_id,
log_size,
claim,
proof: proof.into(),
}
}

pub fn into_stark_proof(self) -> Result<(String, u32, u32, StarkProof), ConversionError> {
let proof = self.proof.try_into().unwrap();
Ok((self.request_id, self.log_size, self.claim, proof))
}
}
19 changes: 13 additions & 6 deletions crates/core/src/verifier_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,23 @@ use stwo_prover::core::prover::VerificationError;
use stwo_prover::examples::fibonacci::Fibonacci;

use crate::types::FibonnacciProvingResponse;
use crate::wrappers::ConversionError;

#[derive(Debug, thiserror::Error)]
pub enum VerifierError {
#[error(transparent)]
Verification(#[from] VerificationError),
#[error(transparent)]
Conversion(#[from] ConversionError),
}

#[derive(Debug, Default)]
pub struct VerifierService {}

impl VerifierService {
pub fn verify_proof(
&self,
response: FibonnacciProvingResponse,
) -> Result<(), VerificationError> {
let fib = Fibonacci::new(response.log_size, BaseField::from(response.claim));
fib.verify(response.proof)
pub fn verify_proof(&self, response: FibonnacciProvingResponse) -> Result<(), VerifierError> {
let (_, log_size, claim, proof) = response.into_stark_proof()?;
let fib = Fibonacci::new(log_size, BaseField::from(claim));
fib.verify(proof).map_err(VerifierError::Verification)
}
}
50 changes: 50 additions & 0 deletions crates/core/src/wrappers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use std::mem;

use serde::{Deserialize, Serialize};
use stwo_prover::core::prover::StarkProof;

#[derive(Debug, Serialize, Deserialize)]
pub struct StarkProofWrapper(Vec<u8>);

/// Warning: This is a hack to get around the fact that StarkProof is not serializable.
/// TODO: Remove this when StarkProof is serializable.
impl From<StarkProof> for StarkProofWrapper {
fn from(proof: StarkProof) -> Self {
let bytes = unsafe {
let ptr = &proof as *const StarkProof as *const u8;
std::slice::from_raw_parts(ptr, mem::size_of::<StarkProof>())
};
StarkProofWrapper(bytes.to_vec())
}
}

/// Warning: This is a hack to get around the fact that StarkProof is not serializable.
/// TODO: Remove this when StarkProof is serializable.
impl TryFrom<StarkProofWrapper> for StarkProof {
type Error = &'static str;

fn try_from(wrapper: StarkProofWrapper) -> Result<Self, Self::Error> {
if wrapper.0.len() != mem::size_of::<StarkProof>() {
return Err("Invalid byte length for StarkProof");
}

let proof = unsafe {
let ptr = wrapper.0.as_ptr() as *const StarkProof;
ptr.read()
};

Ok(proof)
}
}

#[derive(Debug, thiserror::Error)]
pub enum ConversionError {
#[error("Invalid hash")]
InvalidHash,
#[error("Invalid lookup value")]
InvalidLookupValue,
#[error("Invalid sampled value")]
InvalidSampledValue,
#[error("Invalid Merkle proof")]
InvalidMerkleProof,
}

0 comments on commit 92ccf4c

Please sign in to comment.