Bladeren bron

research/rlnd: Remove obsolete code

x 1 maand geleden
bovenliggende
commit
698892878b

+ 0 - 3
script/research/rlnd/rlnd-cli/.gitignore

@@ -1,3 +0,0 @@
-/target
-Cargo.lock
-rustfmt.toml

+ 0 - 42
script/research/rlnd/rlnd-cli/src/lib.rs

@@ -1,42 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2026 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::sync::Arc;
-
-use darkfi::{rpc::client::RpcClient, Result};
-use smol::Executor;
-use url::Url;
-
-/// rlnd JSON-RPC related methods
-pub mod rpc;
-
-/// CLI-util structure
-pub struct RlndCli {
-    /// JSON-RPC client to execute requests to darkfid daemon
-    pub rpc_client: RpcClient,
-}
-
-impl RlndCli {
-    pub async fn new(endpoint: &str, ex: Arc<Executor<'static>>) -> Result<Self> {
-        // Initialize rpc client
-        let endpoint = Url::parse(endpoint)?;
-        let rpc_client = RpcClient::new(endpoint, ex).await?;
-
-        Ok(Self { rpc_client })
-    }
-}

+ 0 - 118
script/research/rlnd/rlnd-cli/src/main.rs

@@ -1,118 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2026 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::sync::Arc;
-
-use clap::{Parser, Subcommand};
-use darkfi::{cli_desc, Result};
-use prettytable::{format, row, Table};
-use smol::Executor;
-
-use rlnd_cli::RlndCli;
-
-#[derive(Parser)]
-#[command(about = cli_desc!())]
-struct Args {
-    #[arg(short, long, default_value = "tcp://127.0.0.1:25637")]
-    /// rldn JSON-RPC endpoint
-    endpoint: String,
-
-    #[command(subcommand)]
-    /// Sub command to execute
-    command: Subcmd,
-}
-
-#[derive(Subcommand)]
-enum Subcmd {
-    /// Send a ping request to the rlnd RPC endpoint
-    Ping,
-
-    /// List all memberships
-    List,
-
-    /// Register a membership
-    Register {
-        /// Stake of this membership
-        stake: u64,
-    },
-
-    /// Slash a membership
-    Slash {
-        /// Membership id to slash
-        id: String,
-    },
-}
-
-fn main() -> Result<()> {
-    // Initialize an executor
-    let executor = Arc::new(Executor::new());
-    let ex = executor.clone();
-    smol::block_on(executor.run(async {
-        // Parse arguments
-        let args = Args::parse();
-
-        // Execute a subcommand
-        let rlnd_cli = RlndCli::new(&args.endpoint, ex).await?;
-        match args.command {
-            Subcmd::Ping => {
-                rlnd_cli.ping().await?;
-            }
-
-            Subcmd::List => {
-                match rlnd_cli.get_all_memberships().await {
-                    Ok(memberships) => {
-                        // Create a prettytable with the memberships:
-                        let mut table = Table::new();
-                        table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR);
-                        table.set_titles(row!["ID", "Leaf Position", "Stake"]);
-                        for (id, membership) in memberships.iter() {
-                            table.add_row(row![
-                                id,
-                                format!("{:?}", membership.leaf_position),
-                                membership.stake
-                            ]);
-                        }
-
-                        if table.is_empty() {
-                            println!("No memberships found");
-                        } else {
-                            println!("{table}");
-                        }
-                    }
-                    Err(e) => println!("Membership registration failed: {e}"),
-                }
-            }
-
-            Subcmd::Register { stake } => match rlnd_cli.register_membership(stake).await {
-                Ok((id, membership)) => println!("Registered membership {id:?}: {membership:?}"),
-                Err(e) => println!("Membership registration failed: {e}"),
-            },
-
-            Subcmd::Slash { id } => {
-                println!("Slashing membership: {id}");
-                match rlnd_cli.slash_membership(&id).await {
-                    Ok(membership) => println!("Slashed membership {id}: {membership:?}"),
-                    Err(e) => println!("Membership slashing failed: {e}"),
-                }
-            }
-        }
-        rlnd_cli.rpc_client.stop().await;
-
-        Ok(())
-    }))
-}

+ 0 - 119
script/research/rlnd/rlnd-cli/src/rpc.rs

