Skip to content

Commit

Permalink
fix: fix import command
Browse files Browse the repository at this point in the history
  • Loading branch information
edytapawlak committed Jan 22, 2025
1 parent 71949aa commit 36a7823
Show file tree
Hide file tree
Showing 9 changed files with 256 additions and 78 deletions.
61 changes: 61 additions & 0 deletions src/debug.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use std::sync::Arc;

use keri_controller::{communication::Communication, error::ControllerError, identifier::nontransferable::NontransferableIdentifier, known_events::KnownEvents, BasicPrefix, IdentifierPrefix, LocationScheme};
use keri_core::{actor::{prelude::Message, simple_controller::PossibleResponse}, event::sections::seal::EventSeal, processor::escrow::EscrowConfig, signer::Signer, transport::default::DefaultTransport};
use teliox::transport::TelTransport;
use tempfile::Builder;

use crate::export::ExportError;

pub struct TemporaryIdentifier {
signer: Arc<Signer>,
id: NontransferableIdentifier
}

pub fn generate_temporary_identifier() -> Result<TemporaryIdentifier, ExportError> {
// create temporary identifier to pull KEL from witnesses
let signer = Arc::new(Signer::new());
let bp = BasicPrefix::Ed25519NT(signer.public_key());
let transport = Box::new(DefaultTransport::new());
let tel_transport = Box::new(TelTransport);
let tmp_dir = Builder::new().prefix("tmp-dir").tempdir().map_err(|e| ExportError::TemporaryId("Temporary file creation error".to_string()))?;

let tmp_events =
Arc::new(KnownEvents::new(tmp_dir.path().to_path_buf(), EscrowConfig::default()).map_err(|e| ExportError::TemporaryId("Temporary identifier creation error".to_string()))?);
let comm = Arc::new(Communication {
events: tmp_events.clone(),
transport,
tel_transport,
});
let tmp_id = NontransferableIdentifier::new(bp, comm.clone());
Ok(TemporaryIdentifier { signer, id: tmp_id })
}

impl TemporaryIdentifier {
pub async fn pull_kel(&self, seal: &EventSeal, witness_location: LocationScheme) -> Result<Vec<Message>, ControllerError> {
let witness_id = match &witness_location.eid {
IdentifierPrefix::Basic(basic_prefix) => basic_prefix.clone(),
_ => unreachable!("Witness identifier must be basic prefix"),
};

let qry = self.id.query_log(seal, witness_id);
let signature = self.id.sign(self.signer.sign(qry.encode()?).unwrap());
let resp = self.id
.finalize_query(witness_location, qry, signature)
.await?;
match resp {
PossibleResponse::Kel(vec) => {
Ok(vec)

}
_ => unreachable!("Unexpected response from witness"),
}
}

pub async fn pull_tel(&self, registry_id: &IdentifierPrefix, vc_id: Option<IdentifierPrefix>, witness: LocationScheme) -> String {
let tel_qry = self.id.query_tel(registry_id.clone(), vc_id).unwrap();
let signature = self.signer.sign(tel_qry.encode().unwrap()).unwrap();
let sig = self.id.sign(signature);
self.id.finalize_query_tel(witness, tel_qry, sig).await.unwrap()
}
}
112 changes: 98 additions & 14 deletions src/export.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
use keri_controller::{LocationScheme, SeedPrefix};
use std::fs::create_dir_all;

use keri_controller::config::ControllerConfig;
use keri_controller::controller::Controller;
use keri_controller::{
identifier::Identifier, IdentifierPrefix, LocationScheme, SeedPrefix,
};
use keri_controller::{CesrPrimitive, EndRole, Oobi};
use keri_core::event::sections::seal::EventSeal;
use keri_core::oobi::Role;
use serde::{Deserialize, Serialize};

