fix webapp createwallet, and in_memory open wallet

pull/19/head
Niko PLP 7 months ago
parent 32fffcb947
commit 1451f497c2
  1. 2
      nextgraph/examples/open.rs
  2. 2
      nextgraph/examples/persistent.rs
  3. 88
      nextgraph/src/local_broker.rs
  4. 2
      ng-app/src-tauri/src/lib.rs
  5. 13
      ng-app/src/routes/WalletCreate.svelte
  6. 2
      ng-sdk-js/src/lib.rs
  7. 2
      ng-storage-rocksdb/src/block_storage.rs
  8. 2
      ng-storage-rocksdb/src/kcv_storage.rs
  9. 8
      ng-verifier/src/types.rs

@ -59,7 +59,7 @@ async fn main() -> std::io::Result<()> {
// now that the wallet is opened, let's start a session. // now that the wallet is opened, let's start a session.
// we pass the user_id and the wallet_name // we pass the user_id and the wallet_name
let _session = session_start(SessionConfig::new_rocksdb(&user_id, &wallet_name)).await?; let _session = session_start(SessionConfig::new_save(&user_id, &wallet_name)).await?;
// if the user has internet access, they can now decide to connect to its Server Broker, in order to sync data // if the user has internet access, they can now decide to connect to its Server Broker, in order to sync data
let status = user_connect(&user_id).await?; let status = user_connect(&user_id).await?;

@ -124,7 +124,7 @@ async fn main() -> std::io::Result<()> {
// now that the wallet is opened, let's start a session. // now that the wallet is opened, let's start a session.
// we pass the user_id and the wallet_name // we pass the user_id and the wallet_name
let _session = session_start(SessionConfig::new_rocksdb( let _session = session_start(SessionConfig::new_save(
&user_id, &user_id,
&wallet_result.wallet_name, &wallet_result.wallet_name,
)) ))

@ -85,10 +85,7 @@ impl JsStorageConfig {
let ser = serde_bare::to_vec(&spls)?; let ser = serde_bare::to_vec(&spls)?;
//saving the new val //saving the new val
let encoded = base64_url::encode(&ser); let encoded = base64_url::encode(&ser);
let r = (session_write2)(format!("ng_peer_last_seq@{}", peer_id), encoded); (session_write2)(format!("ng_peer_last_seq@{}", peer_id), encoded)?;
if r.is_ok() {
return Err(NgError::SerializationError);
}
} }
Ok(val) Ok(val)
}), }),
@ -113,16 +110,18 @@ impl JsStorageConfig {
), ),
outbox_read_function: Box::new( outbox_read_function: Box::new(
move |peer_id: PubKey| -> Result<Vec<Vec<u8>>, NgError> { move |peer_id: PubKey| -> Result<Vec<Vec<u8>>, NgError> {
let res = (session_read4)(format!("ng_outboxes@{}@start", peer_id)); let start_key = format!("ng_outboxes@{}@start", peer_id);
let mut start = match res { let res = (session_read4)(start_key.clone());
let _start = match res {
Err(_) => return Err(NgError::NotFound), Err(_) => return Err(NgError::NotFound),
Ok(start_str) => start_str Ok(start_str) => start_str
.parse::<u64>() .parse::<u64>()
.map_err(|_| NgError::InvalidFileFormat)?, .map_err(|_| NgError::InvalidFileFormat)?,
}; };
let mut idx: u64 = 0;
let mut result = vec![]; let mut result = vec![];
loop { loop {
let idx_str = format!("{:05}", start); let idx_str = format!("{:05}", idx);
let str = format!("ng_outboxes@{}@{idx_str}", peer_id); let str = format!("ng_outboxes@{}@{idx_str}", peer_id);
let res = (session_read4)(str.clone()); let res = (session_read4)(str.clone());
let res = match res { let res = match res {
@ -133,8 +132,9 @@ impl JsStorageConfig {
let decoded = let decoded =
base64_url::decode(&res).map_err(|_| NgError::SerializationError)?; base64_url::decode(&res).map_err(|_| NgError::SerializationError)?;
result.push(decoded); result.push(decoded);
start += 1; idx += 1;
} }
(session_del)(start_key)?;
Ok(result) Ok(result)
}, },
), ),
@ -236,6 +236,12 @@ impl SessionConfig {
Self::V0(v0) => &v0.verifier_type, Self::V0(v0) => &v0.verifier_type,
} }
} }
pub fn is_memory(&self) -> bool {
match self {
Self::V0(v0) => v0.verifier_type.is_memory(),
}
}
/// Creates a new in_memory SessionConfig with a UserId and a wallet name /// Creates a new in_memory SessionConfig with a UserId and a wallet name
/// ///
/// that should be passed to [session_start] /// that should be passed to [session_start]
@ -247,14 +253,15 @@ impl SessionConfig {
}) })
} }
/// Creates a new SessionConfig backed by RocksDb, with a UserId and a wallet name /// Creates a new SessionConfig that tentatively saves data and/or session, with a UserId and a wallet name
/// ///
/// the session might be downgraded to in_memory if the wallet was added with the in_memory option
/// that should be passed to [session_start] /// that should be passed to [session_start]
pub fn new_rocksdb(user_id: &UserId, wallet_name: &String) -> Self { pub fn new_save(user_id: &UserId, wallet_name: &String) -> Self {
SessionConfig::V0(SessionConfigV0 { SessionConfig::V0(SessionConfigV0 {
user_id: user_id.clone(), user_id: user_id.clone(),
wallet_name: wallet_name.clone(), wallet_name: wallet_name.clone(),
verifier_type: VerifierType::RocksDb, verifier_type: VerifierType::Save,
}) })
} }
@ -273,6 +280,12 @@ impl SessionConfig {
}) })
} }
fn force_in_memory(&mut self) {
match self {
Self::V0(v0) => v0.verifier_type = VerifierType::Memory,
}
}
pub fn new_for_local_broker_config( pub fn new_for_local_broker_config(
user_id: &UserId, user_id: &UserId,
wallet_name: &String, wallet_name: &String,
@ -289,10 +302,10 @@ impl SessionConfig {
} }
VerifierType::Memory VerifierType::Memory
} }
LocalBrokerConfig::JsStorage(js_config) => VerifierType::Memory, LocalBrokerConfig::BasePath(_) | LocalBrokerConfig::JsStorage(_) => match in_memory
LocalBrokerConfig::BasePath(_) => match in_memory { {
true => VerifierType::Memory, true => VerifierType::Memory,
false => VerifierType::RocksDb, false => VerifierType::Save,
}, },
}, },
})) }))
@ -310,11 +323,11 @@ impl SessionConfig {
} }
LocalBrokerConfig::JsStorage(js_config) => match v0.verifier_type { LocalBrokerConfig::JsStorage(js_config) => match v0.verifier_type {
VerifierType::Memory | VerifierType::Remote(_) => true, VerifierType::Memory | VerifierType::Remote(_) => true,
VerifierType::RocksDb => false, VerifierType::Save => true,
VerifierType::WebRocksDb => js_config.is_browser, VerifierType::WebRocksDb => js_config.is_browser,
}, },
LocalBrokerConfig::BasePath(_) => match v0.verifier_type { LocalBrokerConfig::BasePath(_) => match v0.verifier_type {
VerifierType::RocksDb | VerifierType::Remote(_) => true, VerifierType::Save | VerifierType::Remote(_) => true,
VerifierType::Memory => true, VerifierType::Memory => true,
_ => false, _ => false,
}, },
@ -423,14 +436,15 @@ impl LocalBroker {
match (config.verifier_type(), &self.config) { match (config.verifier_type(), &self.config) {
(VerifierType::Memory, LocalBrokerConfig::InMemory) => VerifierConfigType::Memory, (VerifierType::Memory, LocalBrokerConfig::InMemory) => VerifierConfigType::Memory,
(VerifierType::Memory, LocalBrokerConfig::BasePath(_)) => VerifierConfigType::Memory, (VerifierType::Memory, LocalBrokerConfig::BasePath(_)) => VerifierConfigType::Memory,
(VerifierType::RocksDb, LocalBrokerConfig::BasePath(base)) => { (VerifierType::Save, LocalBrokerConfig::BasePath(base)) => {
let mut path = base.clone(); let mut path = base.clone();
path.push(format!("user{}", config.user_id().to_hash_string())); path.push(format!("user{}", config.user_id().to_hash_string()));
VerifierConfigType::RocksDb(path) VerifierConfigType::RocksDb(path)
} }
(VerifierType::Remote(to), _) => VerifierConfigType::Remote(*to), (VerifierType::Remote(to), _) => VerifierConfigType::Remote(*to),
(VerifierType::WebRocksDb, _) => VerifierConfigType::WebRocksDb, (VerifierType::WebRocksDb, _) => VerifierConfigType::WebRocksDb,
(VerifierType::Memory, LocalBrokerConfig::JsStorage(js)) => { (VerifierType::Memory, LocalBrokerConfig::JsStorage(_)) => VerifierConfigType::Memory,
(VerifierType::Save, LocalBrokerConfig::JsStorage(js)) => {
VerifierConfigType::JsSaveSession(js.get_js_storage_config()) VerifierConfigType::JsSaveSession(js.get_js_storage_config())
} }
(_, _) => panic!("invalid combination in verifier_config_type_from_session_config"), (_, _) => panic!("invalid combination in verifier_config_type_from_session_config"),
@ -524,7 +538,8 @@ impl LocalBroker {
} }
#[cfg(target_family = "wasm")] #[cfg(target_family = "wasm")]
{ {
panic!("no RocksDB in WASM"); Arc::new(std::sync::RwLock::new(HashMapBlockStorage::new()))
as Arc<std::sync::RwLock<dyn BlockStorage + Send + Sync + 'static>>
} }
}; };
let client = wallet.client().as_ref().unwrap().clone(); let client = wallet.client().as_ref().unwrap().clone();
@ -544,9 +559,21 @@ impl LocalBroker {
) -> Result<SessionInfo, NgError> { ) -> Result<SessionInfo, NgError> {
let broker = self; let broker = self;
let wallet_name: String = config.wallet_name();
{
match broker.wallets.get(&wallet_name) {
Some(closed_wallet) => {
if closed_wallet.in_memory {
config.force_in_memory();
}
}
None => return Err(NgError::WalletNotFound),
}
}
config.valid_verifier_config_for_local_broker_config(&broker.config)?; config.valid_verifier_config_for_local_broker_config(&broker.config)?;
let wallet_name: String = config.wallet_name();
let wallet_id: PubKey = (*wallet_name).try_into()?; let wallet_id: PubKey = (*wallet_name).try_into()?;
let user_id = config.user_id(); let user_id = config.user_id();
@ -555,7 +582,7 @@ impl LocalBroker {
let ses = &(broker.opened_sessions_list)[*idx as usize]; let ses = &(broker.opened_sessions_list)[*idx as usize];
match ses.as_ref() { match ses.as_ref() {
Some(sess) => { Some(sess) => {
if sess.config.verifier_type() != config.verifier_type() { if !sess.config.is_memory() && config.is_memory() {
return Err(NgError::SessionAlreadyStarted); return Err(NgError::SessionAlreadyStarted);
} else { } else {
return Ok(SessionInfo { return Ok(SessionInfo {
@ -598,8 +625,7 @@ impl LocalBroker {
Some(session) => session, Some(session) => session,
None => { None => {
// creating the session now // creating the session now
let closed_wallet = broker.wallets.get(&wallet_name).unwrap(); if config.is_memory() {
if closed_wallet.in_memory {
let session = SessionPeerStorageV0::new(user_id); let session = SessionPeerStorageV0::new(user_id);
broker.sessions.insert(user_id, session); broker.sessions.insert(user_id, session);
broker.sessions.get(&user_id).unwrap() broker.sessions.get(&user_id).unwrap()
@ -706,6 +732,11 @@ impl LocalBroker {
"NextGraph user_master_key BLAKE3 key", "NextGraph user_master_key BLAKE3 key",
key_material.as_slice(), key_material.as_slice(),
); );
log_info!(
"USER MASTER KEY {user_id} {} {:?}",
user_id.to_hash_string(),
key
);
key_material.zeroize(); key_material.zeroize();
let mut verifier = Verifier::new( let mut verifier = Verifier::new(
VerifierConfig { VerifierConfig {
@ -741,10 +772,16 @@ impl LocalBroker {
} }
pub(crate) fn wallet_save(broker: &mut Self) -> Result<(), NgError> { pub(crate) fn wallet_save(broker: &mut Self) -> Result<(), NgError> {
let wallets_to_be_saved = broker
.wallets
.iter()
.filter(|(_, w)| !w.in_memory)
.map(|(a, b)| (a.clone(), b.clone()))
.collect();
match &broker.config { match &broker.config {
LocalBrokerConfig::JsStorage(js_config) => { LocalBrokerConfig::JsStorage(js_config) => {
// JS save // JS save
let lws_ser = LocalWalletStorage::v0_to_vec(&broker.wallets); let lws_ser = LocalWalletStorage::v0_to_vec(&wallets_to_be_saved);
let encoded = base64_url::encode(&lws_ser); let encoded = base64_url::encode(&lws_ser);
(js_config.local_write)("ng_wallets".to_string(), encoded)?; (js_config.local_write)("ng_wallets".to_string(), encoded)?;
} }
@ -755,7 +792,7 @@ impl LocalBroker {
std::fs::create_dir_all(path.clone()).unwrap(); std::fs::create_dir_all(path.clone()).unwrap();
path.push("wallets"); path.push("wallets");
let lws_ser = LocalWalletStorage::v0_to_vec(&broker.wallets); let lws_ser = LocalWalletStorage::v0_to_vec(&wallets_to_be_saved);
let r = write(path.clone(), &lws_ser); let r = write(path.clone(), &lws_ser);
if r.is_err() { if r.is_err() {
log_debug!("write {:?} {}", path, r.unwrap_err()); log_debug!("write {:?} {}", path, r.unwrap_err());
@ -1192,6 +1229,7 @@ pub async fn user_connect_with_device_info(
let user_id = user.to_string(); let user_id = user.to_string();
let peer_key = &session.peer_key; let peer_key = &session.peer_key;
let peer_id = peer_key.to_pub(); let peer_id = peer_key.to_pub();
log_info!("local peer_id {}", peer_id);
let site = wallet.sites.get(&user_id); let site = wallet.sites.get(&user_id);
if site.is_none() { if site.is_none() {
result.push(( result.push((

@ -179,7 +179,7 @@ async fn session_start(
user: PubKey, user: PubKey,
app: tauri::AppHandle, app: tauri::AppHandle,
) -> Result<SessionInfo, String> { ) -> Result<SessionInfo, String> {
let config = SessionConfig::new_rocksdb(&user, &wallet_name); let config = SessionConfig::new_save(&user, &wallet_name);
nextgraph::local_broker::session_start(config) nextgraph::local_broker::session_start(config)
.await .await
.map_err(|e: NgError| e.to_string()) .map_err(|e: NgError| e.to_string())

@ -1526,13 +1526,12 @@
<span>{emoji}</span><br /> <span>{emoji}</span><br />
{/each} {/each}
<br /><br /> <br /><br />
Copy it on a piece of paper.<br /> Use that until you memorized it,<br Copy it on a piece of paper. Use that until you memorized it, then throw
/> it away.<br /> The order of each image is important!<br />
then throw it away.<br /> The order of each image is important.<br Now click on "Continue to Login" and select your wallet.<br /><br
/> />It is important that you login with this wallet at least once from
Now click on "Continue to Login."<br /><br />It is important that this {#if tauri_platform}device{:else}browser tab{/if},<br />
you login with this wallet at least once from this device<br /> while connected to the internet, so your personal site can be created
(while connected to the internet), so that your personal site is created
on your broker.<br /><br /> on your broker.<br /><br />
<a href="/wallet/login" use:link> <a href="/wallet/login" use:link>
<button <button

@ -168,7 +168,7 @@ pub async fn session_start(wallet_name: String, user_js: JsValue) -> Result<JsVa
let user_id = serde_wasm_bindgen::from_value::<PubKey>(user_js) let user_id = serde_wasm_bindgen::from_value::<PubKey>(user_js)
.map_err(|_| "Deserialization error of user_id")?; .map_err(|_| "Deserialization error of user_id")?;
let config = SessionConfig::new_in_memory(&user_id, &wallet_name); let config = SessionConfig::new_save(&user_id, &wallet_name);
let res = nextgraph::local_broker::session_start(config) let res = nextgraph::local_broker::session_start(config)
.await .await
.map_err(|e: NgError| e.to_string())?; .map_err(|e: NgError| e.to_string())?;

@ -36,7 +36,7 @@ impl RocksDbBlockStorage {
/// The key is the encryption key for the data at rest. /// The key is the encryption key for the data at rest.
pub fn open<'a>(path: &Path, key: [u8; 32]) -> Result<RocksDbBlockStorage, StorageError> { pub fn open<'a>(path: &Path, key: [u8; 32]) -> Result<RocksDbBlockStorage, StorageError> {
let mut opts = Options::default(); let mut opts = Options::default();
opts.set_use_fsync(true); //opts.set_use_fsync(true);
opts.create_if_missing(true); opts.create_if_missing(true);
opts.create_missing_column_families(true); opts.create_missing_column_families(true);
let env = Env::enc_env(key).unwrap(); let env = Env::enc_env(key).unwrap();

@ -654,7 +654,7 @@ impl RocksdbKCVStorage {
/// The key is the encryption key for the data at rest. /// The key is the encryption key for the data at rest.
pub fn open<'a>(path: &Path, key: [u8; 32]) -> Result<RocksdbKCVStorage, StorageError> { pub fn open<'a>(path: &Path, key: [u8; 32]) -> Result<RocksdbKCVStorage, StorageError> {
let mut opts = Options::default(); let mut opts = Options::default();
opts.set_use_fsync(true); //opts.set_use_fsync(true);
opts.create_if_missing(true); opts.create_if_missing(true);
opts.create_missing_column_families(true); opts.create_missing_column_families(true);
let env = Env::enc_env(key).unwrap(); let env = Env::enc_env(key).unwrap();

@ -54,14 +54,14 @@ impl SessionPeerLastSeq {
pub enum VerifierType { pub enum VerifierType {
/// nothing will be saved on disk during the session /// nothing will be saved on disk during the session
Memory, Memory,
/// will save all user data locally, with RocksDb backend /// will save all user data locally, with RocksDb backend on native, and on webapp, will save only the session and wallet, not the data itself
RocksDb, Save,
/// the verifier will be remote. a Noise connection will be opened /// the verifier will be remote. a Noise connection will be opened
/// optional peerId to connect to. If None, will try any that has the flag `can_verify` /// optional peerId to connect to. If None, will try any that has the flag `can_verify`
Remote(Option<PubKey>), Remote(Option<PubKey>),
/// IndexedDb based rocksdb compiled to WASM... not ready yet. obviously. only works in the browser /// IndexedDb based rocksdb compiled to WASM... not ready yet. obviously. only works in the browser
WebRocksDb, WebRocksDb,
// Server, this type is for Server Broker that act as verifier. They answer to VerifierType::Remote types of verifier. // Server, this type is for Server Broker that act as verifier. They answer to VerifierType::Remote types of verifier. deprecated
} }
impl VerifierType { impl VerifierType {
@ -73,7 +73,7 @@ impl VerifierType {
} }
pub fn is_persistent(&self) -> bool { pub fn is_persistent(&self) -> bool {
match self { match self {
Self::RocksDb => true, Self::Save => true,
_ => false, _ => false,
} }
} }

Loading…
Cancel
Save