@@ -1,119 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2026 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::time::Instant;
-
-use darkfi::{
-    rpc::{jsonrpc::JsonRequest, util::JsonValue},
-    Error, Result,
-};
-use darkfi_sdk::{
-    crypto::pasta_prelude::{Field, PrimeField},
-    pasta::pallas,
-};
-use darkfi_serial::deserialize;
-use rand::rngs::OsRng;
-use rlnd::database::Membership;
-
-use crate::RlndCli;
-
-impl RlndCli {
-    /// Auxiliary function to ping configured rlnd daemon for liveness.
-    pub async fn ping(&self) -> Result<()> {
-        println!("Executing ping request to rlnd...");
-        let latency = Instant::now();
-        let rep = self.rlnd_daemon_request("ping", &JsonValue::Array(vec![])).await?;
-        let latency = latency.elapsed();
-        println!("Got reply: {rep:?}");
-        println!("Latency: {latency:?}");
-        Ok(())
-    }
-
-    /// Auxiliary function to execute a request towards the configured rlnd daemon JSON-RPC endpoint.
-    pub async fn rlnd_daemon_request(&self, method: &str, params: &JsonValue) -> Result<JsonValue> {
-        let req = JsonRequest::new(method, params.clone());
-        let rep = self.rpc_client.request(req).await?;
-        Ok(rep)
-    }
-
-    /// Queries rlnd to register a new membership for given stake.
-    pub async fn register_membership(&self, stake: u64) -> Result<(String, Membership)> {
-        // Generate a new random membership identity
-        let id = pallas::Base::random(&mut OsRng);
-        let id = bs58::encode(&id.to_repr()).into_string();
-
-        // Generate request params
-        let params = JsonValue::Array(vec![
-            JsonValue::String(id.clone()),
-            JsonValue::String(stake.to_string()),
-        ]);
-
-        // Execute request
-        let rep = self.rlnd_daemon_request("add_membership", &params).await?;
-
-        // Parse response
-        let membership = parse_membership(rep.get::<String>().unwrap())?;
-
-        Ok((id, membership))
-    }
-
-    /// Queries rlnd to retrieve all memberships.
-    pub async fn get_all_memberships(&self) -> Result<Vec<(String, Membership)>> {
-        // Execute request
-        let rep = self.rlnd_daemon_request("get_memberships", &JsonValue::Array(vec![])).await?;
-
-        // Parse response
-        let params = rep.get::<Vec<JsonValue>>().unwrap();
-        let mut ret = Vec::with_capacity(params.len() / 2);
-        for (index, param) in params.iter().enumerate() {
-            // Skip second half of pair
-            if index % 2 == 1 {
-                continue
-            }
-
-            let id = param.get::<String>().unwrap().clone();
-            let membership = parse_membership(params[index + 1].get::<String>().unwrap())?;
-            ret.push((id, membership));
-        }
-
-        Ok(ret)
-    }
-
-    /// Queries rlnd to slash a membership.
-    pub async fn slash_membership(&self, id: &str) -> Result<Membership> {
-        // Generate request params
-        let params = JsonValue::Array(vec![JsonValue::String(id.to_string())]);
-
-        // Execute request
-        let rep = self.rlnd_daemon_request("slash_membership", &params).await?;
-
-        // Parse response
-        let membership = parse_membership(rep.get::<String>().unwrap())?;
-
-        Ok(membership)
-    }
-}
-
-/// Auxiliary function to parse a `Membership` from a `JsonValue::String`.
-pub fn parse_membership(membership: &str) -> Result<Membership> {
-    let Ok(decoded_bytes) = bs58::decode(membership).into_vec() else {
-        return Err(Error::ParseFailed("Invalid Membership"))
-    };
-
-    Ok(deserialize(&decoded_bytes)?)
-}

+ 0 - 3
script/research/rlnd/rlnd/.gitignore

@@ -1,3 +0,0 @@
-/target
-Cargo.lock
-rustfmt.toml

+ 0 - 27
script/research/rlnd/rlnd/rlnd_config.toml

@@ -1,27 +0,0 @@
-## rlnd configuration file
-##
-## Please make sure you go through all the settings so you can configure
-## your daemon properly.
-##
-## The default values are left commented. They can be overridden either by
-## uncommenting, or by using the command-line.
-
-# Path to the database directory
-database = "~/.local/share/darkfi/rlnd"
-
-# Private JSON-RPC settings
-# JSON-RPC listen URL
-private_rpc_listen = "tcp://127.0.0.1:25637"
-
-# Disabled RPC methods
-#private_rpc_disabled_methods = []
-
-# Publicly exposed JSON-RPC settings
-# JSON-RPC listen URL
-public_rpc_listen = "tcp://127.0.0.1:25638"
-
-# Disabled RPC methods
-#public_rpc_disabled_methods = []
-
-# darkirc JSON-RPC endpoint
-endpoint = "tcp://127.0.0.1:26660"

+ 0 - 195
script/research/rlnd/rlnd/src/database.rs

