Skip to content

Commit

Permalink
adding StampNet first revision!! allows starting a public node, publi…
Browse files Browse the repository at this point in the history
…shing an identity, and retrieving an identity from a p2p DHT. working great. also allows setting default StampNet nodes in config, in case you are a sociopath and want to run your own stamp network and not use mine =[. also moving towards setting up `stamp id import` to work with http URLs (ie stamp id import https://andrew.com/id.stamp) and also stamp://s0f-4x9aadf89d URLs which will basically just wrap `stamp net get`. really coming together
  • Loading branch information
orthecreedence committed Apr 20, 2024
1 parent 2488dab commit 0ea3abf
Show file tree
Hide file tree
Showing 9 changed files with 2,325 additions and 107 deletions.
2,077 changes: 1,993 additions & 84 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "stamp-cli"
version = "0.1.3"
version = "0.1.4"
authors = ["Andrew Danger Lyon <[email protected]>"]
edition = "2018"

Expand All @@ -21,6 +21,7 @@ serde_derive = "1.0"
sharks = "0.4"
stamp-aux = { path = "../aux" }
stamp-core = { path = "../core" }
stamp-net = { path = "../net" }
textwrap = { version = "0.13", features = ["terminal_size"] }
tokio = { version = "1.34", features = ["io-std", "rt"] }
tracing = { version = "0.1", features = ["log"] }
Expand Down
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

# non-versioned include
VARS ?= vars.mk
FMT ?= 1
-include $(VARS)

override CARGO_BUILD_ARGS += --features "$(FEATURES)" --color=always
Expand All @@ -15,7 +16,7 @@ build: fmt
cargo build $(CARGO_BUILD_ARGS)

fmt:
cargo fmt
if [ "$(FMT)" == "1" ]; then cargo fmt; fi

release: override CARGO_BUILD_ARGS += --release
release: build
Expand Down
12 changes: 12 additions & 0 deletions src/commands/config.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use crate::{commands, config, db, util};
use anyhow::{anyhow, Result};
use stamp_aux::config::NetConfig;
use stamp_net::Multiaddr;
use std::convert::TryFrom;

pub fn set_default(search: &str) -> Result<()> {
Expand All @@ -19,3 +21,13 @@ pub fn set_default(search: &str) -> Result<()> {
conf.default_identity = Some(id_str);
config::save(&conf)
}

pub fn set_stampnet_servers(servers: Vec<Multiaddr>) -> Result<()> {
let mut conf = config::load()?;
println!(
"Setting StampNet join list to [ {} ]",
servers.iter().map(|s| format!("{}", s)).collect::<Vec<_>>().join(", ")
);
conf.net = Some(NetConfig::new(servers));
config::save(&conf)
}
17 changes: 17 additions & 0 deletions src/commands/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use stamp_core::{
identity::{Identity, IdentityID},
util::{SerText, SerdeBinary, Timestamp},
};
use stamp_net::Multiaddr;
use std::convert::TryFrom;

pub(crate) enum FingerprintFormat {
Expand Down Expand Up @@ -85,6 +86,22 @@ pub(crate) fn create_vanity(
Ok((tmp_master_key, transactions, now))
}

pub fn import(location: &str, join: Vec<Multiaddr>) -> Result<()> {
let contents = util::load_file(location)?;
let (transactions, existing) =
stamp_aux::id::import_pre(contents.as_slice()).map_err(|e| anyhow!("Error importing identity: {}", e))?;
let identity = util::build_identity(&transactions)?;
if existing.is_some() {
if !util::yesno_prompt("The identity you're importing already exists locally. Overwrite? [y/N]", "n")? {
return Ok(());
}
}
let id_str = id_str!(identity.id())?;
db::save_identity(transactions)?;
println!("Imported identity {}", id_str);
Ok(())
}

pub fn publish(id: &str, stage: bool, sign_with: Option<&str>) -> Result<String> {
let hash_with = config::hash_algo(Some(&id));
let transactions = try_load_single_identity(id)?;
Expand Down
1 change: 1 addition & 0 deletions src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod debug;
pub mod id;
pub mod keychain;
pub mod message;
pub mod net;
pub mod sign;
pub mod stage;
pub mod stamp;
164 changes: 164 additions & 0 deletions src/commands/net.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
use crate::{commands::id::try_load_single_identity, config, db, util};
use anyhow::{anyhow, Result};
use stamp_aux::id::sign_with_optimal_key;
use stamp_core::{
dag::Transaction,
identity::IdentityID,
util::{base64_decode, SerText, SerdeBinary, Timestamp},
};
use stamp_net::{
agent::{self, random_peer_key, Agent, DHTMode, Event, Quorum, RelayMode},
Multiaddr,
};
use std::convert::TryFrom;
use std::sync::Arc;
use tokio::{
sync::{mpsc, oneshot, RwLock},
task,
};
use tracing::log::{trace, warn};

async fn event_sink(mut events: mpsc::Receiver<Event>, tx_ident: mpsc::Sender<()>, min_idents: usize) -> stamp_net::error::Result<()> {
let mut num_idents = 0;
loop {
match events.recv().await {
Some(Event::Quit) => break,
Some(Event::IdentifyRecv) => {
num_idents += 1;
if num_idents >= min_idents {
let _ = tx_ident.try_send(());
}
}
Some(ev) => trace!("event_sink: {:?}", ev),
_ => {}
}
}
Ok(())
}

pub fn get_stampnet_joinlist(join: Vec<Multiaddr>) -> Result<Vec<Multiaddr>> {
if join.len() > 0 {
return Ok(join);
}
let config = config::load()?;
let join_list = match config.net {
Some(net) => net.join_list.clone(),
None => {
vec![
"/dns/join01.stampid.net/tcp/5757".parse()?,
"/dns/join02.stampid.net/tcp/5757".parse()?,
]
}
};
Ok(join_list)
}

#[tokio::main(flavor = "current_thread")]
pub async fn publish(id: &str, publish_transaction_file: Option<&str>, join: Vec<Multiaddr>) -> Result<()> {
let hash_with = config::hash_algo(Some(&id));
let transactions = try_load_single_identity(id)?;
let identity = util::build_identity(&transactions)?;
let id_str = id_str!(identity.id())?;
let signed_publish_transaction = if let Some(publish_transaction_file) = publish_transaction_file {
let contents = util::load_file(publish_transaction_file)?;
Transaction::deserialize_binary(&contents).or_else(|_| Transaction::deserialize_binary(&base64_decode(&contents)?))?
} else {
let master_key =
util::passphrase_prompt(&format!("Your master passphrase for identity {}", IdentityID::short(&id_str)), identity.created())?;
let now = Timestamp::now();
let transaction = transactions
.publish(&hash_with, now)
.map_err(|e| anyhow!("Error creating publish transaction: {:?}", e))?;
sign_with_optimal_key(&identity, &master_key, transaction).map_err(|e| anyhow!("Error signing transaction: {:?}", e))?
};
signed_publish_transaction.clone().validate_publish_transaction()?;

let join = get_stampnet_joinlist(join)?;
let join_len = join.len();
let bind: Multiaddr = "/ip4/127.0.0.1/tcp/0".parse()?;
let peer_key = random_peer_key();
let peer_id = stamp_net::PeerId::from(peer_key.public());
let (agent, events) = Agent::new(peer_key, agent::memory_store(&peer_id), RelayMode::Client, DHTMode::Client).unwrap();
let agent = Arc::new(agent);
let mut task_set = task::JoinSet::new();
let (tx_ident, mut rx_ident) = mpsc::channel::<()>(1);
task_set.spawn(event_sink(events, tx_ident, join_len));
let agent2 = agent.clone();
task_set.spawn(async move { agent2.run(bind.clone(), join).await });
match rx_ident.recv().await {
Some(_) => {}
None => warn!("ident sender dropped"),
}
agent.dht_bootstrap().await?;
let quorum = std::num::NonZeroUsize::new(std::cmp::max(join_len, 1)).ok_or(anyhow!("bad non-zero usize"))?;
agent.publish_identity(signed_publish_transaction, Quorum::N(quorum)).await?;
agent.quit().await?;
while let Some(res) = task_set.join_next().await {
res??;
}
Ok(())
}

#[tokio::main(flavor = "current_thread")]
pub async fn get(id: &str, join: Vec<Multiaddr>) -> Result<()> {
let identity_id = IdentityID::try_from(id)?;
let join = get_stampnet_joinlist(join)?;
let join_len = join.len();
let bind: Multiaddr = "/ip4/127.0.0.1/tcp/0".parse()?;
let peer_key = random_peer_key();
let peer_id = stamp_net::PeerId::from(peer_key.public());
let (agent, events) = Agent::new(peer_key, agent::memory_store(&peer_id), RelayMode::Client, DHTMode::Client).unwrap();
let agent = Arc::new(agent);
let mut task_set = task::JoinSet::new();
let (tx_ident, mut rx_ident) = mpsc::channel::<()>(1);
task_set.spawn(event_sink(events, tx_ident, join_len));
let agent2 = agent.clone();
task_set.spawn(async move { agent2.run(bind.clone(), join).await });
match rx_ident.recv().await {
Some(_) => {}
None => warn!("ident sender dropped"),
}
agent.dht_bootstrap().await?;
let lookup_res = agent.lookup_identity(identity_id.clone()).await?;
agent.quit().await?;
while let Some(res) = task_set.join_next().await {
res??;
}

let publish_transaction = lookup_res.ok_or_else(|| anyhow!("Identity {} not found", identity_id))?;
let (transactions, identity) = publish_transaction.validate_publish_transaction()?;
let exists = db::load_identity(identity.id())?;
let identity = util::build_identity(&transactions)?;
if exists.is_some() {
if !util::yesno_prompt("The identity you're importing already exists locally. Overwrite? [y/N]", "n")? {
return Ok(());
}
}
db::save_identity(transactions)?;
println!("Imported identity {}", identity.id());
Ok(())
}

#[tokio::main(flavor = "current_thread")]
pub async fn node(bind: Multiaddr, join: Vec<Multiaddr>) -> Result<()> {
let join = get_stampnet_joinlist(join)?;
let peer_key = random_peer_key();
let peer_id = stamp_net::PeerId::from(peer_key.public());
let (agent, events) = Agent::new(peer_key, agent::memory_store(&peer_id), RelayMode::Server, DHTMode::Server).unwrap();
let agent = Arc::new(agent);
let mut task_set = task::JoinSet::new();
let (tx_ident, mut rx_ident) = mpsc::channel::<()>(1);
task_set.spawn(event_sink(events, tx_ident, 1));
let agent2 = agent.clone();
let bind2 = bind.clone();
task_set.spawn(async move { agent2.run(bind2.clone(), join).await });
match rx_ident.recv().await {
Some(_) => {}
None => warn!("ident sender dropped"),
}
agent.dht_bootstrap().await?;
while let Some(res) = task_set.join_next().await {
res??;
}
Ok(())
}
2 changes: 1 addition & 1 deletion src/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use tracing_subscriber::{fmt, prelude::*, EnvFilter};

pub fn init() -> Result<()> {
tracing_subscriber::registry()
.with(fmt::layer())
.with(fmt::layer().with_span_events(fmt::format::FmtSpan::CLOSE))
.with(
EnvFilter::try_from_default_env()
.or_else(|_| EnvFilter::try_new("info"))
Expand Down
Loading

0 comments on commit 0ea3abf

Please sign in to comment.