use crate::debug::generate_temporary_identifier;
use crate::tel::save_registry;
use crate::utils::{save_identifier, save_next_seed, save_seed};
use crate::{
init::{handle_init, KeysConfig},
subcommands::identifier::IdentifierSubcommandError,
init::{kel_database_path, KeysConfig},
utils::{
collect_watchers_data, collect_witness_data, load, load_next_seed, load_seed, LoadingError,
},
Expand All @@ -13,10 +24,20 @@ use crate::{
pub enum ExportError {
#[error(transparent)]
Loading(#[from] LoadingError),
#[error("Temporary identifier error: {0}")]
TemporaryId(String),
#[error("File creation error: {0}")]
FileCreation(std::io::Error),
#[error("Writting to file error: {0}")]
FileWritting(std::io::Error),

}

#[derive(Serialize, Deserialize)]
pub struct IdentifierExport {
identifier: IdentifierPrefix,
last_event_seal: EventSeal,
registry_id: Option<IdentifierPrefix>,
current_seed: SeedPrefix,
next_seed: SeedPrefix,
witnesses: Vec<LocationScheme>,
Expand All @@ -30,8 +51,14 @@ pub fn handle_export(alias: &str) -> Result<IdentifierExport, ExportError> {

let (witness_locations, witness_threshold) = collect_witness_data(&identifier)?;
let watchers = collect_watchers_data(&identifier)?;
let id = identifier.id();
let last_event_seal = identifier.get_last_event_seal().unwrap();
let registry_id = identifier.registry_id().map(|id| id.clone());

Ok(IdentifierExport {
identifier: id.clone(),
last_event_seal,
registry_id: registry_id,
current_seed: current,
next_seed: next,
witnesses: witness_locations,
Expand All @@ -40,19 +67,76 @@ pub fn handle_export(alias: &str) -> Result<IdentifierExport, ExportError> {
})
}

pub async fn handle_import(alias: &str, data: &str) -> Result<(), IdentifierSubcommandError> {
let imported: IdentifierExport = serde_json::from_str(data)
.map_err(|_e| IdentifierSubcommandError::ArgumentsError("Invalid JSON".to_string()))?;
pub async fn handle_import(
alias: &str,
imported: IdentifierExport,
) -> Result<(), ExportError> {
let kc = KeysConfig {
current: imported.current_seed,
next: imported.next_seed,
};
handle_init(
alias.to_string(),
Some(kc),
imported.witnesses,
imported.watchers,
imported.witness_threshold,
)
.await

let tmp_id = generate_temporary_identifier()?;

let store_path = kel_database_path(alias)?;
let mut db_path = store_path.clone();
db_path.push("db");
create_dir_all(&db_path).map_err(ExportError::FileCreation)?;

let controller = Controller::new(ControllerConfig {
db_path,
..Default::default()
})
.unwrap();
let identifier = Identifier::new(
imported.identifier.clone(),
imported.registry_id.clone(),
controller.known_events.clone(),
controller.communication.clone(),
controller.query_cache.clone(),
);

// Pull KEL from witnesses
for witness in imported.witnesses {
// Save witness OOBI
identifier
.resolve_oobi(&Oobi::Location(witness.clone()))
.await
.unwrap();
// Find KEL
let kel = tmp_id.pull_kel(&imported.last_event_seal, witness.clone()).await.unwrap();

for msg in kel {
controller.known_events.process(&msg).unwrap();
}

// Find TEL
if let Some(registry_id) = &imported.registry_id {
let tel_resp = tmp_id.pull_tel(registry_id, None, witness).await;
controller.known_events.tel.parse_and_process_tel_stream(tel_resp.as_bytes()).unwrap();
}
}
save_next_seed(&kc.next,&store_path).map_err(ExportError::FileWritting)?;

save_identifier(&imported.identifier, &store_path).map_err(ExportError::FileWritting)?;

save_seed(&kc.current ,&store_path).map_err(ExportError::FileWritting)?;

if let Some(registry_id) = &imported.registry_id {
save_registry(alias, &registry_id.to_str()).unwrap();
}

// reconfigure watcher
let watchers = imported.watchers;
for watcher in watchers {
identifier.resolve_oobi(&Oobi::Location(watcher.clone())).await.unwrap();
let end_role = EndRole { cid: identifier.id().clone(), role: Role::Watcher, eid: (&watcher.eid).clone() };
identifier.resolve_oobi(&Oobi::EndRole(end_role)).await.unwrap();
}

print!(
"\nIdentifier for alias {} imported: {}",
alias, imported.identifier
);
Ok(())
}
84 changes: 40 additions & 44 deletions src/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use ed25519_dalek::SigningKey;

use keri_controller::{
config::ControllerConfig, controller::Controller, identifier::Identifier, BasicPrefix,
CesrPrimitive, LocationScheme, SeedPrefix,
LocationScheme, SeedPrefix,
};
use keri_core::signer::Signer;
use serde::{Deserialize, Serialize};
Expand All @@ -21,7 +21,7 @@ use crate::{
keri::{setup_identifier, KeriError},
subcommands::identifier::IdentifierSubcommandError,
tel::remove_registry,
utils::working_directory,
utils::{save_identifier, save_next_seed, save_seed, working_directory, LoadingError},
CliError,
};

Expand Down Expand Up @@ -125,6 +125,43 @@ pub async fn handle_init(

let keys = keys_config.unwrap_or_default();

// Compute kel database path
let store_path = kel_database_path(&alias)?;

println!("Initializing identifier for alias {:?}...", store_path);
let mut db_path = store_path.clone();
db_path.push("db");

let info = format!("No witnesses are configured for {} identifier, so KEL won't be publicly available. To configure witnesses, provide their OOBIs with --witness option", &alias);
match &kel_config.witness {
Some(wits) if wits.is_empty() => println!("{}", info),
None => println!("{}", info),
Some(_) => (),
};

let id = handle_new_id(&keys, kel_config, &db_path).await;
match id {
Ok(id) => {
let _ = remove_registry(&alias);
// Save next keys seed
save_next_seed(&keys.next, &store_path)?;

// Save identifier
save_identifier(id.id(), &store_path)?;
// Save private key
save_seed(&keys.current, &store_path)?;

print!("\nIdentifier for alias {} initialized: {}", alias, id.id());
}
Err(e) => {
println!("{}", e)
}
}

Ok(())
}

pub fn kel_database_path(alias: &str) -> Result<PathBuf, LoadingError> {
// Compute kel database path
let mut store_path = working_directory()?;
store_path.push(&alias);
Expand Down Expand Up @@ -154,48 +191,7 @@ pub async fn handle_init(
);
std::process::exit(1);
}

println!("Initializing identifier for alias {:?}...", store_path);
let mut db_path = store_path.clone();
db_path.push("db");

let info = format!("No witnesses are configured for {} identifier, so KEL won't be publicly available. To configure witnesses, provide their OOBIs with --witness option", &alias);
match &kel_config.witness {
Some(wits) if wits.is_empty() => println!("{}", info),
None => println!("{}", info),
Some(_) => (),
};

let id = handle_new_id(&keys, kel_config, &db_path).await;
match id {
Ok(id) => {
let _ = remove_registry(&alias);
// Save next keys seed
let mut nsk_path = store_path.clone();
nsk_path.push("next_priv_key");
let mut file = File::create(nsk_path)?;
file.write_all(keys.next.to_str().as_bytes())?;

print!("\nIdentifier for alias {} initialized: {}", alias, id.id());

// Save identifier
let mut id_path = store_path.clone();
id_path.push("id");
let mut file = File::create(id_path)?;
file.write_all(id.id().to_string().as_bytes())?;

// Save private key
let mut priv_key_path = store_path.clone();
priv_key_path.push("priv_key");
let mut file = File::create(priv_key_path)?;
file.write_all(keys.current.to_str().as_bytes())?;
}
Err(e) => {
println!("{}", e)
}
}

Ok(())
Ok(store_path)
}

pub(crate) async fn handle_new_id(
Expand Down
1 change: 0 additions & 1 deletion src/keri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,6 @@ pub async fn issue(
Ok(())
}


pub async fn revoke(
identifier: &mut Identifier,
cred_said: &SelfAddressingIdentifier,
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ mod temporary_id;
mod utils;
mod verification_status;
mod verify;
mod debug;

#[derive(Parser)]
#[command(author, version, about, long_about = None, help_template = help::HELP_TEMPLATE)]
Expand Down
18 changes: 8 additions & 10 deletions src/subcommands/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,17 +150,15 @@ pub async fn process_data_command(command: DataCommand) -> Result<(), CliError>
alias,
credential: credential_json,
said,
} => {
match (credential_json, said) {
(None, None) => println!("Credential or its SAID in expected"),
(None, Some(said)) => handle_revoke(&alias, &said).await?,
(Some(cred), None) => {
let said = extract_said(&cred)?;
handle_revoke(&alias, &said).await?
},
(Some(_), Some(_)) => println!("Only one of credential or its SAID is expected"),
} => match (credential_json, said) {
(None, None) => println!("Credential or its SAID in expected"),
(None, Some(said)) => handle_revoke(&alias, &said).await?,
(Some(cred), None) => {
let said = extract_said(&cred)?;
handle_revoke(&alias, &said).await?
}
}
(Some(_), Some(_)) => println!("Only one of credential or its SAID is expected"),
},
}
Ok(())
}
11 changes: 9 additions & 2 deletions src/subcommands/identifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use keri_controller::LocationScheme;
use tabled::{builder::Builder, settings::Style};
use url::Url;

use crate::export::IdentifierExport;
use crate::{
export::{handle_export, handle_import, ExportError},
init::{handle_init, KeysConfig},
Expand Down Expand Up @@ -197,7 +198,10 @@ pub async fn process_identifier_command(
}
IdentifierCommand::Import { data, alias } => match data {
Some(data) => {
handle_import(&alias, &data).await?;
let imported: IdentifierExport = serde_json::from_str(&data).map_err(|_e| {
IdentifierSubcommandError::ArgumentsError("Invalid JSON".to_string())
})?;
handle_import(&alias, imported).await?;
Ok(())
}
None => {
Expand All @@ -215,7 +219,10 @@ pub async fn process_identifier_command(
e
))
})?;
handle_import(&alias, &buffer).await?;
let imported: IdentifierExport = serde_json::from_str(&buffer).map_err(|_e| {
IdentifierSubcommandError::ArgumentsError("Invalid JSON".to_string())
})?;
handle_import(&alias, imported).await?;
Ok(())
}
},
Expand Down
Loading

0 comments on commit 36a7823

Please sign in to comment.