@@ -1,195 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2026 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use darkfi::{util::path::expand_path, Error, Result};
-use darkfi_sdk::{
-    bridgetree::Position,
-    crypto::{pasta_prelude::PrimeField, MerkleNode, MerkleTree},
-    pasta::pallas,
-};
-use darkfi_serial::{async_trait, deserialize, serialize, SerialDecodable, SerialEncodable};
-use sled_overlay::sled;
-
-/// This struct represents a tuple of the form (id, stake).
-#[derive(Debug, Clone, PartialEq, Eq, SerialEncodable, SerialDecodable)]
-pub struct Membership {
-    /// Membership leaf position in the memberships Merkle tree
-    pub leaf_position: Position,
-    /// Member stake value
-    pub stake: u64,
-}
-
-impl Membership {
-    /// Generate a new `Membership` in the memberships tree for provided id and stake.
-    pub fn new(memberships_tree: &mut MerkleTree, id: pallas::Base, stake: u64) -> Self {
-        memberships_tree.append(MerkleNode::from(id));
-        let leaf_position = memberships_tree.mark().unwrap();
-        Self { leaf_position, stake }
-    }
-}
-
-pub const SLED_MAIN_TREE: &[u8] = b"_main";
-pub const SLED_MAIN_TREE_MEMBERSHIPS_TREE_KEY: &[u8] = b"_memberships_tree";
-pub const SLED_MEMBERSHIP_TREE: &[u8] = b"_memberships";
-
-/// Structure holding all sled trees for DarkFi RLN state management.
-#[derive(Clone)]
-pub struct RlndDatabase {
-    /// Main pointer to the sled db connection
-    pub sled_db: sled::Db,
-    /// Main `sled` tree, storing arbitrary data,
-    /// like the memberships Merkle tree.
-    pub main: sled::Tree,
-    /// The `sled` tree storing all the memberships information,
-    /// where the key is the membership id, and the value is the serialized
-    /// structure itself.
-    pub membership: sled::Tree,
-}
-
-impl RlndDatabase {
-    /// Instantiate a new `RlndDatabase`.
-    pub fn new(db_path: &str) -> Result<Self> {
-        // Initialize or open sled database
-        let db_path = expand_path(db_path)?;
-        let sled_db = sled_overlay::sled::open(&db_path)?;
-
-        // Open the database trees
-        let main = sled_db.open_tree(SLED_MAIN_TREE)?;
-        let membership = sled_db.open_tree(SLED_MEMBERSHIP_TREE)?;
-
-        // Check if memberships Merkle tree is initialized
-        if main.get(SLED_MAIN_TREE_MEMBERSHIPS_TREE_KEY)?.is_none() {
-            main.insert(SLED_MAIN_TREE_MEMBERSHIPS_TREE_KEY, serialize(&MerkleTree::new(1)))?;
-        }
-
-        Ok(Self { sled_db, main, membership })
-    }
-
-    /// Retrieve memberships Merkle tree record from the main tree.
-    pub fn get_memberships_tree(&self) -> Result<MerkleTree> {
-        let merkle_tree_bytes = self.main.get(SLED_MAIN_TREE_MEMBERSHIPS_TREE_KEY)?;
-        let merkle_tree = deserialize(&merkle_tree_bytes.unwrap())?;
-        Ok(merkle_tree)
-    }
-
-    /// Generate a new `Membership` record for provided id and stake
-    /// and instert it into the database.
-    pub fn add_membership(&self, id: pallas::Base, stake: u64) -> Result<Membership> {
-        // Grab the memberships Merkle tree
-        let mut memberships_merkle_tree = self.get_memberships_tree()?;
-
-        // Generate the new `Membership`
-        let membership = Membership::new(&mut memberships_merkle_tree, id, stake);
-
-        // Update the memberships Merkle tree record in the database
-        self.main
-            .insert(SLED_MAIN_TREE_MEMBERSHIPS_TREE_KEY, serialize(&memberships_merkle_tree))?;
-
-        // Store the new membership
-        self.membership.insert(id.to_repr(), serialize(&membership))?;
-
-        Ok(membership)
-    }
-
-    /// Retrieve `Membership` by given id.
-    pub fn get_membership_by_id(&self, id: &pallas::Base) -> Result<Membership> {
-        let Some(found) = self.membership.get(id.to_repr())? else {
-            return Err(Error::DatabaseError(format!("Membership was not found for id: {id:?}")))
-        };
-        let membership = deserialize(&found)?;
-        Ok(membership)
-    }
-
-    /// Retrieve all membership records contained in the database.
-    /// Be careful as this will try to load everything in memory.
-    pub fn get_all(&self) -> Result<Vec<(pallas::Base, Membership)>> {
-        let mut memberships = vec![];
-
-        for record in self.membership.iter() {
-            let (key, membership) = record?;
-            let id = convert_pallas_key(&key)?;
-            let membership = deserialize(&membership)?;
-            memberships.push((id, membership));
-        }
-
-        Ok(memberships)
-    }
-
-    /// Remove `Membership` record of given id and rebuild the memberships Merkle tree.
-    pub fn remove_membership_by_id(&self, id: &pallas::Base) -> Result<Membership> {
-        // TODO: add a mutex guard here
-        // Remove membership record
-        let Some(found) = self.membership.remove(id.to_repr())? else {
-            return Err(Error::DatabaseError(format!("Membership was not found for id: {id:?}")))
-        };
-
-        // Rebuild the memberships Merkle tree
-        self.rebuild_memberships_merkle_tree()?;
-
-        Ok(deserialize(&found)?)
-    }
-
-    /// Auxiliary function to rebuild the memberships Merkle tree in the database.
-    pub fn rebuild_memberships_merkle_tree(&self) -> Result<()> {
-        // Create a new Merkle tree
-        let mut memberships_merkle_tree = MerkleTree::new(1);
-
-        // Iterate over keys and generate the new memberships
-        let mut memberships = vec![];
-        for record in self.membership.iter() {
-            let (key, membership) = record?;
-            let id = convert_pallas_key(&key)?;
-            let membership: Membership = deserialize(&membership)?;
-            let membership = Membership::new(&mut memberships_merkle_tree, id, membership.stake);
-            memberships.push((id, membership));
-        }
-
-        // Update the memberships Merkle tree record in the database
-        self.main
-            .insert(SLED_MAIN_TREE_MEMBERSHIPS_TREE_KEY, serialize(&memberships_merkle_tree))?;
-
-        // Store the updated memberships
-        for (id, membership) in memberships {
-            self.membership.insert(id.to_repr(), serialize(&membership))?;
-        }
-
-        Ok(())
-    }
-
-    /// Retrieve stored memberships count.
-    pub fn len(&self) -> usize {
-        self.membership.len()
-    }
-
-    /// Check if database contains any memberships.
-    pub fn is_empty(&self) -> bool {
-        self.membership.is_empty()
-    }
-}
-
-/// Auxiliary function to convert a `pallas::Base` key from an `IVec`.
-fn convert_pallas_key(key: &sled::IVec) -> Result<pallas::Base> {
-    let mut repr = [0; 32];
-    repr.copy_from_slice(key);
-    match pallas::Base::from_repr(repr).into_option() {
-        Some(key) => Ok(key),
-        None => Err(Error::DatabaseError(format!(
-            "Key could not be converted into pallas::Base: {key:?}"
-        ))),
-    }
-}

