Skip to content

Commit

Permalink
Add snark/user_command_verify Service
Browse files Browse the repository at this point in the history
To check signatures and verify proofs contained in zkapps
  • Loading branch information
sebastiencs committed Apr 11, 2024
1 parent ce1f4f8 commit b31fced
Show file tree
Hide file tree
Showing 15 changed files with 399 additions and 8 deletions.
2 changes: 1 addition & 1 deletion ledger/src/scan_state/transaction_logic.rs
Expand Up @@ -4311,7 +4311,7 @@ pub mod verifiable {

use super::*;

#[derive(Debug)]
#[derive(Clone, Debug)]
pub enum UserCommand {
SignedCommand(Box<signed_command::SignedCommand>),
ZkAppCommand(Box<zkapp_command::verifiable::ZkAppCommand>),
Expand Down
2 changes: 1 addition & 1 deletion ledger/src/transaction_pool.rs
Expand Up @@ -1909,7 +1909,7 @@ impl TransactionPool {
}
}

fn verify(
pub fn verify(
&self,
diff: Envelope<diff::Diff>,
accounts: BTreeMap<AccountId, Account>,
Expand Down
31 changes: 31 additions & 0 deletions node/native/src/service.rs
Expand Up @@ -3,10 +3,13 @@ use std::collections::{BTreeMap, VecDeque};
use std::sync::{Arc, Mutex};

use ledger::scan_state::scan_state::transaction_snark::{SokDigest, Statement};
use ledger::scan_state::transaction_logic::{verifiable, UserCommand, WithStatus};
use ledger::verifier::Verifier;
use libp2p::identity::Keypair;
use mina_p2p_messages::v2::{LedgerProofProdStableV2, TransactionSnarkWorkTStableV2Proofs};
#[cfg(not(feature = "p2p-libp2p"))]
use node::p2p::service_impl::mio::MioService;
use node::transaction_pool::VerifyUserCommandsService;
use rand::prelude::*;
use redux::ActionMeta;
use serde::Serialize;
Expand Down Expand Up @@ -261,6 +264,34 @@ impl SnarkBlockVerifyService for NodeService {
}
}

impl VerifyUserCommandsService for NodeService {
fn verify_init(
&mut self,
commands: Vec<WithStatus<verifiable::UserCommand>>,
verifier_index: Arc<VerifierIndex>,
verifier_srs: Arc<Mutex<VerifierSRS>>,
) {
if self.replayer.is_some() {
return;
}
let tx = self.event_sender.clone();
rayon::spawn_fifo(move || {
let verifieds: Vec<_> = Verifier
.verify_commands(commands, None)
.into_iter()
.map(|cmd| {
// TODO: Handle invalids
match cmd {
ledger::verifier::VerifyCommandsResult::Valid(cmd) => Ok(cmd),
e => Err(format!("invalid tx: {:?}", e)),
}
})
.collect();
// let _ = tx.send(SnarkEvent::WorkVerify(req_id, result).into());
});
}
}

impl SnarkWorkVerifyService for NodeService {
fn verify_init(
&mut self,
Expand Down
31 changes: 25 additions & 6 deletions node/src/transaction_pool/mod.rs
@@ -1,7 +1,15 @@
use std::collections::{BTreeMap, BTreeSet};

use ledger::{scan_state::transaction_logic::UserCommand, transaction_pool::{diff, ApplyDecision}, Account, AccountId, BaseLedger, Mask};
use std::{
collections::{BTreeMap, BTreeSet},
sync::{Arc, Mutex},
};

use ledger::{
scan_state::transaction_logic::{verifiable, UserCommand, WithStatus},
transaction_pool::{diff, ApplyDecision},
Account, AccountId, BaseLedger, Mask,
};
use mina_p2p_messages::v2::LedgerHash;
use snark::{VerifierIndex, VerifierSRS};

use crate::{Service, Store};

Expand Down Expand Up @@ -47,9 +55,11 @@ impl TransactionPoolState {
is_sender_local,
accounts,
} => match self.pool.unsafe_apply(diff, &accounts, *is_sender_local) {
Ok((ApplyDecision::Accept, accepted, rejected)) => self.rebroadcast(accepted, rejected),
Ok((ApplyDecision::Accept, accepted, rejected)) => {
self.rebroadcast(accepted, rejected)
}
Ok((ApplyDecision::Reject, accepted, rejected)) => todo!(),
Err(_e) => eprintln!("unsafe_apply: {:?}", e),
Err(e) => eprintln!("unsafe_apply error: {:?}", e),
},
ApplyTransitionFrontierDiff {
best_tip_hash: _,
Expand All @@ -58,7 +68,7 @@ impl TransactionPoolState {
ApplyTransitionFrontierDiffWithAccounts { diff, accounts } => {
self.pool.handle_transition_frontier_diff(diff, &accounts);
}
Rebroadcast => {},
Rebroadcast => {}
}
}
}
Expand Down Expand Up @@ -145,3 +155,12 @@ pub fn transaction_pool_effects<S: Service>(
pub trait TransactionPoolLedgerService: redux::Service {
fn get_mask(&self, ledger_hash: &LedgerHash) -> Result<Mask, String>;
}

pub trait VerifyUserCommandsService: redux::Service {
fn verify_init(
&mut self,
commands: Vec<WithStatus<verifiable::UserCommand>>,
verifier_index: Arc<VerifierIndex>,
verifier_srs: Arc<Mutex<VerifierSRS>>,
);
}
1 change: 1 addition & 0 deletions snark/src/lib.rs
Expand Up @@ -10,6 +10,7 @@ pub use ledger::proofs::verifier_index::{get_verifier_index, VerifierKind};
pub use merkle_path::calc_merkle_root_hash;

pub mod block_verify;
pub mod user_command_verify;
pub mod work_verify;

mod snark_event;
Expand Down
3 changes: 3 additions & 0 deletions snark/src/snark_actions.rs
@@ -1,5 +1,7 @@
use serde::{Deserialize, Serialize};

use crate::user_command_verify::SnarkUserCommandVerifyAction;

use super::block_verify::SnarkBlockVerifyAction;
use super::work_verify::SnarkWorkVerifyAction;

Expand All @@ -10,4 +12,5 @@ pub type SnarkActionWithMetaRef<'a> = redux::ActionWithMeta<&'a SnarkAction>;
pub enum SnarkAction {
BlockVerify(SnarkBlockVerifyAction),
WorkVerify(SnarkWorkVerifyAction),
UserCommandVerify(SnarkUserCommandVerifyAction),
}
8 changes: 8 additions & 0 deletions snark/src/snark_event.rs
Expand Up @@ -2,11 +2,16 @@ use serde::{Deserialize, Serialize};

use super::block_verify::{SnarkBlockVerifyError, SnarkBlockVerifyId};
use super::work_verify::{SnarkWorkVerifyError, SnarkWorkVerifyId};
use crate::user_command_verify::{SnarkUserCommandVerifyError, SnarkUserCommandVerifyId};

#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum SnarkEvent {
BlockVerify(SnarkBlockVerifyId, Result<(), SnarkBlockVerifyError>),
WorkVerify(SnarkWorkVerifyId, Result<(), SnarkWorkVerifyError>),
UserCommandVerify(
SnarkUserCommandVerifyId,
Result<(), SnarkUserCommandVerifyError>,
),
}

fn res_kind<T, E>(res: &Result<T, E>) -> &'static str {
Expand All @@ -26,6 +31,9 @@ impl std::fmt::Display for SnarkEvent {
Self::WorkVerify(id, res) => {
write!(f, "WorkVerify, {id}, {}", res_kind(res))
}
Self::UserCommandVerify(id, res) => {
write!(f, "UserCommandVerify, {id}, {}", res_kind(res))
}
}
}
}
3 changes: 3 additions & 0 deletions snark/src/snark_reducer.rs
Expand Up @@ -6,6 +6,9 @@ impl SnarkState {
match action {
SnarkAction::BlockVerify(a) => self.block_verify.reducer(meta.with_action(a)),
SnarkAction::WorkVerify(a) => self.work_verify.reducer(meta.with_action(a)),
SnarkAction::UserCommandVerify(a) => {
self.user_command_verify.reducer(meta.with_action(a))
}
}
}
}
6 changes: 6 additions & 0 deletions snark/src/snark_state.rs
@@ -1,5 +1,6 @@
use serde::{Deserialize, Serialize};

