From c00a5b0a2072264d688bea57bad06315d7bfa474 Mon Sep 17 00:00:00 2001 From: Nacho Date: Wed, 22 Nov 2023 12:25:59 -0300 Subject: [PATCH 1/6] add SQL relations --- src/cli/account.rs | 4 ++-- src/store/mod.rs | 2 +- src/store/store.sql | 27 +++++++++++++++++++++------ 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/cli/account.rs b/src/cli/account.rs index 9626abc8b..fca084ad5 100644 --- a/src/cli/account.rs +++ b/src/cli/account.rs @@ -153,10 +153,10 @@ fn new_account(template: &Option, deploy: bool) -> Result<(), S // TODO: Make these inserts atomic through a single transaction client .store() - .insert_account(&account) - .and_then(|_| client.store().insert_account_code(account.code())) + .insert_account_code(account.code()) .and_then(|_| client.store().insert_account_storage(account.storage())) .and_then(|_| client.store().insert_account_vault(account.vault())) + .and_then(|_| client.store().insert_account(&account)) .map(|_| { println!( "Succesfully created and stored Account ID: {}", diff --git a/src/store/mod.rs b/src/store/mod.rs index 9f3fe8b06..139b6de38 100644 --- a/src/store/mod.rs +++ b/src/store/mod.rs @@ -128,7 +128,7 @@ impl Store { self.db .execute( - "INSERT INTO account_vault (root, assets) VALUES (?, ?)", + "INSERT INTO account_vaults (root, assets) VALUES (?, ?)", params![vault_root, assets], ) .map(|_| ()) diff --git a/src/store/store.sql b/src/store/store.sql index ac38d4836..291857452 100644 --- a/src/store/store.sql +++ b/src/store/store.sql @@ -2,19 +2,30 @@ CREATE TABLE account_code ( root BLOB NOT NULL, -- root of the Merkle tree for all exported procedures in account module. procedures BLOB NOT NULL, -- serialized procedure digests for the account code. - module BLOB NOT NULL -- serialized ModuleAst for the account code. + module BLOB NOT NULL, -- serialized ModuleAst for the account code. + PRIMARY KEY (root) ); -- Create account_storage table CREATE TABLE account_storage ( root BLOB NOT NULL, -- root of the account storage Merkle tree. - slots BLOB NOT NULL -- serialized key-value pair of non-empty account slots. + slots BLOB NOT NULL, -- serialized key-value pair of non-empty account slots. + PRIMARY KEY (root) ); --- Create account_vault table -CREATE TABLE account_vault ( +-- Create account_vaults table +CREATE TABLE account_vaults ( root BLOB NOT NULL, -- root of the Merkle tree for the account vault. - assets BLOB NOT NULL -- serialized account vault assets. + assets BLOB NOT NULL, -- serialized account vault assets. + PRIMARY KEY (root) +); + +-- Create account_keys table +CREATE TABLE account_keys ( + account_id UNSIGNED BIG INT NOT NULL, -- ID of the account + key_pair BLOB NOT NULL, -- key pair + PRIMARY KEY (account_id), + FOREIGN KEY (account_id) REFERENCES accounts(id) ); -- Update accounts table @@ -24,5 +35,9 @@ CREATE TABLE accounts ( storage_root BLOB NOT NULL, -- root of the account_storage Merkle tree. vault_root BLOB NOT NULL, -- root of the account_vault Merkle tree. nonce BIGINT NOT NULL, -- account nonce. - committed BOOLEAN NOT NULL -- true if recorded, false if not. + committed BOOLEAN NOT NULL, -- true if recorded, false if not. + PRIMARY KEY (id), + FOREIGN KEY (code_root) REFERENCES account_code(root), + FOREIGN KEY (storage_root) REFERENCES account_storage(root), + FOREIGN KEY (vault_root) REFERENCES account_vaults(root) ); From f490d11847267315c9bb19adf0a36f6bce76262c Mon Sep 17 00:00:00 2001 From: Nacho Date: Thu, 23 Nov 2023 15:45:39 -0300 Subject: [PATCH 2/6] align comments --- src/store/store.sql | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/store/store.sql b/src/store/store.sql index 291857452..f28c916f3 100644 --- a/src/store/store.sql +++ b/src/store/store.sql @@ -1,40 +1,40 @@ -- Create account_code table CREATE TABLE account_code ( - root BLOB NOT NULL, -- root of the Merkle tree for all exported procedures in account module. - procedures BLOB NOT NULL, -- serialized procedure digests for the account code. - module BLOB NOT NULL, -- serialized ModuleAst for the account code. + root BLOB NOT NULL, -- root of the Merkle tree for all exported procedures in account module. + procedures BLOB NOT NULL, -- serialized procedure digests for the account code. + module BLOB NOT NULL, -- serialized ModuleAst for the account code. PRIMARY KEY (root) ); -- Create account_storage table CREATE TABLE account_storage ( - root BLOB NOT NULL, -- root of the account storage Merkle tree. - slots BLOB NOT NULL, -- serialized key-value pair of non-empty account slots. + root BLOB NOT NULL, -- root of the account storage Merkle tree. + slots BLOB NOT NULL, -- serialized key-value pair of non-empty account slots. PRIMARY KEY (root) ); -- Create account_vaults table CREATE TABLE account_vaults ( - root BLOB NOT NULL, -- root of the Merkle tree for the account vault. - assets BLOB NOT NULL, -- serialized account vault assets. + root BLOB NOT NULL, -- root of the Merkle tree for the account vault. + assets BLOB NOT NULL, -- serialized account vault assets. PRIMARY KEY (root) ); -- Create account_keys table CREATE TABLE account_keys ( - account_id UNSIGNED BIG INT NOT NULL, -- ID of the account - key_pair BLOB NOT NULL, -- key pair + account_id UNSIGNED BIG INT NOT NULL, -- ID of the account + key_pair BLOB NOT NULL, -- key pair PRIMARY KEY (account_id), FOREIGN KEY (account_id) REFERENCES accounts(id) ); --- Update accounts table +-- Create accounts table CREATE TABLE accounts ( id UNSIGNED BIG INT NOT NULL, -- account ID. - code_root BLOB NOT NULL, -- root of the account_code Merkle tree. - storage_root BLOB NOT NULL, -- root of the account_storage Merkle tree. - vault_root BLOB NOT NULL, -- root of the account_vault Merkle tree. - nonce BIGINT NOT NULL, -- account nonce. + code_root BLOB NOT NULL, -- root of the account_code Merkle tree. + storage_root BLOB NOT NULL, -- root of the account_storage Merkle tree. + vault_root BLOB NOT NULL, -- root of the account_vault Merkle tree. + nonce BIGINT NOT NULL, -- account nonce. committed BOOLEAN NOT NULL, -- true if recorded, false if not. PRIMARY KEY (id), FOREIGN KEY (code_root) REFERENCES account_code(root), From 2e332ec8596f86f7ed1c1e4ab7fdb036efe4a346 Mon Sep 17 00:00:00 2001 From: Jmunoz Date: Fri, 24 Nov 2023 15:22:22 -0300 Subject: [PATCH 3/6] initial impl --- src/cli/account.rs | 24 ++++++++++++++++++++++++ src/store/mod.rs | 10 ++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/cli/account.rs b/src/cli/account.rs index 9626abc8b..66c2b0a77 100644 --- a/src/cli/account.rs +++ b/src/cli/account.rs @@ -32,6 +32,13 @@ pub enum AccountCmd { #[clap(short, long, default_value_t = false)] deploy: bool, }, + + /// Remove existing account from the local store + #[clap(short_flag = 'r')] + Remove { + #[clap()] + id: String, + }, } #[derive(Debug, Parser, Clone)] @@ -64,6 +71,7 @@ impl AccountCmd { new_account(template, *deploy)?; } AccountCmd::View { id: _ } => todo!(), + AccountCmd::Remove { id } => remove_account(id)?, } Ok(()) } @@ -167,3 +175,19 @@ fn new_account(template: &Option, deploy: bool) -> Result<(), S Ok(()) } + +// ACCOUNT REMOVE + +fn remove_account(id: &str) -> Result<(), String> { + let client = Client::new(ClientConfig::default()).map_err(|err| err.to_string())?; + + let without_prefix = id.trim_start_matches("0x"); + let account_id: u64 = u64::from_str_radix(&without_prefix, 16).unwrap(); + client + .store() + .remove_account(account_id) + .map_err(|err| err.to_string())?; + + println!("Succesfully removed Account ID: {}", id); + Ok(()) +} diff --git a/src/store/mod.rs b/src/store/mod.rs index 9f3fe8b06..36a7fb3ea 100644 --- a/src/store/mod.rs +++ b/src/store/mod.rs @@ -134,6 +134,16 @@ impl Store { .map(|_| ()) .map_err(StoreError::QueryError) } + + pub fn remove_account(&self, account_id: u64) -> Result<(), StoreError> { + self.db + .execute( + "DELETE FROM accounts WHERE id = ?", + params![account_id as i64], + ) + .map(|_| ()) + .map_err(StoreError::QueryError) + } } // STORE CONFIG From 6267c26a5a7648959209bc9d683b4eeee3b6b5dd Mon Sep 17 00:00:00 2001 From: Jmunoz Date: Fri, 24 Nov 2023 15:36:02 -0300 Subject: [PATCH 4/6] improve rmv function --- src/cli/account.rs | 3 ++- src/errors.rs | 2 ++ src/store/mod.rs | 12 +++++++++--- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/cli/account.rs b/src/cli/account.rs index 66c2b0a77..449dac9d4 100644 --- a/src/cli/account.rs +++ b/src/cli/account.rs @@ -182,7 +182,8 @@ fn remove_account(id: &str) -> Result<(), String> { let client = Client::new(ClientConfig::default()).map_err(|err| err.to_string())?; let without_prefix = id.trim_start_matches("0x"); - let account_id: u64 = u64::from_str_radix(&without_prefix, 16).unwrap(); + let account_id: u64 = + u64::from_str_radix(&without_prefix, 16).map_err(|err| err.to_string())?; client .store() .remove_account(account_id) diff --git a/src/errors.rs b/src/errors.rs index b52fbf800..3b0b02710 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -38,6 +38,7 @@ pub enum StoreError { QueryError(rusqlite::Error), InputSerializationError(serde_json::Error), DataDeserializationError(serde_json::Error), + NotFound, } impl fmt::Display for StoreError { @@ -53,6 +54,7 @@ impl fmt::Display for StoreError { DataDeserializationError(err) => { write!(f, "error deserializing data from the store: {err}") } + NotFound => write!(f, "requested data was not found in the store"), } } } diff --git a/src/store/mod.rs b/src/store/mod.rs index 36a7fb3ea..5532365dc 100644 --- a/src/store/mod.rs +++ b/src/store/mod.rs @@ -136,13 +136,19 @@ impl Store { } pub fn remove_account(&self, account_id: u64) -> Result<(), StoreError> { - self.db + let q = self + .db .execute( "DELETE FROM accounts WHERE id = ?", params![account_id as i64], ) - .map(|_| ()) - .map_err(StoreError::QueryError) + .map_err(StoreError::QueryError)?; + + if q == 0 { + return Err(StoreError::NotFound); + } + + Ok(()) } } From 509f449aab38205c586e0e5eec45f7c10376cf6f Mon Sep 17 00:00:00 2001 From: jmunoz Date: Mon, 27 Nov 2023 12:23:56 -0300 Subject: [PATCH 5/6] remove from other tables --- src/cli/account.rs | 8 +++--- src/lib.rs | 5 ++++ src/store/mod.rs | 66 ++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 70 insertions(+), 9 deletions(-) diff --git a/src/cli/account.rs b/src/cli/account.rs index 78483b3d7..426db0925 100644 --- a/src/cli/account.rs +++ b/src/cli/account.rs @@ -177,15 +177,15 @@ fn new_account(template: &Option, deploy: bool) -> Result<(), S } // ACCOUNT REMOVE +// ================================================================================================ fn remove_account(id: &str) -> Result<(), String> { - let client = Client::new(ClientConfig::default()).map_err(|err| err.to_string())?; + let mut client = Client::new(ClientConfig::default()).map_err(|err| err.to_string())?; let without_prefix = id.trim_start_matches("0x"); - let account_id: u64 = - u64::from_str_radix(&without_prefix, 16).map_err(|err| err.to_string())?; + let account_id: u64 = u64::from_str_radix(without_prefix, 16).map_err(|err| err.to_string())?; client - .store() + .store_mut() .remove_account(account_id) .map_err(|err| err.to_string())?; diff --git a/src/lib.rs b/src/lib.rs index a888acb35..31d0b1e04 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,6 +47,11 @@ impl Client { &self.store } + /// Returns a mutable reference to the store + pub fn store_mut(&mut self) -> &mut Store { + &mut self.store + } + // DATA RETRIEVAL // -------------------------------------------------------------------------------------------- diff --git a/src/store/mod.rs b/src/store/mod.rs index 19bd2e77a..a19109aa0 100644 --- a/src/store/mod.rs +++ b/src/store/mod.rs @@ -135,19 +135,75 @@ impl Store { .map_err(StoreError::QueryError) } - pub fn remove_account(&self, account_id: u64) -> Result<(), StoreError> { - let q = self - .db + pub fn remove_account(&mut self, account_id: u64) -> Result<(), StoreError> { + let tx = self.db.transaction().map_err(StoreError::ConnectionError)?; + + let Ok((code_root, storage_root, vault_root)) = tx.query_row( + "SELECT code_root, storage_root, vault_root FROM accounts WHERE id = ? ", + params![account_id as i64], + |row| { + let code_root: String = row.get(0)?; + let storage_root: String = row.get(1)?; + let vault_root: String = row.get(2)?; + + Ok((code_root, storage_root, vault_root)) + }, + ) else { + return Err(StoreError::NotFound); + }; + + // Remove from accounts table + if tx .execute( "DELETE FROM accounts WHERE id = ?", params![account_id as i64], ) - .map_err(StoreError::QueryError)?; + .map_err(StoreError::QueryError)? + == 0 + { + return Err(StoreError::NotFound); + } + + // Remove from account_keys table + // Currently not stored - if q == 0 { + // Remove from account_code table + if tx + .execute( + "DELETE FROM account_code WHERE root = ?", + params![code_root], + ) + .map_err(StoreError::QueryError)? + == 0 + { + return Err(StoreError::NotFound); + } + + // Remove from account_storage table + if tx + .execute( + "DELETE FROM account_storage WHERE root = ?", + params![storage_root], + ) + .map_err(StoreError::QueryError)? + == 0 + { + return Err(StoreError::NotFound); + } + + // Remove from account_vaults table + if tx + .execute( + "DELETE FROM account_vaults WHERE root = ?", + params![vault_root], + ) + .map_err(StoreError::QueryError)? + == 0 + { return Err(StoreError::NotFound); } + tx.commit().map_err(StoreError::ConnectionError)?; Ok(()) } } From 2aa83a049190263f61347e42a8006486b2552a2b Mon Sep 17 00:00:00 2001 From: jmunoz Date: Mon, 27 Nov 2023 12:25:29 -0300 Subject: [PATCH 6/6] add comment --- src/store/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/store/mod.rs b/src/store/mod.rs index a19109aa0..3b6f2f044 100644 --- a/src/store/mod.rs +++ b/src/store/mod.rs @@ -168,6 +168,7 @@ impl Store { // Currently not stored // Remove from account_code table + // should only be removed if it is not used by any other account if tx .execute( "DELETE FROM account_code WHERE root = ?",