+ 0 - 45
script/research/rlnd/rlnd/src/error.rs

@@ -1,45 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2026 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use darkfi::rpc::jsonrpc::{ErrorCode::ServerError, JsonError, JsonResult};
-
-/// Custom RPC errors available for rlnd.
-/// Please sort them sensefully.
-pub enum RpcError {
-    // Misc errors
-    PingFailed = -32300,
-}
-
-fn to_tuple(e: RpcError) -> (i32, String) {
-    let msg = match e {
-        // Misc errors
-        RpcError::PingFailed => "Darkirc daemon ping error",
-    };
-
-    (e as i32, msg.to_string())
-}
-
-pub fn server_error(e: RpcError, id: u16, msg: Option<&str>) -> JsonResult {
-    let (code, default_msg) = to_tuple(e);
-
-    if let Some(message) = msg {
-        return JsonError::new(ServerError(code), Some(message.to_string()), id).into()
-    }
-
-    JsonError::new(ServerError(code), Some(default_msg), id).into()
-}

+ 0 - 187
script/research/rlnd/rlnd/src/lib.rs

@@ -1,187 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2026 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::{collections::HashSet, sync::Arc};
-
-use smol::lock::Mutex;
-use tracing::{error, info};
-use url::Url;
-
-use darkfi::{
-    rpc::{
-        server::{listen_and_serve, RequestHandler},
-        settings::RpcSettings,
-    },
-    system::{ExecutorPtr, StoppableTask, StoppableTaskPtr},
-    Error, Result,
-};
-
-pub mod error;
-
-/// DarkFi RLN state management database
-pub mod database;
-use database::RlndDatabase;
-
-/// rlnd JSON-RPC related methods
-pub mod rpc;
-use rpc::{DarkircRpcClient, PrivateRpcHandler, PublicRpcHandler};
-
-/// Atomic pointer to the DarkFi RLN state management node
-pub type RlnNodePtr = Arc<RlnNode>;
-
-/// Structure representing a DarkFi RLN state management node
-pub struct RlnNode {
-    /// Main pointer to the sled db connection
-    database: RlndDatabase,
-    /// Private JSON-RPC connection tracker
-    private_rpc_connections: Mutex<HashSet<StoppableTaskPtr>>,
-    /// Publicly exposed JSON-RPC connection tracker
-    public_rpc_connections: Mutex<HashSet<StoppableTaskPtr>>,
-    /// JSON-RPC client to execute requests to the darkirc daemon
-    rpc_client: Mutex<DarkircRpcClient>,
-}
-
-impl RlnNode {
-    pub async fn new(database: RlndDatabase, rpc_client: Mutex<DarkircRpcClient>) -> RlnNodePtr {
-        Arc::new(Self {
-            database,
-            private_rpc_connections: Mutex::new(HashSet::new()),
-            public_rpc_connections: Mutex::new(HashSet::new()),
-            rpc_client,
-        })
-    }
-}
-
-/// Atomic pointer to the DarkFi RLN state management daemon
-pub type RlndPtr = Arc<Rlnd>;
-
-/// Structure representing a DarkFi RLN state management daemon
-pub struct Rlnd {
-    /// Darkfi RLN state management node instance
-    node: RlnNodePtr,
-    /// Private JSON-RPC background task
-    private_rpc_task: StoppableTaskPtr,
-    /// Publicly exposed JSON-RPC background task
-    public_rpc_task: StoppableTaskPtr,
-}
-
-impl Rlnd {
-    /// Initialize a DarkFi RLN state management daemon.
-    ///
-    /// Generates a new `RlnNode` for provided configuration,
-    /// along with all the corresponding background tasks.
-    pub async fn init(db_path: &str, endpoint: &Url, ex: &ExecutorPtr) -> Result<RlndPtr> {
-        info!(target: "rlnd::Rlnd::init", "Initializing a Darkfi RLN state management daemon...");
-
-        // Initialize database
-        let database = RlndDatabase::new(db_path)?;
-
-        // Initialize JSON-RPC client to perform requests to darkirc
-        let Ok(rpc_client) = DarkircRpcClient::new(endpoint.clone(), ex.clone()).await else {
-            error!(target: "rlnd::Rlnd::init", "Failed to initialize darkirc daemon rpc client, check if darkirc is running");
-            return Err(Error::RpcClientStopped)
-        };
-        let rpc_client = Mutex::new(rpc_client);
-
-        // Initialize node
-        let node = RlnNode::new(database, rpc_client).await;
-
-        // Generate the background tasks
-        let private_rpc_task = StoppableTask::new();
-        let public_rpc_task = StoppableTask::new();
-
-        info!(target: "rlnd::Rlnd::init", "Darkfi RLN state management daemon initialized successfully!");
-
-        Ok(Arc::new(Self { node, private_rpc_task, public_rpc_task }))
-    }
-
-    /// Start the DarkFi RLN state management daemon in the given executor, using the provided
-    /// JSON-RPC configurations.
-    pub async fn start(
-        &self,
-        executor: &ExecutorPtr,
-        private_rpc_settings: &RpcSettings,
-        public_rpc_settings: &RpcSettings,
-    ) -> Result<()> {
-        info!(target: "rlnd::Rlnd::start", "Starting Darkfi RLN state management daemon...");
-
-        // Pinging darkirc daemon to verify it listens
-        if let Err(e) = self.node.ping_darkirc_daemon().await {
-            error!(target: "rlnd::Rlnd::start", "Failed to ping darkirc daemon: {}", e);
-            return Err(Error::RpcClientStopped)
-        }
-
-        // Start the private JSON-RPC task
-        info!(target: "rlnd::Rlnd::start", "Starting private JSON-RPC server");
-        let node_ = self.node.clone();
-        self.private_rpc_task.clone().start(
-            listen_and_serve::<PrivateRpcHandler>(private_rpc_settings.clone(), self.node.clone(), None, executor.clone()),
-            |res| async move {
-                match res {
-                    Ok(()) | Err(Error::RpcServerStopped) => <RlnNode as RequestHandler<PrivateRpcHandler>>::stop_connections(&node_).await,
-                    Err(e) => error!(target: "rlnd::Rlnd::start", "Failed starting private JSON-RPC server: {}", e),
-                }
-            },
-            Error::RpcServerStopped,
-            executor.clone(),
-        );
-
-        // Start the publicly exposed JSON-RPC task
-        info!(target: "rlnd::Rlnd::start", "Starting publicly exposed JSON-RPC server");
-        let node_ = self.node.clone();
-        self.public_rpc_task.clone().start(
-            listen_and_serve::<PublicRpcHandler>(public_rpc_settings.clone(), self.node.clone(), None, executor.clone()),
-            |res| async move {
-                match res {
-                    Ok(()) | Err(Error::RpcServerStopped) => <RlnNode as RequestHandler<PublicRpcHandler>>::stop_connections(&node_).await,
-                    Err(e) => error!(target: "rlnd::Rlnd::start", "Failed starting publicly exposed JSON-RPC server: {}", e),
-                }
-            },
-            Error::RpcServerStopped,
-            executor.clone(),
-        );
-
-        info!(target: "rlnd::Rlnd::start", "Darkfi RLN state management daemon started successfully!");
-        Ok(())
-    }
-
-    /// Stop the DarkFi RLN state management daemon.
-    pub async fn stop(&self) -> Result<()> {
-        info!(target: "rlnd::Rlnd::stop", "Terminating Darkfi RLN state management daemon...");
-
-        // Stop the JSON-RPC task
-        info!(target: "rlnd::Rlnd::stop", "Stopping private JSON-RPC server...");
-        self.private_rpc_task.stop().await;
-
-        // Stop the JSON-RPC task
-        info!(target: "rlnd::Rlnd::stop", "Stopping publicly exposed JSON-RPC server...");
-        self.public_rpc_task.stop().await;
-
-        // Flush sled database data
-        info!(target: "rlnd::Rlnd::stop", "Flushing sled database...");
-        let flushed_bytes = self.node.database.sled_db.flush_async().await?;
-        info!(target: "rlnd::Rlnd::stop", "Flushed {} bytes", flushed_bytes);
-
-        // Close the JSON-RPC client, if it was initialized
-        info!(target: "rlnd::Rlnd::stop", "Stopping JSON-RPC client...");
-        self.node.rpc_client.lock().await.stop().await;
-
-        info!(target: "rlnd::Rlnd::stop", "Darkfi RLN state management daemon terminated successfully!");
-        Ok(())
-    }
-}