use crate::user_command_verify::SnarkUserCommandVerifyState;
use crate::SnarkConfig;

use super::block_verify::SnarkBlockVerifyState;
Expand All @@ -9,6 +10,7 @@ use super::work_verify::SnarkWorkVerifyState;
pub struct SnarkState {
pub block_verify: SnarkBlockVerifyState,
pub work_verify: SnarkWorkVerifyState,
pub user_command_verify: SnarkUserCommandVerifyState,
}

impl SnarkState {
Expand All @@ -19,6 +21,10 @@ impl SnarkState {
config.block_verifier_srs,
),
work_verify: SnarkWorkVerifyState::new(
config.work_verifier_index.clone(),
config.work_verifier_srs.clone(),
),
user_command_verify: SnarkUserCommandVerifyState::new(
config.work_verifier_index,
config.work_verifier_srs,
),
Expand Down
32 changes: 32 additions & 0 deletions snark/src/user_command_verify/mod.rs
@@ -0,0 +1,32 @@
mod snark_user_command_verify_state;
pub use snark_user_command_verify_state::*;

mod snark_user_command_verify_actions;
pub use snark_user_command_verify_actions::*;

mod snark_user_command_verify_reducer;

mod snark_user_command_verify_effects;

mod snark_user_command_verify_service;
pub use snark_user_command_verify_service::*;

use serde::{Deserialize, Serialize};

pub struct SnarkUserCommandVerifyIdType;
impl openmina_core::requests::RequestIdType for SnarkUserCommandVerifyIdType {
fn request_id_type() -> &'static str {
"SnarkUserCommandVerifyId"
}
}

