mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-09 14:48:08 -05:00
merge crypsinous into master in crypsinousintomaster branch
This commit is contained in:
29
example/dchat/Cargo.toml
Normal file
29
example/dchat/Cargo.toml
Normal file
@@ -0,0 +1,29 @@
|
||||
[package]
|
||||
name = "dchat"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
description = "Demo chat to document darkfi net code"
|
||||
|
||||
[dependencies]
|
||||
darkfi = {path = "../../", features = ["net", "rpc"]}
|
||||
|
||||
# Async
|
||||
async-std = "1.12.0"
|
||||
async-trait = "0.1.57"
|
||||
async-executor = "1.4.1"
|
||||
async-channel = "1.7.1"
|
||||
easy-parallel = "3.2.0"
|
||||
smol = "1.2.5"
|
||||
num_cpus = "1.13.1"
|
||||
|
||||
# Misc
|
||||
log = "0.4.17"
|
||||
simplelog = "0.12.0"
|
||||
url = "2.2.2"
|
||||
|
||||
# Encoding and parsing
|
||||
serde_json = "1.0.85"
|
||||
serde = {version = "1.0.144", features = ["derive"]}
|
||||
toml = "0.5.9"
|
||||
|
||||
|
||||
45
example/dchat/README.md
Normal file
45
example/dchat/README.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Dchat
|
||||
|
||||
A demo chat program to document DarkFi net
|
||||
code. Tutorial can be found in the [DarkFi
|
||||
book](https://darkrenaissance.github.io/darkfi/learn/writing-a-p2p-app.html).
|
||||
|
||||
## Usage
|
||||
|
||||
Spin up a seed node:
|
||||
|
||||
```shell
|
||||
cd example/dchat-seed
|
||||
cargo run
|
||||
```
|
||||
|
||||
Run dchat as an inbound node:
|
||||
|
||||
```shell
|
||||
cargo run a
|
||||
```
|
||||
|
||||
Run dchat as an outbound node:
|
||||
|
||||
```shell
|
||||
cargo run b
|
||||
```
|
||||
|
||||
## Logging
|
||||
|
||||
Dchat creates a logging file for the inbound node at /tmp/alice.log.
|
||||
Logging for the outbound node is found at /tmp/bob.log.
|
||||
|
||||
Tail them like so:
|
||||
|
||||
```shell
|
||||
tail -f /tmp/alice.log
|
||||
```
|
||||
|
||||
Or use multitail for colored output:
|
||||
|
||||
```shell
|
||||
multitail -c /tmp/alice.log
|
||||
```
|
||||
|
||||
|
||||
28
example/dchat/dchat_config.toml
Normal file
28
example/dchat/dchat_config.toml
Normal file
@@ -0,0 +1,28 @@
|
||||
# chat toml
|
||||
|
||||
[net]
|
||||
## P2P accept addresses
|
||||
#inbound=["tls://127.0.0.1:11002"]
|
||||
|
||||
## Connection slots
|
||||
outbound_connections=5
|
||||
|
||||
## P2P external addresses
|
||||
#external_addr=["tls://127.0.0.1:11002"]
|
||||
|
||||
## Peers to connect to
|
||||
#peers=["tls://127.0.0.1:11003"]
|
||||
|
||||
## Seed nodes to connect to
|
||||
#seeds=["tls://irc0.dark.fi:11001", "tls://irc1.dark.fi:11001"]
|
||||
seeds=["tcp://127.0.0.1:55555"]
|
||||
|
||||
## Only used for debugging. Compromises privacy when set.
|
||||
#node_id = "foo"
|
||||
|
||||
## these are the default configuration for the p2p network
|
||||
#manual_attempt_limit=0
|
||||
#seed_query_timeout_seconds=8
|
||||
#connect_timeout_seconds=10
|
||||
#channel_handshake_seconds=4
|
||||
#channel_heartbeat_seconds=10
|
||||
12
example/dchat/src/dchat_error.rs
Normal file
12
example/dchat/src/dchat_error.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
use std::{error, fmt};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ErrorMissingSpecifier;
|
||||
|
||||
impl fmt::Display for ErrorMissingSpecifier {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "missing node specifier. you must specify either a or b")
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for ErrorMissingSpecifier {}
|
||||
19
example/dchat/src/dchatmsg.rs
Normal file
19
example/dchat/src/dchatmsg.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
use async_std::sync::{Arc, Mutex};
|
||||
|
||||
use darkfi::{
|
||||
net,
|
||||
util::serial::{SerialDecodable, SerialEncodable},
|
||||
};
|
||||
|
||||
pub type DchatMsgsBuffer = Arc<Mutex<Vec<DchatMsg>>>;
|
||||
|
||||
impl net::Message for DchatMsg {
|
||||
fn name() -> &'static str {
|
||||
"DchatMsg"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
|
||||
pub struct DchatMsg {
|
||||
pub msg: String,
|
||||
}
|
||||
224
example/dchat/src/main.rs
Normal file
224
example/dchat/src/main.rs
Normal file
@@ -0,0 +1,224 @@
|
||||
use async_executor::Executor;
|
||||
use async_std::sync::{Arc, Mutex};
|
||||
use easy_parallel::Parallel;
|
||||
|
||||
use std::{error, fs::File, io::stdin};
|
||||
|
||||
use log::debug;
|
||||
use simplelog::WriteLogger;
|
||||
use url::Url;
|
||||
|
||||
use darkfi::{net, net::Settings, rpc::server::listen_and_serve};
|
||||
|
||||
use crate::{
|
||||
dchat_error::ErrorMissingSpecifier,
|
||||
dchatmsg::{DchatMsg, DchatMsgsBuffer},
|
||||
protocol_dchat::ProtocolDchat,
|
||||
rpc::JsonRpcInterface,
|
||||
};
|
||||
|
||||
pub mod dchat_error;
|
||||
pub mod dchatmsg;
|
||||
pub mod protocol_dchat;
|
||||
pub mod rpc;
|
||||
|
||||
pub type Error = Box<dyn error::Error>;
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
struct Dchat {
|
||||
p2p: net::P2pPtr,
|
||||
recv_msgs: DchatMsgsBuffer,
|
||||
}
|
||||
|
||||
impl Dchat {
|
||||
fn new(p2p: net::P2pPtr, recv_msgs: DchatMsgsBuffer) -> Self {
|
||||
Self { p2p, recv_msgs }
|
||||
}
|
||||
|
||||
async fn menu(&self) -> Result<()> {
|
||||
let mut buffer = String::new();
|
||||
let stdin = stdin();
|
||||
loop {
|
||||
println!(
|
||||
"Welcome to dchat.
|
||||
s: send message
|
||||
i: inbox
|
||||
q: quit "
|
||||
);
|
||||
stdin.read_line(&mut buffer)?;
|
||||
// Remove trailing \n
|
||||
buffer.pop();
|
||||
match buffer.as_str() {
|
||||
"q" => return Ok(()),
|
||||
"s" => {
|
||||
// Remove trailing s
|
||||
buffer.pop();
|
||||
stdin.read_line(&mut buffer)?;
|
||||
match self.send(buffer.clone()).await {
|
||||
Ok(_) => {
|
||||
println!("you sent: {}", buffer);
|
||||
}
|
||||
Err(e) => {
|
||||
println!("send failed for reason: {}", e);
|
||||
}
|
||||
}
|
||||
buffer.clear();
|
||||
}
|
||||
"i" => {
|
||||
let msgs = self.recv_msgs.lock().await;
|
||||
if msgs.is_empty() {
|
||||
println!("inbox is empty")
|
||||
} else {
|
||||
println!("received:");
|
||||
for i in msgs.iter() {
|
||||
if !i.msg.is_empty() {
|
||||
println!("{}", i.msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
buffer.clear();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn register_protocol(&self, msgs: DchatMsgsBuffer) -> Result<()> {
|
||||
debug!(target: "dchat", "Dchat::register_protocol() [START]");
|
||||
let registry = self.p2p.protocol_registry();
|
||||
registry
|
||||
.register(!net::SESSION_SEED, move |channel, _p2p| {
|
||||
let msgs2 = msgs.clone();
|
||||
async move { ProtocolDchat::init(channel, msgs2).await }
|
||||
})
|
||||
.await;
|
||||
debug!(target: "dchat", "Dchat::register_protocol() [STOP]");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn start(&mut self, ex: Arc<Executor<'_>>) -> Result<()> {
|
||||
debug!(target: "dchat", "Dchat::start() [START]");
|
||||
|
||||
let ex2 = ex.clone();
|
||||
|
||||
self.register_protocol(self.recv_msgs.clone()).await?;
|
||||
self.p2p.clone().start(ex.clone()).await?;
|
||||
ex2.spawn(self.p2p.clone().run(ex.clone())).detach();
|
||||
|
||||
self.menu().await?;
|
||||
|
||||
self.p2p.stop().await;
|
||||
|
||||
debug!(target: "dchat", "Dchat::start() [STOP]");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn send(&self, msg: String) -> Result<()> {
|
||||
let dchatmsg = DchatMsg { msg };
|
||||
self.p2p.broadcast(dchatmsg).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct AppSettings {
|
||||
accept_addr: Url,
|
||||
net: Settings,
|
||||
}
|
||||
|
||||
impl AppSettings {
|
||||
pub fn new(accept_addr: Url, net: Settings) -> Self {
|
||||
Self { accept_addr, net }
|
||||
}
|
||||
}
|
||||
|
||||
fn alice() -> Result<AppSettings> {
|
||||
let log_level = simplelog::LevelFilter::Debug;
|
||||
let log_config = simplelog::Config::default();
|
||||
|
||||
let log_path = "/tmp/alice.log";
|
||||
let file = File::create(log_path).unwrap();
|
||||
WriteLogger::init(log_level, log_config, file)?;
|
||||
|
||||
let seed = Url::parse("tcp://127.0.0.1:50515").unwrap();
|
||||
let inbound = Url::parse("tcp://127.0.0.1:51554").unwrap();
|
||||
let ext_addr = Url::parse("tcp://127.0.0.1:51554").unwrap();
|
||||
|
||||
let net = Settings {
|
||||
inbound: vec![inbound],
|
||||
external_addr: vec![ext_addr],
|
||||
seeds: vec![seed],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let accept_addr = Url::parse("tcp://127.0.0.1:55054").unwrap();
|
||||
let settings = AppSettings::new(accept_addr, net);
|
||||
|
||||
Ok(settings)
|
||||
}
|
||||
|
||||
fn bob() -> Result<AppSettings> {
|
||||
let log_level = simplelog::LevelFilter::Debug;
|
||||
let log_config = simplelog::Config::default();
|
||||
|
||||
let log_path = "/tmp/bob.log";
|
||||
let file = File::create(log_path).unwrap();
|
||||
WriteLogger::init(log_level, log_config, file)?;
|
||||
|
||||
let seed = Url::parse("tcp://127.0.0.1:50515").unwrap();
|
||||
|
||||
let net = Settings {
|
||||
inbound: vec![],
|
||||
outbound_connections: 5,
|
||||
seeds: vec![seed],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let accept_addr = Url::parse("tcp://127.0.0.1:51054").unwrap();
|
||||
let settings = AppSettings::new(accept_addr, net);
|
||||
|
||||
Ok(settings)
|
||||
}
|
||||
|
||||
#[async_std::main]
|
||||
async fn main() -> Result<()> {
|
||||
let settings: Result<AppSettings> = match std::env::args().nth(1) {
|
||||
Some(id) => match id.as_str() {
|
||||
"a" => alice(),
|
||||
"b" => bob(),
|
||||
_ => Err(ErrorMissingSpecifier.into()),
|
||||
},
|
||||
None => Err(ErrorMissingSpecifier.into()),
|
||||
};
|
||||
|
||||
let settings = settings?.clone();
|
||||
|
||||
let p2p = net::P2p::new(settings.net).await;
|
||||
|
||||
let nthreads = num_cpus::get();
|
||||
let (signal, shutdown) = async_channel::unbounded::<()>();
|
||||
|
||||
let ex = Arc::new(Executor::new());
|
||||
let ex2 = ex.clone();
|
||||
let ex3 = ex2.clone();
|
||||
|
||||
let msgs: DchatMsgsBuffer = Arc::new(Mutex::new(vec![DchatMsg { msg: String::new() }]));
|
||||
|
||||
let mut dchat = Dchat::new(p2p.clone(), msgs);
|
||||
|
||||
let accept_addr = settings.accept_addr.clone();
|
||||
let rpc = Arc::new(JsonRpcInterface { addr: accept_addr.clone(), p2p });
|
||||
ex.spawn(async move { listen_and_serve(accept_addr.clone(), rpc).await }).detach();
|
||||
|
||||
let (_, result) = Parallel::new()
|
||||
.each(0..nthreads, |_| smol::future::block_on(ex2.run(shutdown.recv())))
|
||||
.finish(|| {
|
||||
smol::future::block_on(async move {
|
||||
dchat.start(ex3).await?;
|
||||
drop(signal);
|
||||
Ok(())
|
||||
})
|
||||
});
|
||||
|
||||
result
|
||||
}
|
||||
55
example/dchat/src/protocol_dchat.rs
Normal file
55
example/dchat/src/protocol_dchat.rs
Normal file
@@ -0,0 +1,55 @@
|
||||
use async_executor::Executor;
|
||||
use async_std::sync::Arc;
|
||||
use async_trait::async_trait;
|
||||
use darkfi::{net, Result};
|
||||
use log::debug;
|
||||
|
||||
use crate::dchatmsg::{DchatMsg, DchatMsgsBuffer};
|
||||
|
||||
pub struct ProtocolDchat {
|
||||
jobsman: net::ProtocolJobsManagerPtr,
|
||||
msg_sub: net::MessageSubscription<DchatMsg>,
|
||||
msgs: DchatMsgsBuffer,
|
||||
}
|
||||
|
||||
impl ProtocolDchat {
|
||||
pub async fn init(channel: net::ChannelPtr, msgs: DchatMsgsBuffer) -> net::ProtocolBasePtr {
|
||||
debug!(target: "dchat", "ProtocolDchat::init() [START]");
|
||||
let message_subsytem = channel.get_message_subsystem();
|
||||
message_subsytem.add_dispatch::<DchatMsg>().await;
|
||||
|
||||
let msg_sub =
|
||||
channel.subscribe_msg::<DchatMsg>().await.expect("Missing DchatMsg dispatcher!");
|
||||
|
||||
Arc::new(Self {
|
||||
jobsman: net::ProtocolJobsManager::new("ProtocolDchat", channel.clone()),
|
||||
msg_sub,
|
||||
msgs,
|
||||
})
|
||||
}
|
||||
|
||||
async fn handle_receive_msg(self: Arc<Self>) -> Result<()> {
|
||||
debug!(target: "dchat", "ProtocolDchat::handle_receive_msg() [START]");
|
||||
while let Ok(msg) = self.msg_sub.receive().await {
|
||||
let msg = (*msg).to_owned();
|
||||
self.msgs.lock().await.push(msg);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl net::ProtocolBase for ProtocolDchat {
|
||||
async fn start(self: Arc<Self>, executor: Arc<Executor<'_>>) -> Result<()> {
|
||||
debug!(target: "dchat", "ProtocolDchat::ProtocolBase::start() [START]");
|
||||
self.jobsman.clone().start(executor.clone());
|
||||
self.jobsman.clone().spawn(self.clone().handle_receive_msg(), executor.clone()).await;
|
||||
debug!(target: "dchat", "ProtocolDchat::ProtocolBase::start() [STOP]");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
"ProtocolDchat"
|
||||
}
|
||||
}
|
||||
53
example/dchat/src/rpc.rs
Normal file
53
example/dchat/src/rpc.rs
Normal file
@@ -0,0 +1,53 @@
|
||||
use async_trait::async_trait;
|
||||
use log::debug;
|
||||
use serde_json::{json, Value};
|
||||
use url::Url;
|
||||
|
||||
use darkfi::{
|
||||
net,
|
||||
rpc::{
|
||||
jsonrpc::{ErrorCode, JsonError, JsonRequest, JsonResponse, JsonResult},
|
||||
server::RequestHandler,
|
||||
},
|
||||
};
|
||||
|
||||
pub struct JsonRpcInterface {
|
||||
pub addr: Url,
|
||||
pub p2p: net::P2pPtr,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl RequestHandler for JsonRpcInterface {
|
||||
async fn handle_request(&self, req: JsonRequest) -> JsonResult {
|
||||
if req.params.as_array().is_none() {
|
||||
return JsonError::new(ErrorCode::InvalidRequest, None, req.id).into()
|
||||
}
|
||||
|
||||
debug!(target: "RPC", "--> {}", serde_json::to_string(&req).unwrap());
|
||||
|
||||
match req.method.as_str() {
|
||||
Some("ping") => self.pong(req.id, req.params).await,
|
||||
Some("get_info") => self.get_info(req.id, req.params).await,
|
||||
Some(_) | None => JsonError::new(ErrorCode::MethodNotFound, None, req.id).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl JsonRpcInterface {
|
||||
// RPCAPI:
|
||||
// Replies to a ping method.
|
||||
// --> {"jsonrpc": "2.0", "method": "ping", "params": [], "id": 42}
|
||||
// <-- {"jsonrpc": "2.0", "result": "pong", "id": 42}
|
||||
async fn pong(&self, id: Value, _params: Value) -> JsonResult {
|
||||
JsonResponse::new(json!("pong"), id).into()
|
||||
}
|
||||
|
||||
// RPCAPI:
|
||||
// Retrieves P2P network information.
|
||||
// --> {"jsonrpc": "2.0", "method": "get_info", "params": [], "id": 42}
|
||||
// <-- {"jsonrpc": "2.0", result": {"nodeID": [], "nodeinfo": [], "id": 42}
|
||||
async fn get_info(&self, id: Value, _params: Value) -> JsonResult {
|
||||
let resp = self.p2p.get_info().await;
|
||||
JsonResponse::new(resp, id).into()
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@ use darkfi::{
|
||||
zk::circuit::lead_contract::LeadContract,
|
||||
};
|
||||
|
||||
|
||||
fn main() {
|
||||
let k: u32 = 13;
|
||||
//
|
||||
|
||||
@@ -48,9 +48,9 @@ impl ProgramOptions {
|
||||
let programcli = DarkCli::parse();
|
||||
|
||||
let accept_addr = if let Some(accept_addr) = programcli.accept {
|
||||
Some(accept_addr.parse()?)
|
||||
vec![accept_addr.parse()?]
|
||||
} else {
|
||||
None
|
||||
vec![]
|
||||
};
|
||||
|
||||
let mut seed_addrs: Vec<url::Url> = vec![];
|
||||
|
||||
@@ -12,10 +12,10 @@ edition = "2021"
|
||||
darkfi = {path = "../../", features = ["net", "rpc"]}
|
||||
# Async
|
||||
smol = "1.2.5"
|
||||
futures = "0.3.21"
|
||||
async-std = "1.11.0"
|
||||
async-trait = "0.1.53"
|
||||
async-channel = "1.6.1"
|
||||
futures = "0.3.24"
|
||||
async-std = "1.12.0"
|
||||
async-trait = "0.1.57"
|
||||
async-channel = "1.7.1"
|
||||
async-executor = "1.4.1"
|
||||
easy-parallel = "3.2.0"
|
||||
|
||||
@@ -23,11 +23,11 @@ easy-parallel = "3.2.0"
|
||||
rand = "0.8.5"
|
||||
|
||||
# Misc
|
||||
clap = {version = "3.1.18", features = ["derive"]}
|
||||
clap = {version = "3.2.20", features = ["derive"]}
|
||||
log = "0.4.17"
|
||||
simplelog = "0.12.0"
|
||||
fxhash = "0.2.1"
|
||||
url = "2.2.2"
|
||||
|
||||
# Encoding and parsing
|
||||
serde_json = "1.0.81"
|
||||
serde_json = "1.0.85"
|
||||
|
||||
2
example/serial_derive/.gitignore
vendored
Normal file
2
example/serial_derive/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
target/*
|
||||
Cargo.lock
|
||||
11
example/serial_derive/Cargo.toml
Normal file
11
example/serial_derive/Cargo.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "serial_derive"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
darkfi = {path = "../../", features = ["util"]}
|
||||
|
||||
[workspace]
|
||||
14
example/serial_derive/src/main.rs
Normal file
14
example/serial_derive/src/main.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
use darkfi::util::serial::{
|
||||
serialize, Decodable, Encodable, SerialDecodable, SerialEncodable, VarInt,
|
||||
};
|
||||
|
||||
#[derive(SerialEncodable)]
|
||||
enum Test {
|
||||
Type1(u32),
|
||||
Type2,
|
||||
Type3,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
@@ -5,7 +5,7 @@ use rand::rngs::OsRng;
|
||||
|
||||
use darkfi::{
|
||||
crypto::{
|
||||
constants::MERKLE_DEPTH_ORCHARD,
|
||||
constants::MERKLE_DEPTH,
|
||||
keypair::{Keypair, PublicKey, SecretKey},
|
||||
merkle_node::MerkleNode,
|
||||
note::{EncryptedNote, Note},
|
||||
@@ -22,8 +22,6 @@ use darkfi::{
|
||||
Result,
|
||||
};
|
||||
|
||||
const MERKLE_DEPTH: u8 = MERKLE_DEPTH_ORCHARD as u8;
|
||||
|
||||
/// The state machine, held in memory.
|
||||
struct MemoryState {
|
||||
/// The entire Merkle tree state
|
||||
@@ -172,7 +170,7 @@ fn main() -> Result<()> {
|
||||
|
||||
// Now spend
|
||||
let owncoin = &state.own_coins[0];
|
||||
let note = owncoin.note;
|
||||
let note = &owncoin.note;
|
||||
let leaf_position = owncoin.leaf_position;
|
||||
let root = state.tree.root(0).unwrap();
|
||||
let merkle_path = state.tree.authentication_path(leaf_position, &root).unwrap();
|
||||
@@ -183,7 +181,7 @@ fn main() -> Result<()> {
|
||||
leaf_position,
|
||||
merkle_path,
|
||||
secret: keypair.secret,
|
||||
note,
|
||||
note: note.clone(),
|
||||
}],
|
||||
outputs: vec![TransactionBuilderOutputInfo {
|
||||
value: 110,
|
||||
|
||||
Reference in New Issue
Block a user