+ 0 - 103
script/research/rlnd/rlnd/src/main.rs

@@ -1,103 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2026 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::sync::Arc;
-
-use async_std::prelude::StreamExt;
-use structopt_toml::{serde::Deserialize, structopt::StructOpt, StructOptToml};
-use tracing::info;
-use url::Url;
-
-use darkfi::{async_daemonize, cli_desc, rpc::settings::RpcSettingsOpt, Error, Result};
-
-use rlnd::Rlnd;
-
-const CONFIG_FILE: &str = "rlnd_config.toml";
-const CONFIG_FILE_CONTENTS: &str = include_str!("../rlnd_config.toml");
-
-#[derive(Clone, Debug, Deserialize, StructOpt, StructOptToml)]
-#[serde(default)]
-#[structopt(name = "rlnd", about = cli_desc!())]
-struct Args {
-    #[structopt(short, long)]
-    /// Configuration file to use
-    config: Option<String>,
-
-    #[structopt(long, default_value = "~/.local/share/darkfi/rlnd")]
-    /// Path to the database directory
-    database: String,
-
-    /// Private RPC server listen address
-    #[structopt(long, default_value = "tcp://127.0.0.1:22222")]
-    pub private_rpc_listen: Url,
-
-    /// Private RPC Disabled JSON-RPC methods
-    #[structopt(long, use_delimiter = true)]
-    pub private_rpc_disabled_methods: Option<Vec<String>>,
-
-    /// Public RPC server listen address
-    #[structopt(long, default_value = "tcp://127.0.0.1:22223")]
-    pub public_rpc_listen: Url,
-
-    /// Public RPC Disabled JSON-RPC methods
-    #[structopt(long, use_delimiter = true)]
-    pub public_rpc_disabled_methods: Option<Vec<String>>,
-
-    #[structopt(short, long, default_value = "tcp://127.0.0.1:26660")]
-    /// darkirc JSON-RPC endpoint
-    endpoint: Url,
-
-    #[structopt(short, long)]
-    /// Set log file to ouput into
-    log: Option<String>,
-
-    #[structopt(short, parse(from_occurrences))]
-    /// Increase verbosity (-vvv supported)
-    verbose: u8,
-}
-
-async_daemonize!(realmain);
-async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
-    info!(target: "rlnd", "Initializing DarkFi RLN state management node...");
-
-    // Generate the daemon
-    let daemon = Rlnd::init(&args.database, &args.endpoint, &ex).await?;
-
-    let private_rpc = RpcSettingsOpt {
-        rpc_listen: args.private_rpc_listen.clone(),
-        rpc_disabled_methods: args.private_rpc_disabled_methods.clone(),
-    };
-    let public_rpc = RpcSettingsOpt {
-        rpc_listen: args.public_rpc_listen.clone(),
-        rpc_disabled_methods: args.public_rpc_disabled_methods.clone(),
-    };
-
-    // Start the daemon
-    daemon.start(&ex, &private_rpc.into(), &public_rpc.into()).await?;
-
-    // Signal handling for graceful termination.
-    let (signals_handler, signals_task) = SignalHandler::new(ex)?;
-    signals_handler.wait_termination(signals_task).await?;
-    info!(target: "rlnd", "Caught termination signal, cleaning up and exiting...");
-
-    daemon.stop().await?;
-
-    info!(target: "rlnd", "Shut down successfully");
-
-    Ok(())
-}