pub type SnarkUserCommandVerifyId =
openmina_core::requests::RequestId<SnarkUserCommandVerifyIdType>;

#[derive(Serialize, Deserialize, Debug, Clone, thiserror::Error)]
pub enum SnarkUserCommandVerifyError {
#[error("verification failed")]
VerificationFailed,
#[error("validator thread crashed")]
ValidatorThreadCrashed,
}
66 changes: 66 additions & 0 deletions snark/src/user_command_verify/snark_user_command_verify_actions.rs
@@ -0,0 +1,66 @@
use ledger::scan_state::transaction_logic::verifiable;
use serde::{Deserialize, Serialize};

use openmina_core::{snark::Snark, ActionEvent};

use super::{SnarkUserCommandVerifyError, SnarkUserCommandVerifyId};

pub type SnarkUserCommandVerifyActionWithMeta = redux::ActionWithMeta<SnarkUserCommandVerifyAction>;
pub type SnarkUserCommandVerifyActionWithMetaRef<'a> =
redux::ActionWithMeta<&'a SnarkUserCommandVerifyAction>;

#[derive(Serialize, Deserialize, Debug, Clone, ActionEvent)]
#[action_event(level = trace, fields(display(req_id), display(error)))]
pub enum SnarkUserCommandVerifyAction {
#[action_event(level = info)]
Init {
req_id: SnarkUserCommandVerifyId,
#[serde(skip)] // TODO
commands: Vec<verifiable::UserCommand>,
sender: String,
},
Pending {
req_id: SnarkUserCommandVerifyId,
},
Error {
req_id: SnarkUserCommandVerifyId,
error: SnarkUserCommandVerifyError,
},
#[action_event(level = info)]
Success {
req_id: SnarkUserCommandVerifyId,
},
Finish {
req_id: SnarkUserCommandVerifyId,
},
}

impl redux::EnablingCondition<crate::SnarkState> for SnarkUserCommandVerifyAction {
fn is_enabled(&self, state: &crate::SnarkState, _time: redux::Timestamp) -> bool {
match self {
SnarkUserCommandVerifyAction::Init {
req_id, commands, ..
} => !commands.is_empty() && state.user_command_verify.jobs.next_req_id() == *req_id,
SnarkUserCommandVerifyAction::Pending { req_id } => state
.user_command_verify
.jobs
.get(*req_id)
.map_or(false, |v| v.is_init()),
SnarkUserCommandVerifyAction::Error { req_id, .. } => state
.user_command_verify
.jobs
.get(*req_id)
.map_or(false, |v| v.is_pending()),
SnarkUserCommandVerifyAction::Success { req_id } => state
.user_command_verify
.jobs
.get(*req_id)
.map_or(false, |v| v.is_pending()),
SnarkUserCommandVerifyAction::Finish { req_id } => state
.user_command_verify
.jobs
.get(*req_id)
.map_or(false, |v| v.is_finished()),
}
}
}
33 changes: 33 additions & 0 deletions snark/src/user_command_verify/snark_user_command_verify_effects.rs
@@ -0,0 +1,33 @@
use redux::ActionMeta;

use super::{SnarkUserCommandVerifyAction, SnarkUserCommandVerifyService};

impl SnarkUserCommandVerifyAction {
pub fn effects<Store, S>(self, _: &ActionMeta, store: &mut Store)
where
Store: crate::SnarkStore<S>,
Store::Service: SnarkUserCommandVerifyService,
SnarkUserCommandVerifyAction: redux::EnablingCondition<S>,
{
match self {
SnarkUserCommandVerifyAction::Init {
req_id, commands, ..
} => {
let verifier_index = store.state().work_verify.verifier_index.clone();
let verifier_srs = store.state().work_verify.verifier_srs.clone();
store
.service()
.verify_init(req_id, verifier_index, verifier_srs, commands);
store.dispatch(SnarkUserCommandVerifyAction::Pending { req_id });
}
SnarkUserCommandVerifyAction::Error { req_id, .. } => {
store.dispatch(SnarkUserCommandVerifyAction::Finish { req_id });
}
SnarkUserCommandVerifyAction::Success { req_id } => {
store.dispatch(SnarkUserCommandVerifyAction::Finish { req_id });
}
SnarkUserCommandVerifyAction::Pending { .. } => {}
SnarkUserCommandVerifyAction::Finish { .. } => {}
}
}
}

0 comments on commit b31fced

Please sign in to comment.