mirror of
https://github.com/vacp2p/status-rln-prover.git
synced 2026-01-08 05:03:54 -05:00
Add rln benchmarks (computation & serialization)
This commit is contained in:
200
Cargo.lock
generated
200
Cargo.lock
generated
@@ -788,6 +788,12 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anes"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.18"
|
||||
@@ -1476,6 +1482,12 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cast"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.20"
|
||||
@@ -1493,17 +1505,46 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.40"
|
||||
version = "0.4.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
|
||||
checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ciborium"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
|
||||
dependencies = [
|
||||
"ciborium-io",
|
||||
"ciborium-ll",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ciborium-io"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
|
||||
|
||||
[[package]]
|
||||
name = "ciborium-ll"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
|
||||
dependencies = [
|
||||
"ciborium-io",
|
||||
"half",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.37"
|
||||
@@ -1665,6 +1706,42 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "criterion"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f"
|
||||
dependencies = [
|
||||
"anes",
|
||||
"cast",
|
||||
"ciborium",
|
||||
"clap",
|
||||
"criterion-plot",
|
||||
"is-terminal",
|
||||
"itertools 0.10.5",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"oorandom",
|
||||
"plotters",
|
||||
"rayon",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"tinytemplate",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "criterion-plot"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
|
||||
dependencies = [
|
||||
"cast",
|
||||
"itertools 0.10.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.6"
|
||||
@@ -2280,6 +2357,16 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "half"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crunchy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
@@ -2316,6 +2403,12 @@ version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08"
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.3"
|
||||
@@ -2697,6 +2790,17 @@ version = "2.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9"
|
||||
dependencies = [
|
||||
"hermit-abi 0.5.1",
|
||||
"libc",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.1"
|
||||
@@ -2988,7 +3092,7 @@ version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"hermit-abi 0.3.9",
|
||||
"libc",
|
||||
]
|
||||
|
||||
@@ -3040,6 +3144,12 @@ version = "1.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
|
||||
[[package]]
|
||||
name = "oorandom"
|
||||
version = "11.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.72"
|
||||
@@ -3263,6 +3373,34 @@ version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
||||
|
||||
[[package]]
|
||||
name = "plotters"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"plotters-backend",
|
||||
"plotters-svg",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "plotters-backend"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a"
|
||||
|
||||
[[package]]
|
||||
name = "plotters-svg"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670"
|
||||
dependencies = [
|
||||
"plotters-backend",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
@@ -3692,6 +3830,20 @@ dependencies = [
|
||||
"zerokit_utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rln_proof"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ark-bn254",
|
||||
"ark-groth16",
|
||||
"ark-relations",
|
||||
"ark-serialize 0.5.0",
|
||||
"criterion",
|
||||
"rln",
|
||||
"serde_json",
|
||||
"zerokit_utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rlp"
|
||||
version = "0.5.2"
|
||||
@@ -3848,6 +4000,15 @@ version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
version = "0.1.27"
|
||||
@@ -4154,12 +4315,16 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"alloy",
|
||||
"ark-bn254",
|
||||
"ark-serialize 0.5.0",
|
||||
"bytesize",
|
||||
"chrono",
|
||||
"clap",
|
||||
"dashmap",
|
||||
"futures",
|
||||
"parking_lot 0.12.3",
|
||||
"prost",
|
||||
"rln",
|
||||
"rln_proof",
|
||||
"serde_json",
|
||||
"thiserror 2.0.12",
|
||||
"tokio",
|
||||
@@ -4387,6 +4552,16 @@ dependencies = [
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinytemplate"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.44.2"
|
||||
@@ -4837,6 +5012,16 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "want"
|
||||
version = "0.3.1"
|
||||
@@ -4987,6 +5172,15 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||
dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
|
||||
31
Cargo.toml
31
Cargo.toml
@@ -1,25 +1,6 @@
|
||||
[package]
|
||||
name = "status_rln_prover"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.5.37", features = ["derive"] }
|
||||
tonic = { version = "0.13", features = ["gzip"] }
|
||||
tonic-reflection = "0.13"
|
||||
prost = "0.13"
|
||||
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
|
||||
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
|
||||
tracing = "0.1.41"
|
||||
tracing-test = "0.2.5"
|
||||
alloy = { version = "0.15", features = ["full"] }
|
||||
thiserror = "2.0"
|
||||
futures = "0.3"
|
||||
rln = { git = "https://github.com/vacp2p/zerokit" }
|
||||
ark-bn254 = { version = "0.5", features = ["std"] }
|
||||
serde_json = "1.0"
|
||||
dashmap = "6.1.0"
|
||||
bytesize = "2.0.1"
|
||||
|
||||
[build-dependencies]
|
||||
tonic-build = "*"
|
||||
[workspace]
|
||||
members = [
|
||||
"prover",
|
||||
"rln_proof"
|
||||
]
|
||||
resolver = "2"
|
||||
@@ -3,6 +3,10 @@ package prover;
|
||||
|
||||
import "google/protobuf/descriptor.proto";
|
||||
|
||||
option java_package = "net.vac.prover";
|
||||
option java_outer_classname = "OuterSample";
|
||||
option java_multiple_files = true;
|
||||
|
||||
service RlnProver {
|
||||
|
||||
rpc SendTransaction (SendTransactionRequest) returns (SendTransactionReply);
|
||||
@@ -111,7 +115,7 @@ message SendTransactionRequest {
|
||||
|
||||
message SendTransactionReply {
|
||||
bool result = 1;
|
||||
string message = 2;
|
||||
// string message = 2;
|
||||
}
|
||||
|
||||
message RlnProofFilter {
|
||||
29
prover/Cargo.toml
Normal file
29
prover/Cargo.toml
Normal file
@@ -0,0 +1,29 @@
|
||||
[package]
|
||||
name = "status_rln_prover"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.5.37", features = ["derive"] }
|
||||
tonic = { version = "0.13", features = ["gzip"] }
|
||||
tonic-reflection = "0.13"
|
||||
prost = "0.13"
|
||||
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
|
||||
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
|
||||
tracing = "0.1.41"
|
||||
tracing-test = "0.2.5"
|
||||
alloy = { version = "0.15", features = ["full"] }
|
||||
thiserror = "2.0"
|
||||
futures = "0.3"
|
||||
rln = { git = "https://github.com/vacp2p/zerokit" }
|
||||
ark-bn254 = { version = "0.5", features = ["std"] }
|
||||
ark-serialize = "0.5.0"
|
||||
serde_json = "1.0"
|
||||
dashmap = "6.1.0"
|
||||
bytesize = "2.0.1"
|
||||
rln_proof = { path = "../rln_proof" }
|
||||
chrono = "0.4.41"
|
||||
parking_lot = "0.12.3"
|
||||
|
||||
[build-dependencies]
|
||||
tonic-build = "*"
|
||||
@@ -5,7 +5,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||
tonic_build::configure()
|
||||
.file_descriptor_set_path(out_dir.join("prover_descriptor.bin"))
|
||||
.compile_protos(&["proto/prover.proto"], &["proto"])
|
||||
.compile_protos(&["../proto/net/vac/prover/prover.proto"], &["../proto"])
|
||||
.unwrap();
|
||||
|
||||
Ok(())
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::net::IpAddr;
|
||||
|
||||
// third-party
|
||||
use clap::Parser;
|
||||
|
||||
#[derive(Debug, Clone, Parser)]
|
||||
@@ -1,20 +1,23 @@
|
||||
// std
|
||||
use std::io::Cursor;
|
||||
use std::collections::HashMap;
|
||||
use std::io::{Cursor, Write};
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
// use std::sync::atomic::{
|
||||
// AtomicI64,
|
||||
// };
|
||||
// third-party
|
||||
use alloy::primitives::Address;
|
||||
use ark_bn254::Fr;
|
||||
use ark_serialize::{CanonicalSerialize, SerializationError};
|
||||
use bytesize::ByteSize;
|
||||
use futures::TryFutureExt;
|
||||
use rln::{
|
||||
hashers::{hash_to_field, poseidon_hash},
|
||||
protocol::prepare_prove_input,
|
||||
public::RLN,
|
||||
};
|
||||
use serde_json::json;
|
||||
use rln::hashers::{hash_to_field, poseidon_hash};
|
||||
use rln::pm_tree_adapter::PmTree;
|
||||
use rln::protocol::{ProofError, serialize_proof_values};
|
||||
use tokio::sync::{
|
||||
broadcast,
|
||||
RwLock, broadcast,
|
||||
broadcast::{Receiver, Sender},
|
||||
mpsc,
|
||||
};
|
||||
@@ -33,7 +36,10 @@ use tracing::{
|
||||
};
|
||||
// internal
|
||||
use crate::{
|
||||
error::{AppError, RegistrationError},
|
||||
error::{
|
||||
AppError,
|
||||
// RegistrationError
|
||||
},
|
||||
registry::UserRegistry,
|
||||
};
|
||||
|
||||
@@ -50,6 +56,9 @@ use prover_proto::{
|
||||
SendTransactionRequest,
|
||||
rln_prover_server::{RlnProver, RlnProverServer},
|
||||
};
|
||||
use rln_proof::{
|
||||
RlnData, RlnIdentifier, RlnUserIdentity, ZerokitMerkleTree, compute_rln_proof_and_values,
|
||||
};
|
||||
|
||||
const PROVER_SERVICE_LIMIT_PER_CONNECTION: usize = 16;
|
||||
// Timeout for all handlers of a request
|
||||
@@ -59,17 +68,32 @@ const PROVER_SERVICE_HTTP2_MAX_CONCURRENT_STREAM: u32 = 64;
|
||||
// Http2 max frame size (e.g. 16 Kb)
|
||||
const PROVER_SERVICE_HTTP2_MAX_FRAME_SIZE: ByteSize = ByteSize::kib(16);
|
||||
// Max size for Message (decoding, e.g., 5 Mb)
|
||||
// const PROVER_SERVICE_MESSAGE_DECODING_MAX_SIZE: usize = 1024 * 1024 * 5;
|
||||
const PROVER_SERVICE_MESSAGE_DECODING_MAX_SIZE: ByteSize = ByteSize::mib(5);
|
||||
// Max size for Message (encoding, e.g., 5 Mb)
|
||||
const PROVER_SERVICE_MESSAGE_ENCODING_MAX_SIZE: ByteSize = ByteSize::mib(5);
|
||||
const PROVER_SPAM_LIMIT: u64 = 10_000;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ProverService {
|
||||
registry: UserRegistry,
|
||||
rln_identifier: Arc<RlnIdentifier>,
|
||||
message_counters: RwLock<HashMap<Address, u64>>,
|
||||
spam_limit: u64,
|
||||
broadcast_channel: (Sender<Vec<u8>>, Receiver<Vec<u8>>),
|
||||
}
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
enum ProofGenerationError {
|
||||
#[error("Proof generation failed: {0}")]
|
||||
Proof(#[from] ProofError),
|
||||
#[error("Proof serialization failed: {0}")]
|
||||
Serialization(#[from] SerializationError),
|
||||
#[error("Proof serialization failed: {0}")]
|
||||
SerializationWrite(#[from] std::io::Error),
|
||||
#[error("Error: {0}")]
|
||||
Misc(String),
|
||||
}
|
||||
|
||||
#[tonic::async_trait]
|
||||
impl RlnProver for ProverService {
|
||||
async fn send_transaction(
|
||||
@@ -78,74 +102,103 @@ impl RlnProver for ProverService {
|
||||
) -> Result<Response<SendTransactionReply>, Status> {
|
||||
debug!("send_transaction request: {:?}", request);
|
||||
let req = request.into_inner();
|
||||
let sender = req.sender;
|
||||
|
||||
let id = if let Some(sender) = sender {
|
||||
if let Ok(sender_) = Address::try_from(sender.value.as_slice()) {
|
||||
if let Some(id) = self.registry.get(&sender_) {
|
||||
Ok(*id)
|
||||
} else {
|
||||
Err(RegistrationError::NotFound(sender_))
|
||||
}
|
||||
let sender = if let Some(sender) = req.sender {
|
||||
if let Ok(sender) = Address::try_from(sender.value.as_slice()) {
|
||||
sender
|
||||
} else {
|
||||
Err(RegistrationError::InvalidAddress(sender.value.to_vec()))
|
||||
return Err(Status::invalid_argument("Invalid sender address"));
|
||||
}
|
||||
} else {
|
||||
Err(RegistrationError::NoSender)
|
||||
return Err(Status::invalid_argument("No sender address"));
|
||||
};
|
||||
|
||||
let reply = match id {
|
||||
Ok(id) => {
|
||||
let id_secret_hash = id.0;
|
||||
let _id_commitment = id.1;
|
||||
// Update the counter as soon as possible (should help to prevent spamming...)
|
||||
let mut message_counter_guard = self.message_counters.write().await;
|
||||
let counter = *message_counter_guard
|
||||
.entry(sender)
|
||||
.and_modify(|e| *e += 1)
|
||||
.or_insert(1);
|
||||
drop(message_counter_guard);
|
||||
|
||||
// TODO/FIXME: blocking code
|
||||
{
|
||||
// FIXME
|
||||
let tree_height = 20;
|
||||
let input = Cursor::new(json!({}).to_string());
|
||||
let mut rln = RLN::new(tree_height, input).unwrap();
|
||||
|
||||
// FIXME
|
||||
let message_id = Fr::from(1);
|
||||
let id_index = 10;
|
||||
let user_message_limit = Fr::from(10);
|
||||
let rln_identifier = hash_to_field(b"test-rln-identifier");
|
||||
let epoch = hash_to_field(b"Today at noon, this year");
|
||||
let external_nullifier = poseidon_hash(&[epoch, rln_identifier]);
|
||||
let signal = b"RLN is awesome";
|
||||
|
||||
let prove_input = prepare_prove_input(
|
||||
id_secret_hash,
|
||||
id_index,
|
||||
user_message_limit,
|
||||
message_id,
|
||||
external_nullifier,
|
||||
signal,
|
||||
);
|
||||
|
||||
let mut input_buffer = Cursor::new(prove_input);
|
||||
let mut output_buffer = Cursor::new(Vec::<u8>::new());
|
||||
rln.generate_rln_proof(&mut input_buffer, &mut output_buffer)
|
||||
.unwrap();
|
||||
|
||||
self.broadcast_channel
|
||||
.0
|
||||
.send(output_buffer.into_inner())
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
SendTransactionReply {
|
||||
result: true,
|
||||
message: "".to_string(),
|
||||
}
|
||||
}
|
||||
Err(e) => SendTransactionReply {
|
||||
result: false,
|
||||
message: e.to_string(),
|
||||
},
|
||||
let user_id = if let Some(id) = self.registry.get(&sender) {
|
||||
*id
|
||||
} else {
|
||||
return Err(Status::not_found("Sender not registered"));
|
||||
};
|
||||
|
||||
let user_identity = RlnUserIdentity {
|
||||
secret_hash: user_id.0,
|
||||
commitment: user_id.1,
|
||||
user_limit: Fr::from(self.spam_limit),
|
||||
};
|
||||
|
||||
// Inexpensive clone (behind Arc ptr)
|
||||
let rln_identifier = self.rln_identifier.clone();
|
||||
|
||||
// Move to a task (as generating the proof can take quite some time)
|
||||
let blocking_task = tokio::task::spawn_blocking(move || {
|
||||
let rln_data = RlnData {
|
||||
message_id: Fr::from(counter),
|
||||
// TODO: tx hash to field
|
||||
data: hash_to_field(b"RLN is awesome"),
|
||||
};
|
||||
// FIXME: track/update epoch
|
||||
let epoch = hash_to_field(b"Today at noon, this year");
|
||||
|
||||
// FIXME: maintain tree in Prover or query RLN Reg SC ?
|
||||
// Merkle tree
|
||||
let tree_height = 20;
|
||||
let mut tree = PmTree::new(tree_height, Fr::from(0), Default::default())
|
||||
.map_err(|e| ProofGenerationError::Misc(e.to_string()))?;
|
||||
// .unwrap();
|
||||
// let mut tree = OptimalMerkleTree::new(tree_height, Fr::from(0), Default::default()).unwrap();
|
||||
let rate_commit = poseidon_hash(&[user_identity.commitment, user_identity.user_limit]);
|
||||
tree.set(0, rate_commit)
|
||||
.map_err(|e| ProofGenerationError::Misc(e.to_string()))?;
|
||||
//.unwrap();
|
||||
let merkle_proof = tree
|
||||
.proof(0)
|
||||
.map_err(|e| ProofGenerationError::Misc(e.to_string()))?;
|
||||
// .unwrap();
|
||||
|
||||
let (proof, proof_values) = compute_rln_proof_and_values(
|
||||
&user_identity,
|
||||
&rln_identifier,
|
||||
rln_data,
|
||||
epoch,
|
||||
&merkle_proof,
|
||||
)
|
||||
.map_err(ProofGenerationError::Proof)?;
|
||||
// .unwrap(); // FIXME: no unwrap
|
||||
|
||||
// Serialize proof
|
||||
// FIXME: proof size?
|
||||
let mut output_buffer = Cursor::new(Vec::with_capacity(512));
|
||||
proof
|
||||
.serialize_compressed(&mut output_buffer)
|
||||
.map_err(ProofGenerationError::Serialization)?;
|
||||
// .unwrap();
|
||||
output_buffer
|
||||
.write_all(&serialize_proof_values(&proof_values))
|
||||
.map_err(ProofGenerationError::SerializationWrite)?;
|
||||
// .unwrap();
|
||||
|
||||
Ok::<Vec<u8>, ProofGenerationError>(output_buffer.into_inner())
|
||||
});
|
||||
|
||||
let result = blocking_task.await;
|
||||
if let Err(e) = result {
|
||||
return Err(Status::from_error(Box::new(e)));
|
||||
}
|
||||
// blocking_task returns Result<Result<Vec<u8>, _>>
|
||||
// Result (1st) is a JoinError (and should not happen)
|
||||
// Result (2nd) is a ProofGenerationError
|
||||
let _result = result.unwrap();
|
||||
|
||||
// TODO: broadcast proof
|
||||
|
||||
let reply = SendTransactionReply { result: true };
|
||||
Ok(Response::new(reply))
|
||||
}
|
||||
|
||||
@@ -186,17 +239,30 @@ impl RlnProver for ProverService {
|
||||
|
||||
pub(crate) struct GrpcProverService {
|
||||
addr: SocketAddr,
|
||||
rln_identifier: RlnIdentifier,
|
||||
// epoch_counter: Arc<AtomicI64>,
|
||||
}
|
||||
|
||||
impl GrpcProverService {
|
||||
pub(crate) fn new(addr: SocketAddr) -> Self {
|
||||
Self { addr }
|
||||
pub(crate) fn new(
|
||||
addr: SocketAddr,
|
||||
rln_identifier: RlnIdentifier, /* epoch_counter: Arc<AtomicI64> */
|
||||
) -> Self {
|
||||
Self {
|
||||
addr,
|
||||
rln_identifier,
|
||||
// epoch_counter,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn serve(&self) -> Result<(), AppError> {
|
||||
let (tx, rx) = broadcast::channel(2);
|
||||
|
||||
let prover_service = ProverService {
|
||||
registry: Default::default(),
|
||||
rln_identifier: Arc::new(self.rln_identifier.clone()),
|
||||
message_counters: Default::default(),
|
||||
spam_limit: PROVER_SPAM_LIMIT,
|
||||
broadcast_channel: (tx, rx),
|
||||
};
|
||||
|
||||
@@ -237,7 +303,6 @@ impl GrpcProverService {
|
||||
mod tests {
|
||||
use crate::grpc_service::prover_proto::Address;
|
||||
use prost::Message;
|
||||
// use crate::proto::prover::{Address}; // Adjust the import path as needed
|
||||
|
||||
const MAX_ADDRESS_SIZE_BYTES: usize = 20;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
mod args;
|
||||
mod epoch_service;
|
||||
mod error;
|
||||
mod grpc_service;
|
||||
mod registry;
|
||||
@@ -8,7 +9,12 @@ mod registry_listener;
|
||||
use std::net::SocketAddr;
|
||||
// third-party
|
||||
use alloy::primitives::address;
|
||||
// use chrono::{
|
||||
// DateTime,
|
||||
// Utc
|
||||
// };
|
||||
use clap::Parser;
|
||||
use rln_proof::RlnIdentifier;
|
||||
use tracing::level_filters::LevelFilter;
|
||||
use tracing::{
|
||||
debug,
|
||||
@@ -16,12 +22,14 @@ use tracing::{
|
||||
// info
|
||||
};
|
||||
use tracing_subscriber::{EnvFilter, fmt, layer::SubscriberExt, util::SubscriberInitExt};
|
||||
|
||||
// internal
|
||||
use crate::args::AppArgs;
|
||||
// use crate::epoch_service::EpochService;
|
||||
use crate::grpc_service::GrpcProverService;
|
||||
use crate::registry_listener::RegistryListener;
|
||||
|
||||
const RLN_IDENTIFIER_NAME: &[u8] = b"test-rln-identifier";
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let filter = EnvFilter::builder()
|
||||
@@ -42,18 +50,34 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let registry_listener =
|
||||
RegistryListener::new(app_args.rpc_url.as_str(), uniswap_token_address, event);
|
||||
|
||||
// Epoch
|
||||
// let mut epoch_service = EpochService::new(
|
||||
// Duration::from_secs(10),
|
||||
// Utc::now()
|
||||
// );
|
||||
|
||||
// grpc
|
||||
|
||||
let rln_identifier = RlnIdentifier::new(RLN_IDENTIFIER_NAME);
|
||||
let addr = SocketAddr::new(app_args.ip, app_args.port);
|
||||
debug!("Listening on: {}", addr);
|
||||
let prover_service = GrpcProverService::new(addr);
|
||||
let prover_service = GrpcProverService::new(
|
||||
addr,
|
||||
rln_identifier,
|
||||
// epoch_service.current_epoch.clone()
|
||||
);
|
||||
|
||||
let res = tokio::try_join!(prover_service.serve(), registry_listener.listen());
|
||||
let res = tokio::try_join!(
|
||||
// epoch_service.listen_for_new_epoch(),
|
||||
registry_listener.listen(),
|
||||
prover_service.serve(),
|
||||
);
|
||||
|
||||
match res {
|
||||
Ok((first, second)) => {
|
||||
debug!("{:?}", first);
|
||||
debug!("{:?}", second);
|
||||
// Ok((epoch, registry, prover)) => {
|
||||
Ok((registry, prover)) => {
|
||||
debug!("{:?}", registry);
|
||||
debug!("{:?}", prover);
|
||||
}
|
||||
Err(e) => {
|
||||
error!("{:?}", e);
|
||||
33
rln_proof/Cargo.toml
Normal file
33
rln_proof/Cargo.toml
Normal file
@@ -0,0 +1,33 @@
|
||||
[package]
|
||||
name = "rln_proof"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
# clap = { version = "4.5.37", features = ["derive"] }
|
||||
# tonic = { version = "0.13", features = ["gzip"] }
|
||||
# tonic-reflection = "0.13"
|
||||
# prost = "0.13"
|
||||
# tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
|
||||
# tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
|
||||
# tracing = "0.1.41"
|
||||
# tracing-test = "0.2.5"
|
||||
# alloy = { version = "0.15", features = ["full"] }
|
||||
# thiserror = "2.0"
|
||||
# futures = "0.3"
|
||||
rln = { git = "https://github.com/vacp2p/zerokit", package = "rln", features = ["default"] }
|
||||
zerokit_utils = { git = "https://github.com/vacp2p/zerokit", package = "zerokit_utils", features = ["default"] }
|
||||
ark-bn254 = { version = "0.5", features = ["std"] }
|
||||
serde_json = "1.0"
|
||||
# dashmap = "6.1.0"
|
||||
# bytesize = "2.0.1"
|
||||
ark-groth16 = "*"
|
||||
ark-relations = "*"
|
||||
ark-serialize = "0.5.0"
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = "0.5"
|
||||
|
||||
[[bench]]
|
||||
name = "generate_proof"
|
||||
harness = false
|
||||
125
rln_proof/benches/generate_proof.rs
Normal file
125
rln_proof/benches/generate_proof.rs
Normal file
@@ -0,0 +1,125 @@
|
||||
// std
|
||||
use std::io::{Cursor, Write};
|
||||
// criterion
|
||||
use criterion::{Criterion, criterion_group, criterion_main};
|
||||
// third-party
|
||||
use ark_bn254::Fr;
|
||||
use ark_serialize::CanonicalSerialize;
|
||||
use rln::hashers::{hash_to_field, poseidon_hash};
|
||||
use rln::pm_tree_adapter::PmTree;
|
||||
use rln::protocol::{keygen, serialize_proof_values};
|
||||
// internal
|
||||
use rln_proof::{
|
||||
RlnData, RlnIdentifier, RlnUserIdentity, ZerokitMerkleTree, compute_rln_proof_and_values,
|
||||
};
|
||||
|
||||
pub fn criterion_benchmark(c: &mut Criterion) {
|
||||
let (identity_secret_hash, id_commitment) = keygen();
|
||||
let user_limit = 100;
|
||||
let rln_identity = RlnUserIdentity {
|
||||
commitment: id_commitment,
|
||||
secret_hash: identity_secret_hash,
|
||||
user_limit: Fr::from(user_limit),
|
||||
};
|
||||
let rln_identifier = RlnIdentifier::new(b"test-test");
|
||||
let rln_data = RlnData {
|
||||
message_id: Fr::from(user_limit - 2),
|
||||
data: hash_to_field(b"data-from-message"),
|
||||
};
|
||||
|
||||
// Merkle tree
|
||||
let tree_height = 20;
|
||||
let mut tree = PmTree::new(tree_height, Fr::from(0), Default::default()).unwrap();
|
||||
let rate_commit = poseidon_hash(&[rln_identity.commitment, rln_identity.user_limit]);
|
||||
tree.set(0, rate_commit).unwrap();
|
||||
let merkle_proof = tree.proof(0).unwrap();
|
||||
|
||||
// Epoch
|
||||
let epoch = hash_to_field(b"Today at noon, this year");
|
||||
|
||||
{
|
||||
// Not a benchmark but print the proof size (serialized)
|
||||
let (proof, proof_values) = compute_rln_proof_and_values(
|
||||
&rln_identity,
|
||||
&rln_identifier,
|
||||
rln_data.clone(),
|
||||
epoch,
|
||||
&merkle_proof,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut output_buffer = Cursor::new(Vec::new());
|
||||
proof.serialize_compressed(&mut output_buffer).unwrap();
|
||||
output_buffer
|
||||
.write_all(&serialize_proof_values(&proof_values))
|
||||
.unwrap();
|
||||
|
||||
println!(
|
||||
"Proof size (serialized): {:?}",
|
||||
output_buffer.into_inner().len()
|
||||
)
|
||||
}
|
||||
|
||||
c.bench_function("compute proof and values", |b| {
|
||||
/*
|
||||
b.iter(|| {
|
||||
compute_rln_proof_and_values(
|
||||
&rln_identity,
|
||||
&rln_identifier,
|
||||
rln_data.clone(),
|
||||
epoch,
|
||||
&merkle_proof,
|
||||
)
|
||||
})
|
||||
*/
|
||||
b.iter_batched(
|
||||
|| {
|
||||
// generate setup data
|
||||
rln_data.clone()
|
||||
},
|
||||
|data| {
|
||||
// function to benchmark
|
||||
compute_rln_proof_and_values(
|
||||
&rln_identity,
|
||||
&rln_identifier,
|
||||
data,
|
||||
epoch,
|
||||
&merkle_proof,
|
||||
)
|
||||
},
|
||||
criterion::BatchSize::SmallInput,
|
||||
);
|
||||
});
|
||||
|
||||
c.bench_function("serialize proof and values", |b| {
|
||||
b.iter_batched(
|
||||
|| {
|
||||
// generate setup data
|
||||
compute_rln_proof_and_values(
|
||||
&rln_identity,
|
||||
&rln_identifier,
|
||||
rln_data.clone(),
|
||||
epoch,
|
||||
&merkle_proof,
|
||||
)
|
||||
.unwrap()
|
||||
},
|
||||
|(proof, proof_values)| {
|
||||
let mut output_buffer = Cursor::new(Vec::with_capacity(320));
|
||||
proof.serialize_compressed(&mut output_buffer).unwrap();
|
||||
output_buffer
|
||||
.write_all(&serialize_proof_values(&proof_values))
|
||||
.unwrap();
|
||||
},
|
||||
criterion::BatchSize::SmallInput,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group! {
|
||||
name = benches;
|
||||
config = Criterion::default()
|
||||
.sample_size(50);
|
||||
targets = criterion_benchmark
|
||||
}
|
||||
criterion_main!(benches);
|
||||
BIN
rln_proof/resources/graph.bin
Normal file
BIN
rln_proof/resources/graph.bin
Normal file
Binary file not shown.
6
rln_proof/src/lib.rs
Normal file
6
rln_proof/src/lib.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
mod proof;
|
||||
|
||||
pub use proof::{RlnData, RlnIdentifier, RlnUserIdentity, compute_rln_proof_and_values};
|
||||
|
||||
// re export trait from zerokit utils crate (for prover)
|
||||
pub use zerokit_utils::merkle_tree::merkle_tree::ZerokitMerkleTree;
|
||||
80
rln_proof/src/proof.rs
Normal file
80
rln_proof/src/proof.rs
Normal file
@@ -0,0 +1,80 @@
|
||||
// std
|
||||
use std::io::Cursor;
|
||||
// third-party
|
||||
use ark_bn254::{Bn254, Fr};
|
||||
use ark_groth16::{Proof, ProvingKey};
|
||||
use ark_relations::r1cs::ConstraintMatrices;
|
||||
use rln::circuit::ZKEY_BYTES;
|
||||
use rln::circuit::zkey::read_zkey;
|
||||
use rln::hashers::{hash_to_field, poseidon_hash};
|
||||
use rln::protocol::{
|
||||
ProofError, RLNProofValues, generate_proof, proof_values_from_witness, rln_witness_from_values,
|
||||
};
|
||||
|
||||
/// A RLN user identity & limit
|
||||
pub struct RlnUserIdentity {
|
||||
pub commitment: Fr,
|
||||
pub secret_hash: Fr,
|
||||
pub user_limit: Fr,
|
||||
}
|
||||
|
||||
/// RLN info for a channel / group
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RlnIdentifier {
|
||||
pub identifier: Fr,
|
||||
pub pkey_and_constraints: (ProvingKey<Bn254>, ConstraintMatrices<Fr>),
|
||||
pub graph: Vec<u8>,
|
||||
}
|
||||
|
||||
impl RlnIdentifier {
|
||||
pub fn new(identifier: &[u8]) -> Self {
|
||||
// TODO: valid / correct ?
|
||||
let pk_and_matrices = {
|
||||
let mut reader = Cursor::new(ZKEY_BYTES);
|
||||
read_zkey(&mut reader).unwrap()
|
||||
};
|
||||
let graph_bytes = include_bytes!("../resources/graph.bin");
|
||||
|
||||
Self {
|
||||
identifier: hash_to_field(identifier),
|
||||
pkey_and_constraints: pk_and_matrices,
|
||||
graph: graph_bytes.to_vec(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Data to be proven by RLN
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RlnData {
|
||||
/// message index (in a given epoch)
|
||||
pub message_id: Fr,
|
||||
/// message / signal hashed (bytes hashed to a field element type)
|
||||
pub data: Fr,
|
||||
}
|
||||
|
||||
pub fn compute_rln_proof_and_values(
|
||||
user_identity: &RlnUserIdentity,
|
||||
rln_identifier: &RlnIdentifier,
|
||||
rln_data: RlnData,
|
||||
epoch: Fr,
|
||||
merkle_proof: &rln::poseidon_tree::MerkleProof,
|
||||
) -> Result<(Proof<Bn254>, RLNProofValues), ProofError> {
|
||||
let external_nullifier = poseidon_hash(&[rln_identifier.identifier, epoch]);
|
||||
|
||||
let witness = rln_witness_from_values(
|
||||
user_identity.secret_hash,
|
||||
merkle_proof,
|
||||
rln_data.data,
|
||||
external_nullifier,
|
||||
user_identity.user_limit,
|
||||
rln_data.message_id,
|
||||
)?;
|
||||
|
||||
let proof_values = proof_values_from_witness(&witness)?;
|
||||
let proof = generate_proof(
|
||||
&rln_identifier.pkey_and_constraints,
|
||||
&witness,
|
||||
rln_identifier.graph.as_slice(),
|
||||
)?;
|
||||
Ok((proof, proof_values))
|
||||
}
|
||||
Reference in New Issue
Block a user