event_graph: added account registeration zk circuit, removed old privmsg struct, plust few small fixes

This commit is contained in:
dasman
2026-01-10 20:00:33 +03:00
parent fac3892c4b
commit e9141d5831
14 changed files with 273 additions and 167 deletions

View File

@@ -15,8 +15,7 @@ RUST_TARGET = $(shell rustc -Vv | grep '^host: ' | cut -d' ' -f2)
# List of zkas circuits to compile, used for tests
PROOFS_SRC = \
$(shell find proof -type f -name '*.zk') \
$(shell find bin/darkirc/proof -type f -name '*.zk')
$(shell find proof -type f -name '*.zk')
PROOFS_BIN = $(PROOFS_SRC:=.bin)

View File

@@ -43,13 +43,15 @@ pub const RLN_GENESIS: u64 = 1_738_688_400_000;
/// RLN epoch length in millis
pub const RLN_EPOCH_LEN: u64 = 600_000; // 10 min
pub const RLN2_REGISTER_ZKBIN: &[u8] =
include_bytes!("../../../../src/event_graph/proof/rlnv2-diff-register.zk.bin");
pub const RLN2_SIGNAL_ZKBIN: &[u8] =
include_bytes!("../../../../src/event_graph/proofs/rlnv2-diff-signal.zk.bin");
include_bytes!("../../../../src/event_graph/proof/rlnv2-diff-signal.zk.bin");
pub const RLN2_SLASH_ZKBIN: &[u8] =
include_bytes!("../../../../src/event_graph/proofs/rlnv2-diff-slash.zk.bin");
include_bytes!("../../../../src/event_graph/proof/rlnv2-diff-slash.zk.bin");
/// TODO: this should be configurable
pub const USER_MSG_LIMIT: u64 = 6;
pub const MAX_MSG_LIMIT: u64 = 20;
/// Find closest epoch to given timestamp
pub fn closest_epoch(timestamp: u64) -> u64 {
@@ -85,8 +87,8 @@ impl RlnIdentity {
pallas::Base::random(&mut rng),
]),
trapdoor: poseidon_hash([RLN_TRAPDOOR_DERIVATION_PATH, pallas::Base::random(&mut rng)]),
user_message_limit: USER_MSG_LIMIT,
message_id: 1,
user_message_limit: MAX_MSG_LIMIT,
message_id: 0,
last_epoch: closest_epoch(UNIX_EPOCH.elapsed().unwrap().as_millis() as u64),
}
}
@@ -98,6 +100,36 @@ impl RlnIdentity {
poseidon_hash([identity_secret_hash])
}
pub fn create_register_proof(
&self,
event: &Event,
identities_tree: &mut SmtMemoryFp,
register_pk: &ProvingKey,
) -> Result<Proof> {
let witnesses = vec![
Witness::Base(Value::known(self.nullifier)),
Witness::Base(Value::known(self.trapdoor)),
Witness::Base(Value::known(pallas::Base::from(self.user_message_limit))),
Witness::Base(Value::known(pallas::Base::from(MAX_MSG_LIMIT))),
];
let commitment = self.commitment();
let public_inputs = vec![commitment, pallas::Base::from(self.user_message_limit)];
info!(target: "crypto::rln::create_register_proof", "[RLN] Creating register proof for account {}", event.header.id());
let register_zkbin = ZkBinary::decode(RLN2_REGISTER_ZKBIN)?;
let register_circuit = ZkCircuit::new(witnesses, &register_zkbin);
let proof =
Proof::create(&register_pk, &[register_circuit], &public_inputs, &mut OsRng).unwrap();
let leaf = vec![commitment];
let leaf: Vec<_> = leaf.into_iter().map(|l| (l, l)).collect();
// TODO: Recipients should verify that identity doesn't exist already before insert.
identities_tree.insert_batch(leaf.clone()).unwrap(); // leaf == pos
Ok(proof)
}
pub fn create_signal_proof(
&self,
event: &Event,
@@ -117,10 +149,11 @@ impl RlnIdentity {
let internal_nullifier = poseidon_hash([a_1]);
// 2. Inclusion proof
let commitment = self.commitment();
let identity_root = identity_tree.root();
let identity_path = identity_tree.prove_membership(&self.commitment());
let identity_path = identity_tree.prove_membership(&commitment);
// TODO: Delete me later
assert!(identity_path.verify(&identity_root, &self.commitment(), &self.commitment()));
assert!(identity_path.verify(&identity_root, &commitment, &commitment));
// 3. Create ZK proof
let witnesses = vec![

View File

@@ -47,7 +47,7 @@ use tracing::{debug, error, info, warn};
use super::{
server::{IrcServer, MAX_MSG_LEN},
Msg, NickServ, OldPrivmsg, SERVER_NAME,
NickServ, Privmsg, SERVER_NAME,
};
use crate::crypto::rln::{closest_epoch, RlnIdentity, RLN2_SIGNAL_ZKBIN};
@@ -214,7 +214,7 @@ impl Client {
// If we have a RLN identity, now we'll build a ZK proof.
// Also I really want GOTO in Rust... Fags.
if let Some(mut rln_identity) = *self.server.rln_identity.write().await {
if let Some(ref mut rln_identity) = *self.server.rln_identity.write().await {
// If the current epoch is different, we can reset the message counter
if rln_identity.last_epoch != closest_epoch(event.header.timestamp) {
rln_identity.last_epoch = closest_epoch(event.header.timestamp);
@@ -266,7 +266,6 @@ impl Client {
// <file:./command.rs::async fn get_history(&self, channels: &HashSet<String>) -> Result<Vec<ReplyType>> {>
// for which the logic for delivery should be kept in sync
r = self.incoming.receive().fuse() => {
info!("incoming: {:?}", r);
// We will skip this if it's our own message.
let event_id = r.header.id();
if *self.last_sent.read().await == event_id {
@@ -284,11 +283,10 @@ impl Client {
}
// Try to deserialize the `Event`'s content into a `Privmsg`
let mut privmsg = match Msg::deserialize(r.content()).await {
Ok(Msg::V1(old_msg)) => old_msg.into_new(),
Ok(Msg::V2(new_msg)) => new_msg,
let mut privmsg = match deserialize_async_partial(r.content()).await {
Ok((v, _)) => v,
Err(e) => {
error!("[IRC CLIENT] Failed deserializing incoming Privmsg event: {e}");
error!(target: "irc::client", "[IRC CLIENT] Failed deserializing event: {e}");
continue
}
};
@@ -370,7 +368,7 @@ impl Client {
{
Ok((v, _)) => v,
Err(e) => {
error!(target: "irc::server", "[RLN] Failed deserializing incoming RLN Identity events: {}", e);
error!(target: "irc::client", "[RLN] Failed deserializing incoming RLN Identity events: {}", e);
continue
}
};
@@ -542,11 +540,18 @@ impl Client {
// Truncate messages longer than MAX_MSG_LEN
let msg = if msg.len() > MAX_MSG_LEN { msg.split_at(MAX_MSG_LEN).0 } else { msg };
OldPrivmsg { channel, nick, msg: msg.to_string() }
}
// Internal helper function that creates an Event from PRIVMSG arguments
async fn privmsg_to_event(&self, mut privmsg: OldPrivmsg) -> Event {
// TODO: This is kept as old version of privmsg, since now we
// can deserialize both old and new versions, after some time
// this will be replaced with Privmsg (new version)
let mut privmsg = Privmsg {
version: 0,
channel,
nick: self.nickname.read().await.to_string(),
msg: msg.to_string(),
msg_type: 0,
};
// Encrypt the Privmsg if an encryption method is available.
self.server.try_encrypt(&mut privmsg).await;

View File

@@ -52,13 +52,14 @@
use std::{collections::HashSet, sync::atomic::Ordering::SeqCst};
use darkfi::Result;
use darkfi_serial::deserialize_async_partial;
use tracing::{error, info};
use super::{
client::{Client, ReplyType},
rpl::*,
server::MAX_NICK_LEN,
IrcChannel, Msg, SERVER_NAME,
IrcChannel, SERVER_NAME,
};
use crate::crypto::bcrypt::bcrypt_hash_password;
@@ -931,9 +932,8 @@ impl Client {
}
// Try to deserialize it. (Here we skip errors)
let mut privmsg = match Msg::deserialize(event.content()).await {
Ok(Msg::V1(old_msg)) => old_msg.into_new(),
Ok(Msg::V2(new_msg)) => new_msg,
let mut privmsg = match deserialize_async_partial(event.content()).await {
Ok((v, _)) => v,
Err(_) => continue,
};

View File

@@ -19,8 +19,7 @@
use std::{collections::HashSet, sync::Arc};
use crypto_box::ChaChaBox;
use darkfi::{Error, Result};
use darkfi_serial::{async_trait, deserialize_async_partial, SerialDecodable, SerialEncodable};
use darkfi_serial::{async_trait, SerialDecodable, SerialEncodable};
/// IRC client state
pub(crate) mod client;
@@ -41,32 +40,6 @@ pub(crate) mod rpl;
/// Hardcoded server name
const SERVER_NAME: &str = "irc.dark.fi";
pub trait Priv {
fn channel(&mut self) -> &mut String;
fn nick(&mut self) -> &mut String;
fn msg(&mut self) -> &mut String;
}
/// IRC PRIVMSG (old version)
#[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
pub struct OldPrivmsg {
pub channel: String,
pub nick: String,
pub msg: String,
}
impl OldPrivmsg {
pub fn into_new(self) -> Privmsg {
Privmsg {
version: 0,
msg_type: 0,
channel: self.channel.clone(),
nick: self.nick.clone(),
msg: self.msg.clone(),
}
}
}
/// IRC PRIVMSG (new version)
#[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
pub struct Privmsg {
@@ -77,54 +50,6 @@ pub struct Privmsg {
pub msg: String,
}
impl Priv for OldPrivmsg {
fn channel(&mut self) -> &mut String {
&mut self.channel
}
fn nick(&mut self) -> &mut String {
&mut self.nick
}
fn msg(&mut self) -> &mut String {
&mut self.msg
}
}
impl Priv for Privmsg {
fn channel(&mut self) -> &mut String {
&mut self.channel
}
fn nick(&mut self) -> &mut String {
&mut self.nick
}
fn msg(&mut self) -> &mut String {
&mut self.msg
}
}
pub enum Msg {
V1(OldPrivmsg),
V2(Privmsg),
}
impl Msg {
pub async fn deserialize(bytes: &[u8]) -> Result<Self> {
let old_privmsg = deserialize_async_partial(bytes).await;
if let Ok((old_msg, _)) = old_privmsg {
return Ok(Msg::V1(old_msg))
}
let new_privmsg = deserialize_async_partial(bytes).await;
if let Ok((new_msg, _)) = new_privmsg {
return Ok(Msg::V2(new_msg))
}
Err(Error::Custom("Unknown message format".into()))
}
}
/// IRC channel definition
#[derive(Clone)]
pub struct IrcChannel {

View File

@@ -22,7 +22,7 @@ use darkfi::{
event_graph::Event,
system::{StoppableTask, StoppableTaskPtr, Subscription},
util::path::expand_path,
zk::{empty_witnesses, ProvingKey, VerifyingKey, ZkCircuit},
zk::{empty_witnesses, ProvingKey, ZkCircuit},
zkas::ZkBinary,
Error, Result,
};
@@ -49,11 +49,11 @@ use url::Url;
use super::{
client::Client,
services::nickserv::{ACCOUNTS_DB_PREFIX, ACCOUNTS_KEY_RLN_IDENTITY},
IrcChannel, IrcContact, Priv, Privmsg,
IrcChannel, IrcContact, Privmsg,
};
use crate::{
crypto::{
rln::{RlnIdentity, RLN2_SIGNAL_ZKBIN, RLN2_SLASH_ZKBIN},
rln::{RlnIdentity, RLN2_REGISTER_ZKBIN, RLN2_SIGNAL_ZKBIN, RLN2_SLASH_ZKBIN},
saltbox,
},
settings::{
@@ -156,7 +156,28 @@ impl IrcServer {
let mut identity_tree = SmtMemoryFp::new(store, hasher.clone(), &EMPTY_NODES_FP);
// Generate RLN proving and verifying keys, if needed
let rln_signal_zkbin = ZkBinary::decode(RLN2_SIGNAL_ZKBIN, false)?;
let rln_register_zkbin = ZkBinary::decode(RLN2_REGISTER_ZKBIN)?;
let rln_register_circuit =
ZkCircuit::new(empty_witnesses(&rln_register_zkbin)?, &rln_register_zkbin);
if server_store.get("rlnv2-diff-register-pk")?.is_none() {
info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Register ProvingKey");
let provingkey = ProvingKey::build(rln_register_zkbin.k, &rln_register_circuit);
let mut buf = vec![];
provingkey.write(&mut buf)?;
server_store.insert("rlnv2-diff-register-pk", buf)?;
}
// if server_store.get("rlnv2-diff-register-vk")?.is_none() {
// info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Register VerifyingKey");
// let verifyingkey = VerifyingKey::build(rln_register_zkbin.k, &rln_register_circuit);
// let mut buf = vec![];
// verifyingkey.write(&mut buf)?;
// server_store.insert("rlnv2-diff-register-vk", buf)?;
// }
// Generate RLN proving and verifying keys, if needed
let rln_signal_zkbin = ZkBinary::decode(RLN2_SIGNAL_ZKBIN)?;
let rln_signal_circuit =
ZkCircuit::new(empty_witnesses(&rln_signal_zkbin)?, &rln_signal_zkbin);
@@ -168,33 +189,37 @@ impl IrcServer {
server_store.insert("rlnv2-diff-signal-pk", buf)?;
}
if server_store.get("rlnv2-diff-signal-vk")?.is_none() {
info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Signal VerifyingKey");
let verifyingkey = VerifyingKey::build(rln_signal_zkbin.k, &rln_signal_circuit);
let mut buf = vec![];
verifyingkey.write(&mut buf)?;
server_store.insert("rlnv2-diff-signal-vk", buf)?;
}
// if server_store.get("rlnv2-diff-signal-vk")?.is_none() {
// info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Signal VerifyingKey");
// let verifyingkey = VerifyingKey::build(rln_signal_zkbin.k, &rln_signal_circuit);
// let mut buf = vec![];
// verifyingkey.write(&mut buf)?;
// server_store.insert("rlnv2-diff-signal-vk", buf)?;
// }
// Generate RLN proving and verifying keys, if needed
let rln_slash_zkbin = ZkBinary::decode(RLN2_SLASH_ZKBIN)?;
let rln_slash_circuit =
ZkCircuit::new(empty_witnesses(&rln_slash_zkbin)?, &rln_slash_zkbin);
if server_store.get("rlnv2-diff-slash-pk")?.is_none() {
info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Slash ProvingKey");
let zkbin = ZkBinary::decode(RLN2_SLASH_ZKBIN, false)?;
let circuit = ZkCircuit::new(empty_witnesses(&zkbin).unwrap(), &zkbin);
let provingkey = ProvingKey::build(zkbin.k, &circuit);
let provingkey = ProvingKey::build(rln_slash_zkbin.k, &rln_slash_circuit);
let mut buf = vec![];
provingkey.write(&mut buf)?;
server_store.insert("rlnv2-diff-slash-pk", buf)?;
}
if server_store.get("rlnv2-diff-slash-vk")?.is_none() {
info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Slash VerifyingKey");
let zkbin = ZkBinary::decode(RLN2_SLASH_ZKBIN, false)?;
let circuit = ZkCircuit::new(empty_witnesses(&zkbin).unwrap(), &zkbin);
let verifyingkey = VerifyingKey::build(zkbin.k, &circuit);
let mut buf = vec![];
verifyingkey.write(&mut buf)?;
server_store.insert("rlnv2-diff-slash-vk", buf)?;
}
// if server_store.get("rlnv2-diff-slash-vk")?.is_none() {
// info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Slash VerifyingKey");
// let verifyingkey = VerifyingKey::build(rln_slash_zkbin.k, &rln_slash_circuit);
// let mut buf = vec![];
// verifyingkey.write(&mut buf)?;
// server_store.insert("rlnv2-diff-slash-vk", buf)?;
// }
// Construct SMT from static DAG
let mut events = darkirc.event_graph.static_fetch_all().await?;
@@ -403,28 +428,28 @@ impl IrcServer {
}
/// Try encrypting a given `Privmsg` if there is such a channel/contact.
pub async fn try_encrypt<T: Priv>(&self, privmsg: &mut T) {
if let Some((name, channel)) = self.channels.read().await.get_key_value(privmsg.channel()) {
pub async fn try_encrypt(&self, privmsg: &mut Privmsg) {
if let Some((name, channel)) = self.channels.read().await.get_key_value(&privmsg.channel) {
if let Some(saltbox) = &channel.saltbox {
// We will use a dummy channel value of MAX_NICK_LEN,
// since its not used, so all encrypted messages look the same.
*privmsg.channel() = saltbox::encrypt(saltbox, &[0x00; MAX_NICK_LEN]);
privmsg.channel = saltbox::encrypt(saltbox, &[0x00; MAX_NICK_LEN]);
// We will pad the name to MAX_NICK_LEN so they all look the same
*privmsg.nick() = saltbox::encrypt(saltbox, &Self::pad(privmsg.nick()));
*privmsg.msg() = saltbox::encrypt(saltbox, privmsg.msg().as_bytes());
privmsg.nick = saltbox::encrypt(saltbox, &Self::pad(&privmsg.nick));
privmsg.msg = saltbox::encrypt(saltbox, privmsg.msg.as_bytes());
debug!("Successfully encrypted message for {name}");
return
}
};
if let Some((name, contact)) = self.contacts.read().await.get_key_value(privmsg.channel()) {
if let Some((name, contact)) = self.contacts.read().await.get_key_value(&privmsg.channel) {
// We will use dummy channel and nick values of MAX_NICK_LEN,
// since they are not used, so all encrypted messages look the same.
*privmsg.channel() = saltbox::encrypt(&contact.saltbox, &[0x00; MAX_NICK_LEN]);
privmsg.channel = saltbox::encrypt(&contact.saltbox, &[0x00; MAX_NICK_LEN]);
// We will encrypt the dummy nick value using our own self saltbox,
// so we can identify our messages.
*privmsg.nick() = saltbox::encrypt(&contact.self_saltbox, &[0x00; MAX_NICK_LEN]);
*privmsg.msg() = saltbox::encrypt(&contact.saltbox, privmsg.msg().as_bytes());
privmsg.nick = saltbox::encrypt(&contact.self_saltbox, &[0x00; MAX_NICK_LEN]);
privmsg.msg = saltbox::encrypt(&contact.saltbox, privmsg.msg.as_bytes());
debug!("Successfully encrypted message for {name}");
};
}

View File

@@ -16,16 +16,21 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use std::{str::SplitAsciiWhitespace, sync::Arc, time::UNIX_EPOCH};
use std::{io::Cursor, str::SplitAsciiWhitespace, sync::Arc, time::UNIX_EPOCH};
use darkfi::{event_graph::Event, Result};
use darkfi::{
event_graph::Event,
zk::{empty_witnesses, ProvingKey, ZkCircuit},
zkas::ZkBinary,
Error, Result,
};
use darkfi_sdk::{crypto::pasta_prelude::PrimeField, pasta::pallas};
use darkfi_serial::serialize_async;
use smol::lock::RwLock;
use super::super::{client::ReplyType, rpl::*};
use crate::{
crypto::rln::{closest_epoch, RlnIdentity, USER_MSG_LIMIT},
crypto::rln::{closest_epoch, RlnIdentity, RLN2_REGISTER_ZKBIN},
IrcServer,
};
@@ -139,7 +144,8 @@ impl NickServ {
let account_name = account_name.unwrap();
let identity_nullifier = identity_nullifier.unwrap();
let identity_trapdoor = identity_trapdoor.unwrap();
let _user_msg_limit = user_msg_limit.unwrap();
let user_msg_limit: u64 =
user_msg_limit.unwrap().parse().expect("msg limit must be a number");
// Open the sled tree
let db =
@@ -188,9 +194,9 @@ impl NickServ {
let new_rln_identity = RlnIdentity {
nullifier: identity_nullifier,
trapdoor: identity_trapdoor,
user_message_limit: USER_MSG_LIMIT,
message_id: 1, // TODO
last_epoch: closest_epoch(UNIX_EPOCH.elapsed().unwrap().as_secs()),
user_message_limit: user_msg_limit,
message_id: 0, // TODO
last_epoch: closest_epoch(UNIX_EPOCH.elapsed().unwrap().as_millis() as u64),
};
// Store account
@@ -204,17 +210,30 @@ impl NickServ {
*self.server.rln_identity.write().await = Some(new_rln_identity);
// Update SMT, DAG and broadcast
let mut identities_tree = self.server.rln_identity_tree.write().await;
let rln_commitment = new_rln_identity.commitment();
let commitment = vec![rln_commitment];
let commitment: Vec<_> = commitment.into_iter().map(|l| (l, l)).collect();
identities_tree.insert_batch(commitment)?;
let evgr = &self.server.darkirc.event_graph;
let event = Event::new_static(serialize_async(&rln_commitment).await, evgr).await;
let mut identity_tree = self.server.rln_identity_tree.write().await;
// Retrieve the register ZK proving key from the db
let register_zkbin = ZkBinary::decode(RLN2_REGISTER_ZKBIN)?;
let register_circuit = ZkCircuit::new(empty_witnesses(&register_zkbin)?, &register_zkbin);
let Some(proving_key) = self.server.server_store.get("rlnv2-diff-register-pk")? else {
return Err(Error::DatabaseError(
"RLN register proving key not found in server store".to_string(),
))
};
let mut reader = Cursor::new(proving_key);
let proving_key = ProvingKey::read(&mut reader, register_circuit)?;
let proof =
new_rln_identity.create_register_proof(&event, &mut identity_tree, &proving_key)?;
let blob = serialize_async(&(proof, user_msg_limit)).await;
evgr.static_insert(&event).await?;
evgr.static_broadcast(event).await?;
evgr.static_broadcast(event, blob).await?;
Ok(vec![ReplyType::Notice((
"NickServ".to_string(),

View File

@@ -238,7 +238,7 @@ pub fn parse_rln_identity(data: &toml::Value) -> Result<Option<RlnIdentity>> {
user_message_limit,
// TODO: FIXME: We should probably keep track of these rather than
// resetting here
message_id: 1,
message_id: 0,
last_epoch: closest_epoch(UNIX_EPOCH.elapsed().unwrap().as_secs()),
}))
}

View File

@@ -101,6 +101,10 @@ pub const NULL_PARENTS: [Hash; N_EVENT_PARENTS] = [NULL_ID; N_EVENT_PARENTS];
/// Maximum number of DAGs to store, this should be configurable
pub const DAGS_MAX_NUMBER: i8 = 24;
pub const RLN2_REGISTER_ZKBIN: &[u8] = include_bytes!("proof/rlnv2-diff-register.zk.bin");
pub const RLN2_SIGNAL_ZKBIN: &[u8] = include_bytes!("proof/rlnv2-diff-signal.zk.bin");
pub const RLN2_SLASH_ZKBIN: &[u8] = include_bytes!("proof/rlnv2-diff-slash.zk.bin");
/// Atomic pointer to an [`EventGraph`] instance.
pub type EventGraphPtr = Arc<EventGraph>;
pub type LayerUTips = BTreeMap<u64, HashSet<blake3::Hash>>;
@@ -369,8 +373,12 @@ pub struct EventGraph {
deg_publisher: PublisherPtr<DegEvent>,
/// Run in fast mode where if set we sync only headers.
fast_mode: bool,
/// Registering verify key
register_vk: VerifyingKey,
/// Signaling verify key
signal_vk: VerifyingKey,
/// Slashing verify key
slash_vk: VerifyingKey,
}
impl EventGraph {
@@ -396,8 +404,27 @@ impl EventGraph {
ex: Arc<Executor<'_>>,
) -> Result<EventGraphPtr> {
// Read or build signal verifying key
let signal_zkbin = include_bytes!("proofs/rlnv2-diff-signal.zk.bin");
let signal_zkbin = ZkBinary::decode(signal_zkbin, false).unwrap();
let register_zkbin = ZkBinary::decode(RLN2_REGISTER_ZKBIN, false).unwrap();
let register_empty_circuit =
ZkCircuit::new(empty_witnesses(&register_zkbin).unwrap(), &register_zkbin);
let register_vk = match sled_db.get("rlnv2-diff-register-vk")? {
Some(vk) => {
let mut reader = Cursor::new(vk);
VerifyingKey::read(&mut reader, register_empty_circuit)?
}
None => {
info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Register VerifyingKey");
let verifyingkey = VerifyingKey::build(register_zkbin.k, &register_empty_circuit);
let mut buf = vec![];
verifyingkey.write(&mut buf)?;
sled_db.insert("rlnv2-diff-register-vk", buf)?;
verifyingkey
}
};
// Read or build signal verifying key
let signal_zkbin = ZkBinary::decode(RLN2_SIGNAL_ZKBIN, false).unwrap();
let signal_empty_circuit =
ZkCircuit::new(empty_witnesses(&signal_zkbin).unwrap(), &signal_zkbin);
@@ -416,6 +443,26 @@ impl EventGraph {
}
};
// Read or build slash verifying key
let slash_zkbin = ZkBinary::decode(RLN2_SLASH_ZKBIN, false).unwrap();
let slash_empty_circuit =
ZkCircuit::new(empty_witnesses(&slash_zkbin).unwrap(), &slash_zkbin);
let slash_vk = match sled_db.get("rlnv2-diff-slash-vk")? {
Some(vk) => {
let mut reader = Cursor::new(vk);
VerifyingKey::read(&mut reader, slash_empty_circuit)?
}
None => {
info!(target: "irc::server", "[RLN] Creating RlnV2_Diff_Slash VerifyingKey");
let verifyingkey = VerifyingKey::build(slash_zkbin.k, &slash_empty_circuit);
let mut buf = vec![];
verifyingkey.write(&mut buf)?;
sled_db.insert("rlnv2-diff-slash-vk", buf)?;
verifyingkey
}
};
let broadcasted_ids = RwLock::new(HashSet::new());
let event_pub = Publisher::new();
let static_pub = Publisher::new();
@@ -449,7 +496,9 @@ impl EventGraph {
synced: RwLock::new(false),
deg_enabled: RwLock::new(false),
deg_publisher: Publisher::new(),
register_vk,
signal_vk,
slash_vk,
});
// Check if we have it in our DAG.
@@ -1285,8 +1334,8 @@ impl EventGraph {
Ok(())
}
pub async fn static_broadcast(&self, event: Event) -> Result<()> {
self.p2p.broadcast(&StaticPut(event)).await;
pub async fn static_broadcast(&self, event: Event, blob: Vec<u8>) -> Result<()> {
self.p2p.broadcast(&StaticPut(event, blob)).await;
Ok(())
}

View File

@@ -0,0 +1,22 @@
k = 11;
field = "pallas";
constant "Rlnv2Diff_Register" {}
witness "Rlnv2Diff_Register" {
Base identity_nullifier,
Base identity_trapdoor,
Base user_message_limit,
Base message_limit,
}
circuit "Rlnv2Diff_Register" {
identity_secret = poseidon_hash(identity_nullifier, identity_trapdoor);
identity_secret_hash = poseidon_hash(identity_secret, user_message_limit);
identity_commitment = poseidon_hash(identity_secret_hash);
less_than_strict(user_message_limit, message_limit);
constrain_instance(identity_commitment);
constrain_instance(user_message_limit);
}

View File

@@ -26,7 +26,10 @@ use std::{
},
};
use darkfi_sdk::{crypto::poseidon_hash, pasta::pallas};
use darkfi_sdk::{
crypto::{poseidon_hash, util::FieldElemAsStr},
pasta::{pallas, Fp},
};
use darkfi_serial::{
async_trait, deserialize_async, deserialize_async_partial, SerialDecodable, SerialEncodable,
};
@@ -146,7 +149,7 @@ impl_p2p_message!(EventPut, "EventGraph::EventPut", 0, 0, DEFAULT_METERING_CONFI
/// A P2P message representing publishing an event of a static graph
/// (most likely RLN_identities) on the network
#[derive(Clone, SerialEncodable, SerialDecodable)]
pub struct StaticPut(pub Event);
pub struct StaticPut(pub Event, pub Vec<u8>);
impl_p2p_message!(StaticPut, "EventGraph::StaticPut", 0, 0, DEFAULT_METERING_CONFIGURATION);
/// A P2P message representing an event request
@@ -299,6 +302,9 @@ impl ProtocolEventGraph {
let mut verification_failed = false;
#[allow(clippy::never_loop)]
loop {
if blob.is_empty() {
break
}
let (proof, y, internal_nullifier, identity_root): (
Proof,
pallas::Base,
@@ -325,15 +331,15 @@ impl ProtocolEventGraph {
let public_inputs =
vec![identity_root, external_nullifier, x, y, internal_nullifier];
metadata.add_share(external_nullifier, internal_nullifier, x, y)?;
if metadata.is_duplicate(&external_nullifier, &internal_nullifier, &x, &y) {
error!("[Signal] Duplicate Message!");
error!(target: "event_graph::protocol::handle_event_put()", "[EVENTGRAPH] Duplicate Message!");
verification_failed = true;
break
}
info!("internal nullifier: {}", internal_nullifier.to_string());
if metadata.is_reused(&external_nullifier, &internal_nullifier) {
info!(target: "event_graph::protocol::handle_event_put()", "[EVENTGRAPH] Metadata is reused.. slashing..");
let shares = metadata.get_shares(&external_nullifier, &internal_nullifier);
let _secret = sss_recover(&shares);
@@ -346,6 +352,9 @@ impl ProtocolEventGraph {
break
}
// At this point we can safely add the shares
metadata.add_share(external_nullifier, internal_nullifier, x, y)?;
info!(target: "event_graph::protocol::handle_event_put()", "[EVENTGRAPH] Verifying incoming Event RLN proof");
verification_failed =
proof.verify(&self.event_graph.signal_vk, &public_inputs).is_err();
@@ -354,7 +363,7 @@ impl ProtocolEventGraph {
}
if verification_failed {
error!(target: "event_graph::protocol::handle_event_put()", "[EVENTGRAPH] Incoming Event RLN proof verification failed");
error!(target: "event_graph::protocol::handle_event_put()", "[EVENTGRAPH] Incoming Event RLN Signaling proof verification failed");
continue
}
@@ -611,21 +620,19 @@ impl ProtocolEventGraph {
let mut bantimes = MovingWindow::new(WINDOW_EXPIRY_TIME);
loop {
let event = match self.st_put_sub.receive().await {
Ok(v) => v.0.clone(),
let (event, blob) = match self.st_put_sub.receive().await {
Ok(v) => (v.0.clone(), v.1.clone()),
Err(_) => continue,
};
trace!(
target: "event_graph::protocol::handle_event_put()",
"Got EventPut: {} [{}]", event.id(), self.channel.address(),
target: "event_graph::protocol::handle_static_put()",
"Got StaticPut: {} [{}]", event.id(), self.channel.address(),
);
info!("Received a static event: {:?}", event);
// Check if node has finished syncing its DAG
if !*self.event_graph.synced.read().await {
debug!(
target: "event_graph::protocol::handle_event_put",
target: "event_graph::protocol::handle_static_put",
"DAG is still syncing, skipping..."
);
continue
@@ -640,6 +647,30 @@ impl ProtocolEventGraph {
continue
}
if !blob.is_empty() {
let (proof, user_msg_limit): (Proof, u64) = match deserialize_async_partial(&blob)
.await
{
Ok((v, _)) => v,
Err(e) => {
error!(target: "event_graph::protocol::handle_static_put()","[EVENTGRAPH] Failed deserializing event ephemeral data: {}", e);
continue
}
};
let commitment: Fp = match deserialize_async_partial(&event.content()).await {
Ok((v, _)) => v,
Err(e) => {
error!(target: "event_graph::protocol::handle_static_put()","[EVENTGRAPH] Failed deserializing event ephemeral data: {}", e);
continue
}
};
let public_inputs = vec![commitment, user_msg_limit.into()];
if proof.verify(&self.event_graph.register_vk, &public_inputs).is_err() {
error!(target: "event_graph::protocol::handle_static_put()", "[EVENTGRAPH] Incoming Event RLN Registration proof verification failed");
continue
}
}
// Check if event's parents are in the static DAG
for parent in event.header.parents.iter() {
if *parent == NULL_ID {
@@ -679,7 +710,7 @@ impl ProtocolEventGraph {
);
self.event_graph.static_insert(&event).await?;
self.event_graph.static_broadcast(event).await?
self.event_graph.static_broadcast(event, blob).await?
}
}

View File

@@ -304,11 +304,9 @@ impl MessageMetadata {
external_nullifier: &pallas::Base,
internal_nullifier: &pallas::Base,
) -> bool {
let inner_map = self.data.get(external_nullifier);
if inner_map.is_some() {
return inner_map.unwrap().get(internal_nullifier).is_some()
if let Some(inner_map) = self.data.get(external_nullifier) {
return inner_map.get(internal_nullifier).is_some()
}
false
}
}