Bitcoin keys now being produced per-node

This commit is contained in:
Dave Hrycyszyn
2024-06-18 16:32:32 +01:00
parent 4cf6513959
commit f5da5af0b9
8 changed files with 66 additions and 22 deletions

1
Cargo.lock generated
View File

@@ -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",
]

View File

@@ -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"] }

View File

@@ -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::<Vec<&str>>()[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)
}

View File

@@ -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]

View File

@@ -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")

View File

@@ -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;

View File

@@ -6,7 +6,7 @@ use crate::{crdt::TransactionList, utils, websocket::WebSocketClient};
pub struct SideNode {
crdt: BaseCrdt<TransactionList>,
keys: fastcrypto::ed25519::Ed25519KeyPair,
bft_crdt_keys: fastcrypto::ed25519::Ed25519KeyPair,
incoming_receiver: mpsc::Receiver<SignedOp>,
stdin_receiver: std::sync::mpsc::Receiver<String>,
handle: ezsockets::Client<WebSocketClient>,
@@ -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
}

View File

@@ -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 {