From 318d446dbd4d14b1c2d6bd7b16038f5cff8b0ae1 Mon Sep 17 00:00:00 2001 From: silverpill Date: Mon, 15 Aug 2022 23:56:06 +0000 Subject: [PATCH] Add create-monero-wallet CLI command --- Cargo.lock | 106 ++++++++++++++++++++++++++++++++++++++- Cargo.toml | 2 + config.yaml.example | 7 +++ src/bin/mitractl.rs | 1 + src/cli.rs | 24 ++++++++- src/config/blockchain.rs | 25 ++++++++- src/config/mod.rs | 2 +- src/lib.rs | 1 + src/monero/mod.rs | 1 + src/monero/wallet.rs | 23 +++++++++ 10 files changed, 186 insertions(+), 6 deletions(-) create mode 100644 src/monero/mod.rs create mode 100644 src/monero/wallet.rs diff --git a/Cargo.lock b/Cargo.lock index f1796ab..a7e970e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -350,6 +350,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[package]] +name = "base58-monero" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d079cdf47e1ca75554200bb2f30bff5a5af16964cac4a566b18de9a5d48db2b" +dependencies = [ + "thiserror", +] + [[package]] name = "base64" version = "0.13.0" @@ -521,7 +530,7 @@ version = "3.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3aab4734e083b809aaf5794e14e756d1c798d2c69c7f7de7a09a2f5214993c1" dependencies = [ - "heck", + "heck 0.4.0", "proc-macro-error", "proc-macro2", "quote", @@ -658,6 +667,20 @@ dependencies = [ "subtle", ] +[[package]] +name = "curve25519-dalek" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "serde", + "subtle", + "zeroize", +] + [[package]] name = "deadpool" version = "0.9.2" @@ -1119,6 +1142,15 @@ dependencies = [ "http", ] +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "heck" version = "0.4.0" @@ -1143,6 +1175,12 @@ dependencies = [ "serde", ] +[[package]] +name = "hex-literal" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" + [[package]] name = "hmac" version = "0.11.0" @@ -1626,6 +1664,7 @@ dependencies = [ "log", "mime-sniffer", "mime_guess", + "monero-rpc", "num_cpus", "pem", "postgres-protocol", @@ -1654,6 +1693,44 @@ dependencies = [ "web3", ] +[[package]] +name = "monero" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afa5d322a573d345588c3255aaf3316b6a13f3b94f8e776c5ffcde237ec481d" +dependencies = [ + "base58-monero", + "curve25519-dalek", + "fixed-hash", + "hex", + "hex-literal", + "sealed", + "serde", + "serde-big-array", + "thiserror", + "tiny-keccak", +] + +[[package]] +name = "monero-rpc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66a7d67be6fc453829e6e0913f239741b0520a40ff6c7e8300f35444a163d257" +dependencies = [ + "anyhow", + "chrono", + "fixed-hash", + "hex", + "http", + "jsonrpc-core", + "monero", + "reqwest", + "serde", + "serde_json", + "tracing", + "uuid", +] + [[package]] name = "native-tls" version = "0.2.10" @@ -2617,6 +2694,18 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "sealed" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b5e421024b5e5edfbaa8e60ecf90bda9dbffc602dbb230e6028763f85f0c68c" +dependencies = [ + "heck 0.3.3", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "secp256k1" version = "0.21.3" @@ -2668,6 +2757,15 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-big-array" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3323f09a748af288c3dc2474ea6803ee81f118321775bffa3ac8f7e65c5e90e7" +dependencies = [ + "serde", +] + [[package]] name = "serde_derive" version = "1.0.136" @@ -3228,6 +3326,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" + [[package]] name = "unicode-xid" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index d3733c6..5f79219 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,8 @@ env_logger = { version = "0.9.0", default-features = false } # Used to guess media type of a file mime_guess = "2.0.3" mime-sniffer = "0.1.2" +# Used to query Monero node +monero-rpc = "0.2.0" # Used to determine the number of CPUs on the system num_cpus = "1.13.0" # Used for working with regular expressions diff --git a/config.yaml.example b/config.yaml.example index 14b6d17..f3ac9fa 100644 --- a/config.yaml.example +++ b/config.yaml.example @@ -22,5 +22,12 @@ blockchain: chain_sync_step: 100 chain_reorg_max_depth: 0 +#blockchain: +# chain_id: monero:regtest +# daemon_url: 'http://127.0.0.1:58081' +# wallet_url: 'http://127.0.0.1:58083' +# wallet_name: test +# wallet_password: test + ipfs_api_url: 'http://127.0.0.1:5001' ipfs_gateway_url: 'http://127.0.0.1:8001' diff --git a/src/bin/mitractl.rs b/src/bin/mitractl.rs index 2d208b8..fdac5e2 100644 --- a/src/bin/mitractl.rs +++ b/src/bin/mitractl.rs @@ -32,6 +32,7 @@ async fn main() { SubCommand::DeleteUnusedAttachments(cmd) => cmd.execute(&config, db_client).await.unwrap(), SubCommand::DeleteOrphanedFiles(cmd) => cmd.execute(&config, db_client).await.unwrap(), SubCommand::UpdateCurrentBlock(cmd) => cmd.execute(&config, db_client).await.unwrap(), + SubCommand::CreateMoneroWallet(cmd) => cmd.execute(&config).await.unwrap(), _ => panic!(), }; }, diff --git a/src/cli.rs b/src/cli.rs index 4f702d0..ec85fb4 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,4 +1,4 @@ -use anyhow::Error; +use anyhow::{anyhow, Error}; use chrono::{Duration, Utc}; use clap::Parser; use tokio_postgres::GenericClient; @@ -26,6 +26,7 @@ use crate::models::users::queries::{ get_invite_codes, get_user_by_id, }; +use crate::monero::wallet::create_monero_wallet; use crate::utils::crypto::{generate_private_key, serialize_private_key}; use crate::utils::files::remove_files; @@ -48,8 +49,9 @@ pub enum SubCommand { DeletePost(DeletePost), DeleteExtraneousPosts(DeleteExtraneousPosts), DeleteUnusedAttachments(DeleteUnusedAttachments), - UpdateCurrentBlock(UpdateCurrentBlock), DeleteOrphanedFiles(DeleteOrphanedFiles), + UpdateCurrentBlock(UpdateCurrentBlock), + CreateMoneroWallet(CreateMoneroWallet), } /// Generate RSA private key @@ -289,3 +291,21 @@ impl UpdateCurrentBlock { Ok(()) } } + +/// Create Monero wallet +#[derive(Parser)] +pub struct CreateMoneroWallet; + +impl CreateMoneroWallet { + pub async fn execute( + &self, + config: &Config, + ) -> Result<(), Error> { + let monero_config = config.blockchain.as_ref() + .and_then(|conf| conf.monero_config()) + .ok_or(anyhow!("monero configuration not found"))?; + create_monero_wallet(monero_config).await?; + println!("wallet created"); + Ok(()) + } +} diff --git a/src/config/blockchain.rs b/src/config/blockchain.rs index 3fe999d..4796ad1 100644 --- a/src/config/blockchain.rs +++ b/src/config/blockchain.rs @@ -40,15 +40,36 @@ impl EthereumConfig { } } +#[derive(Clone, Deserialize)] +pub struct MoneroConfig { + pub chain_id: ChainId, + pub daemon_url: String, + pub wallet_url: String, + pub wallet_name: String, + pub wallet_password: Option, +} + #[derive(Clone, Deserialize)] #[serde(untagged)] pub enum BlockchainConfig { Ethereum(EthereumConfig), + Monero(MoneroConfig), } impl BlockchainConfig { pub fn ethereum_config(&self) -> Option<&EthereumConfig> { - let Self::Ethereum(ethereum_config) = self; - Some(ethereum_config) + if let Self::Ethereum(ethereum_config) = self { + Some(ethereum_config) + } else { + None + } + } + + pub fn monero_config(&self) -> Option<&MoneroConfig> { + if let Self::Monero(monero_config) = self { + Some(monero_config) + } else { + None + } } } diff --git a/src/config/mod.rs b/src/config/mod.rs index e93eda3..c06c71b 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -2,6 +2,6 @@ mod blockchain; mod environment; mod main; -pub use blockchain::EthereumConfig; +pub use blockchain::{EthereumConfig, MoneroConfig}; pub use environment::Environment; pub use main::{parse_config, Config, Instance}; diff --git a/src/lib.rs b/src/lib.rs index 95344fe..f87d49e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,6 +11,7 @@ mod ipfs; pub mod logger; pub mod mastodon_api; pub mod models; +pub mod monero; pub mod nodeinfo; pub mod scheduler; pub mod utils; diff --git a/src/monero/mod.rs b/src/monero/mod.rs new file mode 100644 index 0000000..2fff25c --- /dev/null +++ b/src/monero/mod.rs @@ -0,0 +1 @@ +pub mod wallet; diff --git a/src/monero/wallet.rs b/src/monero/wallet.rs new file mode 100644 index 0000000..5ca092c --- /dev/null +++ b/src/monero/wallet.rs @@ -0,0 +1,23 @@ +use monero_rpc::RpcClient; + +use crate::config::MoneroConfig; + +#[derive(thiserror::Error, Debug)] +pub enum MoneroError { + #[error(transparent)] + WalletError(#[from] anyhow::Error), +} + +/// http://monerotoruzizulg5ttgat2emf4d6fbmiea25detrmmy7erypseyteyd.onion/resources/developer-guides/wallet-rpc.html#create_wallet +pub async fn create_monero_wallet( + config: &MoneroConfig, +) -> Result<(), MoneroError> { + let wallet_client = RpcClient::new(config.wallet_url.clone()).wallet(); + let language = "English".to_string(); + wallet_client.create_wallet( + config.wallet_name.clone(), + config.wallet_password.clone(), + language, + ).await?; + Ok(()) +}