+ 0 - 346
script/research/rlnd/rlnd/src/rpc.rs

@@ -1,346 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2026 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::{collections::HashSet, time::Instant};
-
-use async_trait::async_trait;
-use darkfi::{
-    rpc::{
-        client::RpcClient,
-        jsonrpc::{ErrorCode, JsonError, JsonRequest, JsonResponse, JsonResult},
-        server::RequestHandler,
-    },
-    system::{sleep, ExecutorPtr, StoppableTaskPtr},
-    Error, Result,
-};
-use darkfi_sdk::{crypto::pasta_prelude::PrimeField, pasta::pallas};
-use darkfi_serial::serialize;
-use smol::lock::MutexGuard;
-use tinyjson::JsonValue;
-use tracing::{debug, error, info};
-use url::Url;
-
-use crate::{
-    error::{server_error, RpcError},
-    RlnNode,
-};
-
-/// Private JSON-RPC `RequestHandler` type
-pub struct PrivateRpcHandler;
-/// Publicly exposed JSON-RPC `RequestHandler` type
-pub struct PublicRpcHandler;
-
-/// Structure to hold a JSON-RPC client and its config,
-/// so we can recreate it in case of an error.
-pub struct DarkircRpcClient {
-    endpoint: Url,
-    ex: ExecutorPtr,
-    client: RpcClient,
-}
-
-impl DarkircRpcClient {
-    pub async fn new(endpoint: Url, ex: ExecutorPtr) -> Result<Self> {
-        let client = RpcClient::new(endpoint.clone(), ex.clone()).await?;
-        Ok(Self { endpoint, ex, client })
-    }
-
-    /// Stop the client.
-    pub async fn stop(&self) {
-        self.client.stop().await
-    }
-}
-
-#[async_trait]
-impl RequestHandler<PrivateRpcHandler> for RlnNode {
-    async fn handle_request(&self, req: JsonRequest) -> JsonResult {
-        debug!(target: "rlnd::private_rpc", "--> {}", req.stringify().unwrap());
-
-        match req.method.as_str() {
-            // =====================
-            // Miscellaneous methods
-            // =====================
-            "ping" => {
-                <RlnNode as RequestHandler<PrivateRpcHandler>>::pong(self, req.id, req.params).await
-            }
-            "ping_darkirc" => self.ping_darkirc(req.id, req.params).await,
-
-            // ================
-            // Database methods
-            // ================
-            "add_membership" => self.add_membership(req.id, req.params).await,
-            "get_memberships" => self.get_memberships(req.id, req.params).await,
-            "slash_membership" => self.slash_membership(req.id, req.params).await,
-
-            // ==============
-            // Invalid method
-            // ==============
-            _ => JsonError::new(ErrorCode::MethodNotFound, None, req.id).into(),
-        }
-    }
-
-    async fn connections_mut(&self) -> MutexGuard<'life0, HashSet<StoppableTaskPtr>> {
-        self.private_rpc_connections.lock().await
-    }
-}
-
-#[async_trait]
-impl RequestHandler<PublicRpcHandler> for RlnNode {
-    async fn handle_request(&self, req: JsonRequest) -> JsonResult {
-        debug!(target: "rlnd::public_rpc", "--> {}", req.stringify().unwrap());
-
-        match req.method.as_str() {
-            // =====================
-            // Miscellaneous methods
-            // =====================
-            "ping" => {
-                <RlnNode as RequestHandler<PublicRpcHandler>>::pong(self, req.id, req.params).await
-            }
-
-            // ================
-            // Database methods
-            // ================
-            "slash_membership" => self.slash_membership(req.id, req.params).await,
-
-            // ==============
-            // Invalid method
-            // ==============
-            _ => JsonError::new(ErrorCode::MethodNotFound, None, req.id).into(),
-        }
-    }
-
-    async fn connections_mut(&self) -> MutexGuard<'life0, HashSet<StoppableTaskPtr>> {
-        self.public_rpc_connections.lock().await
-    }
-}
-
-impl RlnNode {
-    // RPCAPI:
-    // Pings configured darkirc daemon for liveness.
-    // Returns `true` on success.
-    //
-    // --> {"jsonrpc": "2.0", "method": "ping_darkirc", "params": [], "id": 1}
-    // <-- {"jsonrpc": "2.0", "result": "true", "id": 1}
-    async fn ping_darkirc(&self, id: u16, _params: JsonValue) -> JsonResult {
-        if let Err(e) = self.ping_darkirc_daemon().await {
-            error!(target: "rlnd::rpc::ping_darkirc", "Failed to ping darkirc daemon: {}", e);
-            return server_error(RpcError::PingFailed, id, None)
-        }
-        JsonResponse::new(JsonValue::Boolean(true), id).into()
-    }
-
-    /// Ping configured darkirc daemon JSON-RPC endpoint.
-    pub async fn ping_darkirc_daemon(&self) -> Result<()> {
-        debug!(target: "rlnd::ping_darkirc_daemon", "Pinging darkirc daemon...");
-        self.darkirc_daemon_request("ping", &JsonValue::Array(vec![])).await?;
-        Ok(())
-    }
-
-    /// Auxiliary function to execute a request towards the configured darkirc daemon JSON-RPC endpoint.
-    pub async fn darkirc_daemon_request(
-        &self,
-        method: &str,
-        params: &JsonValue,
-    ) -> Result<JsonValue> {
-        debug!(target: "rlnd::rpc::darkirc_daemon_request", "Executing request {} with params: {:?}", method, params);
-        let latency = Instant::now();
-        let req = JsonRequest::new(method, params.clone());
-        let lock = self.rpc_client.lock().await;
-        let rep = lock.client.request(req).await?;
-        drop(lock);
-        let latency = latency.elapsed();
-        debug!(target: "rlnd::rpc::darkirc_daemon_request", "Got reply: {:?}", rep);
-        debug!(target: "rlnd::rpc::darkirc_daemon_request", "Latency: {:?}", latency);
-        Ok(rep)
-    }
-
-    /// Auxiliary function to execute a request towards the configured darkirc daemon JSON-RPC endpoint,
-    /// but in case of failure, sleep and retry until connection is re-established.
-    pub async fn darkirc_daemon_request_with_retry(
-        &self,
-        method: &str,
-        params: &JsonValue,
-    ) -> JsonValue {
-        loop {
-            // Try to execute the request using current client
-            match self.darkirc_daemon_request(method, params).await {
-                Ok(v) => return v,
-                Err(e) => {
-                    error!(target: "rlnd::rpc::darkirc_daemon_request_with_retry", "Failed to execute darkirc daemon request: {}", e);
-                }
-            }
-            loop {
-                // Sleep a bit before retrying
-                info!(target: "rlnd::rpc::darkirc_daemon_request_with_retry", "Sleeping so we can retry later");
-                sleep(10).await;
-                // Create a new client
-                let mut rpc_client = self.rpc_client.lock().await;
-                let Ok(client) =
-                    RpcClient::new(rpc_client.endpoint.clone(), rpc_client.ex.clone()).await
-                else {
-                    error!(target: "rlnd::rpc::darkirc_daemon_request_with_retry", "Failed to initialize darkirc daemon rpc client, check if darkirc is running");
-                    drop(rpc_client);
-                    continue
-                };
-                info!(target: "rlnd::rpc::darkirc_daemon_request_with_retry", "Connection re-established!");
-                // Set the new client as the daemon one
-                rpc_client.client = client;
-                break;
-            }
-        }
-    }
-
-    // RPCAPI:
-    // Generate a new membership for given identity and stake.
-    // Returns a readable membership upon success.
-    //
-    // **Params:**
-    // * `array[0]`: base58-encoded `pallas::Base` string
-    // * `array[1]`: `u64` Membership stake (as string)
-    //
-    // **Returns:**
-    // * `String`: `Membership` struct serialized into base58.
-    //
-    // --> {"jsonrpc": "2.0", "method": "add_membership", "params": ["3px89oUYY7nzA43vNCBkbvJbsQjNeuH5XRxJ9C2oGnmV", "42"], "id": 1}
-    // <-- {"jsonrpc": "2.0", "result": {...}, "id": 1}
-    async fn add_membership(&self, id: u16, params: JsonValue) -> JsonResult {
-        let params = params.get::<Vec<JsonValue>>().unwrap();
-        if params.len() != 2 || !params[0].is_string() || !params[1].is_string() {
-            return JsonError::new(ErrorCode::InvalidParams, None, id).into()
-        }
-
-        let membership_id = match parse_pallas_base(params[0].get::<String>().unwrap()) {
-            Ok(v) => v,
-            Err(e) => {
-                error!(target: "rlnd::rpc::add_membership", "Error parsing membership id: {e}");
-                return JsonError::new(ErrorCode::InvalidParams, None, id).into()
-            }
-        };
-
-        let stake = match params[1].get::<String>().unwrap().parse::<u64>() {
-            Ok(v) => v,
-            Err(_) => return JsonError::new(ErrorCode::ParseError, None, id).into(),
-        };
-
-        let membership = match self.database.add_membership(membership_id, stake) {
-            Ok(v) => v,
-            Err(e) => {
-                error!(target: "rlnd::rpc::add_membership", "Failed generating membership: {e}");
-                return JsonError::new(ErrorCode::InternalError, None, id).into()
-            }
-        };
-
-        let membership = bs58::encode(&serialize(&membership)).into_string();
-        JsonResponse::new(JsonValue::String(membership), id).into()
-    }
-
-    // RPCAPI:
-    // Returns all database memberships upon success.
-    //
-    // **Params:**
-    // * `None`
-    //
-    // **Returns:**
-    // * `array[N]`: Pairs of `pallas::Base` and `Membership` serialized into base58
-    //
-    // --> {"jsonrpc": "2.0", "method": "get_memberships", "params": [], "id": 1}
-    // <-- {"jsonrpc": "2.0", "result": {...}, "id": 1}
-    async fn get_memberships(&self, id: u16, params: JsonValue) -> JsonResult {
-        let params = params.get::<Vec<JsonValue>>().unwrap();
-        if !params.is_empty() {
-            return JsonError::new(ErrorCode::InvalidParams, None, id).into()
-        }
-
-        let memberships = match self.database.get_all() {
-            Ok(v) => v,
-            Err(e) => {
-                error!(target: "rlnd::rpc::get_memberships", "Error retrieving memberships: {e}");
-                return JsonError::new(ErrorCode::InvalidParams, None, id).into()
-            }
-        };
-
-        let mut ret = vec![];
-        for (id, membership) in memberships {
-            ret.push(JsonValue::String(bs58::encode(&id.to_repr()).into_string()));
-            ret.push(JsonValue::String(bs58::encode(&serialize(&membership)).into_string()));
-        }
-
-        JsonResponse::new(JsonValue::Array(ret), id).into()
-    }
-
-    // RPCAPI:
-    // Slash the membership of given identity.
-    // Returns the membership information upon success.
-    //
-    // **Params:**
-    // * `array[0]`: base58-encoded `pallas::Base` string
-    //
-    // **Returns:**
-    // * `String`: `Membership` struct serialized into base58.
-    //
-    // --> {"jsonrpc": "2.0", "method": "slash_membership", "params": ["3px89oUYY7nzA43vNCBkbvJbsQjNeuH5XRxJ9C2oGnmV"], "id": 1}
-    // <-- {"jsonrpc": "2.0", "result": {...}, "id": 1}
-    async fn slash_membership(&self, id: u16, params: JsonValue) -> JsonResult {
-        let params = params.get::<Vec<JsonValue>>().unwrap();
-        if params.len() != 1 || !params[0].is_string() {
-            return JsonError::new(ErrorCode::InvalidParams, None, id).into()
-        }
-
-        let membership_id = match parse_pallas_base(params[0].get::<String>().unwrap()) {
-            Ok(v) => v,
-            Err(e) => {
-                error!(target: "rlnd::rpc::slash_membership", "Error parsing membership id: {e}");
-                return JsonError::new(ErrorCode::InvalidParams, None, id).into()
-            }
-        };
-
-        let membership = match self.database.remove_membership_by_id(&membership_id) {
-            Ok(v) => v,
-            Err(e) => {
-                error!(target: "rlnd::rpc::slash_membership", "Failed removing membership: {e}");
-                return JsonError::new(ErrorCode::InternalError, None, id).into()
-            }
-        };
-
-        let membership = bs58::encode(&serialize(&membership)).into_string();
-        JsonResponse::new(JsonValue::String(membership), id).into()
-    }
-}
-
-/// Auxiliary function to parse a `pallas::Base` membership id from a `JsonValue::String`.
-pub fn parse_pallas_base(id: &str) -> Result<pallas::Base> {
-    let Ok(decoded_bytes) = bs58::decode(id).into_vec() else {
-        error!(target: "rlnd::rpc::parse_pallas_base", "Error decoding string: {id}");
-        return Err(Error::ParseFailed("Invalid pallas::Base"))
-    };
-
-    let bytes: [u8; 32] = match decoded_bytes.try_into() {
-        Ok(b) => b,
-        Err(e) => {
-            error!(target: "rlnd::rpc::parse_pallas_base", "Error decoding string bytes: {e:?}");
-            return Err(Error::ParseFailed("Invalid pallas::Base"))
-        }
-    };
-
-    match pallas::Base::from_repr(bytes).into() {
-        Some(id) => Ok(id),
-        None => {
-            error!(target: "rlnd::rpc::parse_pallas_base", "Error converting bytes to pallas::Base");
-            Err(Error::ParseFailed("Invalid pallas::Base"))
-        }
-    }
-}