From f5da5af0b9d551e86b18920024f447c1b785e5b0 Mon Sep 17 00:00:00 2001 From: Dave Hrycyszyn Date: Tue, 18 Jun 2024 16:32:32 +0100 Subject: [PATCH] Bitcoin keys now being produced per-node --- Cargo.lock | 1 + side-node/Cargo.toml | 2 +- side-node/src/bitcoin_keys.rs | 35 +++++++++++++++++++++++++++++++++++ side-node/src/init/mod.rs | 27 +++++++++++++++------------ side-node/src/keys.rs | 4 ++-- side-node/src/lib.rs | 1 + side-node/src/node.rs | 6 +++--- side-node/src/utils.rs | 12 ++++++++---- 8 files changed, 66 insertions(+), 22 deletions(-) create mode 100644 side-node/src/bitcoin_keys.rs diff --git a/Cargo.lock b/Cargo.lock index 3968272..5fd95be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2211,6 +2211,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e0cc0f1cf93f4969faf3ea1c7d8a9faed25918d96affa959720823dfe86d4f3" dependencies = [ "bitcoin_hashes 0.12.0", + "rand 0.8.5", "secp256k1-sys 0.10.0", ] diff --git a/side-node/Cargo.toml b/side-node/Cargo.toml index 2c443a9..dfee8df 100644 --- a/side-node/Cargo.toml +++ b/side-node/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" async-trait = "0.1.52" bft-json-crdt = { path = "../crates/bft-json-crdt" } bft-crdt-derive = { path = "../crates/bft-json-crdt/bft-crdt-derive" } -bitcoin = "0.32.2" +bitcoin = { version = "0.32.2", features = ["rand"] } clap = { version = "4.5.4", features = ["derive"] } dirs = "5.0.1" ezsockets = { version = "*", features = ["client"] } diff --git a/side-node/src/bitcoin_keys.rs b/side-node/src/bitcoin_keys.rs new file mode 100644 index 0000000..f4e6bcb --- /dev/null +++ b/side-node/src/bitcoin_keys.rs @@ -0,0 +1,35 @@ +use bitcoin::secp256k1::{rand, Keypair, Secp256k1}; +use std::{ + fs::{self, File}, + io::Write, + path::PathBuf, +}; + +pub(crate) fn write(key_path: &PathBuf) -> Result<(), std::io::Error> { + let secp = Secp256k1::new(); + let (secret_key, public_key) = secp.generate_keypair(&mut rand::thread_rng()); + + let mut file = File::create(key_path)?; + + let pub_str = public_key.to_string(); + let priv_str = secret_key.display_secret().to_string(); + let out = format!("{pub_str}/{priv_str}"); + println!("out: {out}"); + file.write(out.as_bytes())?; + + Ok(()) +} + +pub(crate) fn load_from_file(side_dir: PathBuf) -> bitcoin::secp256k1::Keypair { + let key_path = crate::utils::side_paths(side_dir.clone()).0; + + let data = fs::read_to_string(key_path).expect("couldn't read bitcoin key file"); + println!("data: {:?}", data); + + let secret_key_data = data.split("/").collect::>()[1]; + + let secp = Secp256k1::new(); + let secret_key = bitcoin::secp256k1::SecretKey::from_slice(secret_key_data.as_bytes()).unwrap(); + + Keypair::from_secret_key(&secp, &secret_key) +} diff --git a/side-node/src/init/mod.rs b/side-node/src/init/mod.rs index 453c720..bdbd3b5 100644 --- a/side-node/src/init/mod.rs +++ b/side-node/src/init/mod.rs @@ -2,16 +2,19 @@ use std::path::PathBuf; use config::SideNodeConfig; -use crate::{keys, utils}; +use crate::{bitcoin_keys, keys, utils}; pub(crate) mod config; pub(crate) fn init(home: PathBuf, config: SideNodeConfig) -> Result<(), std::io::Error> { ensure_side_directory_exists(&home)?; - let (key_path, config_path) = utils::side_paths(home.clone()); + let (bft_crdt_key_path, bitcoin_key_path, config_path) = utils::side_paths(home.clone()); - println!("Writing key to: {:?}", key_path); - keys::write(key_path)?; + println!("Writing bft crdt key to: {:?}", bft_crdt_key_path); + keys::write(&bft_crdt_key_path)?; + + println!("Writing bitcoin key to: {:?}", bitcoin_key_path); + bitcoin_keys::write(&bitcoin_key_path)?; println!("Writing config to: {:?}", config_path); config::write_toml(&config, &config_path).expect("unable to write config file"); @@ -20,7 +23,7 @@ pub(crate) fn init(home: PathBuf, config: SideNodeConfig) -> Result<(), std::io: } /// Ensures that the directory at side_dir exists, so we have a place -/// to store our key file and config file. +/// to store our key files and config file. fn ensure_side_directory_exists(side_dir: &PathBuf) -> Result<(), std::io::Error> { if side_dir.exists() { return Ok(()); @@ -58,17 +61,17 @@ mod tests { let (config, name) = side_node_config(); let side_dir = format!("/tmp/side/{name}"); - let mut key_file_path = PathBuf::new(); - key_file_path.push(side_dir.clone()); - key_file_path.push(utils::BFT_CRDT_KEY_FILE); + let mut bitcoin_keys_path = PathBuf::new(); + bitcoin_keys_path.push(side_dir.clone()); + bitcoin_keys_path.push(utils::BITCOIN_KEY_FILE); let _ = init(PathBuf::from_str(&side_dir).unwrap(), config); - assert!(key_file_path.exists()); + assert!(bitcoin_keys_path.exists()); // check that the pem is readable - let data = fs::read_to_string(key_file_path).expect("couldn't read key file"); - let keys = Ed25519KeyPair::decode_base64(&data).expect("couldn't load keypair from file"); - assert_eq!(keys.public().as_bytes().len(), 32); + // let data = fs::read_to_string(bitcoin_keys_path).expect("couldn't read key file"); + // let keys = Ed25519KeyPair::decode_base64(&data).expect("couldn't load keypair from file"); + // assert_eq!(keys.public().as_bytes().len(), 32); } #[test] diff --git a/side-node/src/keys.rs b/side-node/src/keys.rs index 4f0ef34..00ec03e 100644 --- a/side-node/src/keys.rs +++ b/side-node/src/keys.rs @@ -8,7 +8,7 @@ use bft_json_crdt::keypair::{make_keypair, Ed25519KeyPair}; use fastcrypto::traits::EncodeDecodeBase64; /// Writes a new Ed25519 keypair to the file at key_path. -pub(crate) fn write(key_path: PathBuf) -> Result<(), std::io::Error> { +pub(crate) fn write(key_path: &PathBuf) -> Result<(), std::io::Error> { let keys = make_keypair(); let mut file = File::create(key_path)?; @@ -20,7 +20,7 @@ pub(crate) fn write(key_path: PathBuf) -> Result<(), std::io::Error> { pub(crate) fn load_from_file(side_dir: PathBuf) -> Ed25519KeyPair { let key_path = crate::utils::side_paths(side_dir.clone()).0; - let data = fs::read_to_string(key_path).expect("couldn't read key file"); + let data = fs::read_to_string(key_path).expect("couldn't read bft-crdt key file"); println!("data: {:?}", data); Ed25519KeyPair::decode_base64(&data).expect("couldn't load keypair from file") diff --git a/side-node/src/lib.rs b/side-node/src/lib.rs index cb199a4..5dbd829 100644 --- a/side-node/src/lib.rs +++ b/side-node/src/lib.rs @@ -5,6 +5,7 @@ use node::SideNode; use tokio::{sync::mpsc, task}; use websocket::WebSocketClient; +pub(crate) mod bitcoin_keys; pub(crate) mod cli; pub mod crdt; pub(crate) mod init; diff --git a/side-node/src/node.rs b/side-node/src/node.rs index 35eee2d..aa8a970 100644 --- a/side-node/src/node.rs +++ b/side-node/src/node.rs @@ -6,7 +6,7 @@ use crate::{crdt::TransactionList, utils, websocket::WebSocketClient}; pub struct SideNode { crdt: BaseCrdt, - keys: fastcrypto::ed25519::Ed25519KeyPair, + bft_crdt_keys: fastcrypto::ed25519::Ed25519KeyPair, incoming_receiver: mpsc::Receiver, stdin_receiver: std::sync::mpsc::Receiver, handle: ezsockets::Client, @@ -22,7 +22,7 @@ impl SideNode { ) -> Self { let node = Self { crdt, - keys, + bft_crdt_keys: keys, incoming_receiver, stdin_receiver, handle, @@ -80,7 +80,7 @@ impl SideNode { .doc .list .insert(last.id, transaction) - .sign(&self.keys); + .sign(&self.bft_crdt_keys); // self.trace_crdt(); signed_op } diff --git a/side-node/src/utils.rs b/side-node/src/utils.rs index f70d865..aa55a83 100644 --- a/side-node/src/utils.rs +++ b/side-node/src/utils.rs @@ -3,18 +3,22 @@ use std::path::PathBuf; use bft_json_crdt::json_crdt::SignedOp; use serde_json::{json, Value}; +pub(crate) const BITCOIN_KEY_FILE: &str = "bitcoin_keys.pem"; pub(crate) const BFT_CRDT_KEY_FILE: &str = "keys.pem"; pub(crate) const CONFIG_FILE: &str = "config.toml"; /// Returns the path to the key file and config for this host OS. -pub(crate) fn side_paths(prefix: PathBuf) -> (PathBuf, PathBuf) { - let mut key_path = prefix.clone(); - key_path.push(BFT_CRDT_KEY_FILE); +pub(crate) fn side_paths(prefix: PathBuf) -> (PathBuf, PathBuf, PathBuf) { + let mut bft_crdt_key_path = prefix.clone(); + bft_crdt_key_path.push(BFT_CRDT_KEY_FILE); + + let mut bitcoin_key_path = prefix.clone(); + bitcoin_key_path.push(BITCOIN_KEY_FILE); let mut config_path = prefix.clone(); config_path.push(CONFIG_FILE); - (key_path, config_path) + (bft_crdt_key_path, bitcoin_key_path, config_path) } pub(crate) fn home(name: &String) -> std::path::PathBuf {