diff --git a/Cargo.lock b/Cargo.lock index 00c4ca822..2a660a505 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1826,7 +1826,7 @@ checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "guinea" -version = "0.5.1" +version = "0.5.2" dependencies = [ "bincode", "magicblock-magic-program-api", @@ -2781,7 +2781,7 @@ dependencies = [ [[package]] name = "magicblock-account-cloner" -version = "0.5.1" +version = "0.5.2" dependencies = [ "async-trait", "bincode", @@ -2813,7 +2813,7 @@ dependencies = [ [[package]] name = "magicblock-accounts" -version = "0.5.1" +version = "0.5.2" dependencies = [ "async-trait", "log", @@ -2835,7 +2835,7 @@ dependencies = [ [[package]] name = "magicblock-accounts-db" -version = "0.5.1" +version = "0.5.2" dependencies = [ "env_logger 0.11.8", "lmdb-rkv", @@ -2853,7 +2853,7 @@ dependencies = [ [[package]] name = "magicblock-aperture" -version = "0.5.1" +version = "0.5.2" dependencies = [ "arc-swap", "base64 0.21.7", @@ -2903,7 +2903,7 @@ dependencies = [ [[package]] name = "magicblock-api" -version = "0.5.1" +version = "0.5.2" dependencies = [ "anyhow", "borsh 1.6.0", @@ -2958,7 +2958,7 @@ dependencies = [ [[package]] name = "magicblock-chainlink" -version = "0.5.1" +version = "0.5.2" dependencies = [ "arc-swap", "assert_matches", @@ -3011,7 +3011,7 @@ dependencies = [ [[package]] name = "magicblock-committor-program" -version = "0.5.1" +version = "0.5.2" dependencies = [ "borsh 1.6.0", "paste", @@ -3023,7 +3023,7 @@ dependencies = [ [[package]] name = "magicblock-committor-service" -version = "0.5.1" +version = "0.5.2" dependencies = [ "async-trait", "base64 0.21.7", @@ -3069,7 +3069,7 @@ dependencies = [ [[package]] name = "magicblock-config" -version = "0.5.1" +version = "0.5.2" dependencies = [ "clap 4.5.53", "derive_more", @@ -3089,7 +3089,7 @@ dependencies = [ [[package]] name = "magicblock-core" -version = "0.5.1" +version = "0.5.2" dependencies = [ "flume", "magicblock-magic-program-api", @@ -3131,7 +3131,7 @@ dependencies = [ [[package]] name = "magicblock-ledger" -version = "0.5.1" +version = "0.5.2" dependencies = [ "arc-swap", "bincode", @@ -3172,7 +3172,7 @@ dependencies = [ [[package]] name = "magicblock-magic-program-api" -version = "0.5.1" +version = "0.5.2" dependencies = [ "bincode", "serde", @@ -3181,7 +3181,7 @@ dependencies = [ [[package]] name = "magicblock-metrics" -version = "0.5.1" +version = "0.5.2" dependencies = [ "http-body-util", "hyper 1.8.1", @@ -3195,7 +3195,7 @@ dependencies = [ [[package]] name = "magicblock-processor" -version = "0.5.1" +version = "0.5.2" dependencies = [ "bincode", "guinea", @@ -3235,7 +3235,7 @@ dependencies = [ [[package]] name = "magicblock-program" -version = "0.5.1" +version = "0.5.2" dependencies = [ "assert_matches", "bincode", @@ -3271,7 +3271,7 @@ dependencies = [ [[package]] name = "magicblock-rpc-client" -version = "0.5.1" +version = "0.5.2" dependencies = [ "log", "solana-account", @@ -3292,7 +3292,7 @@ dependencies = [ [[package]] name = "magicblock-table-mania" -version = "0.5.1" +version = "0.5.2" dependencies = [ "ed25519-dalek", "log", @@ -3318,7 +3318,7 @@ dependencies = [ [[package]] name = "magicblock-task-scheduler" -version = "0.5.1" +version = "0.5.2" dependencies = [ "bincode", "chrono", @@ -3345,7 +3345,7 @@ dependencies = [ [[package]] name = "magicblock-validator" -version = "0.5.1" +version = "0.5.2" dependencies = [ "console-subscriber", "env_logger 0.11.8", @@ -3360,7 +3360,7 @@ dependencies = [ [[package]] name = "magicblock-validator-admin" -version = "0.5.1" +version = "0.5.2" dependencies = [ "log", "magicblock-delegation-program", @@ -3377,7 +3377,7 @@ dependencies = [ [[package]] name = "magicblock-version" -version = "0.5.1" +version = "0.5.2" dependencies = [ "git-version", "rustc_version", @@ -5294,7 +5294,7 @@ dependencies = [ [[package]] name = "solana-account" version = "2.2.1" -source = "git+https://github.com/magicblock-labs/solana-account.git?rev=57158728#571587284a525b66666291aee5174783139a1595" +source = "git+https://github.com/magicblock-labs/solana-account.git?rev=2246929#2246929c6614f60d9909fdd117aab3bc454a9775" dependencies = [ "bincode", "qualifier_attr", @@ -7066,7 +7066,7 @@ dependencies = [ [[package]] name = "solana-storage-proto" -version = "0.5.1" +version = "0.5.2" dependencies = [ "bincode", "bs58", @@ -8115,7 +8115,7 @@ dependencies = [ [[package]] name = "test-kit" -version = "0.5.1" +version = "0.5.2" dependencies = [ "env_logger 0.11.8", "guinea", diff --git a/Cargo.toml b/Cargo.toml index 7e0ca4b9d..0a046d92f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,7 @@ resolver = "2" [workspace.package] # Solana Version (2.2.x) -version = "0.5.1" +version = "0.5.2" authors = ["MagicBlock Maintainers "] repository = "https://github.com/magicblock-labs/ephemeral-validator" homepage = "https://www.magicblock.xyz" @@ -135,7 +135,7 @@ serde_json = "1.0" serde_with = "3.16" serial_test = "3.2" sha3 = "0.10.8" -solana-account = { git = "https://github.com/magicblock-labs/solana-account.git", rev = "57158728" } +solana-account = { git = "https://github.com/magicblock-labs/solana-account.git", rev = "2246929" } solana-account-decoder = { version = "2.2" } solana-account-decoder-client-types = { version = "2.2" } solana-account-info = { version = "2.2" } @@ -224,7 +224,7 @@ features = ["lz4"] # some solana dependencies have solana-storage-proto as dependency # we need to patch them with our version, because they use protobuf-src v1.1.0 # and we use protobuf-src v2.1.1. Otherwise compilation fails -solana-account = { git = "https://github.com/magicblock-labs/solana-account.git", rev = "57158728" } +solana-account = { git = "https://github.com/magicblock-labs/solana-account.git", rev = "2246929" } solana-storage-proto = { path = "./storage-proto" } solana-svm = { git = "https://github.com/magicblock-labs/magicblock-svm.git", rev = "3e9456ec4" } # Fork is used to enable `disable_manual_compaction` usage diff --git a/magicblock-accounts-db/src/error.rs b/magicblock-accounts-db/src/error.rs index 5ceb1a63f..5154fd4c1 100644 --- a/magicblock-accounts-db/src/error.rs +++ b/magicblock-accounts-db/src/error.rs @@ -26,9 +26,9 @@ impl From for AccountsDbError { #[macro_export] macro_rules! log_err { ($msg: expr) => { - |err| ::log::warn!("{} error: {err}", $msg) + |err| ::log::error!("{} error: {err}", $msg) }; ($msg: expr, $($ctx:expr),* $(,)?) => { - |err| ::log::warn!("{} error: {err}", format!($msg, $($ctx),*)) + |err| ::log::error!("{} error: {err}", format!($msg, $($ctx),*)) }; } diff --git a/magicblock-accounts-db/src/index.rs b/magicblock-accounts-db/src/index.rs index ddd752bf6..fe7c3e5ca 100644 --- a/magicblock-accounts-db/src/index.rs +++ b/magicblock-accounts-db/src/index.rs @@ -168,10 +168,10 @@ impl AccountsDbIndex { pubkey: &Pubkey, owner: &Pubkey, allocation: Allocation, + txn: &mut RwTransaction, ) -> AccountsDbResult> { let Allocation { offset, blocks, .. } = allocation; - let mut txn = self.env.begin_rw_txn()?; let mut dealloc = None; // merge offset and block count into one single u64 and cast it to [u8; 8] @@ -181,23 +181,21 @@ impl AccountsDbIndex { // optimisitically try to insert account to index, assuming that it doesn't exist let inserted = - self.accounts - .put_if_not_exists(&mut txn, pubkey, index_value)?; + self.accounts.put_if_not_exists(txn, pubkey, index_value)?; // if the account does exist, then it already occupies space in main storage if !inserted { // in which case we just move the account to a new allocation // adjusting all of the offsets and cleaning up the older ones let previous = - self.reallocate_account(pubkey, &mut txn, &index_value)?; + self.reallocate_account(pubkey, txn, &index_value)?; dealloc.replace(previous); }; // track the account via programs' index as well - self.programs.put(&mut txn, owner, offset_and_pubkey)?; + self.programs.put(txn, owner, offset_and_pubkey)?; // track the reverse relation between account and its owner - self.owners.put(&mut txn, pubkey, owner)?; + self.owners.put(txn, pubkey, owner)?; - txn.commit()?; Ok(dealloc) } @@ -267,9 +265,9 @@ impl AccountsDbIndex { &self, pubkey: &Pubkey, owner: &Pubkey, + txn: &mut RwTransaction, ) -> AccountsDbResult<()> { - let txn = self.env.begin_ro_txn()?; - let old_owner = match self.owners.get(&txn, pubkey)? { + let old_owner = match self.owners.get(txn, pubkey)? { // if current owner matches with that stored in index, then we are all set Some(val) if owner.as_ref() == val => { return Ok(()); @@ -278,23 +276,21 @@ impl AccountsDbIndex { // if they don't match, then we have to remove old entries and create new ones Some(val) => Pubkey::try_from(val).ok(), }; - let allocation = self.get_allocation(&txn, pubkey)?; - let mut txn = self.env.begin_rw_txn()?; + let allocation = self.get_allocation(txn, pubkey)?; // cleanup `programs` and `owners` index self.remove_programs_index_entry( pubkey, old_owner, - &mut txn, + txn, allocation.offset, )?; // track new owner of the account via programs' index let offset_and_pubkey = bytes!(#pack, allocation.offset, Offset, *pubkey, Pubkey); - self.programs.put(&mut txn, owner, offset_and_pubkey)?; + self.programs.put(txn, owner, offset_and_pubkey)?; // track the reverse relation between account and its owner - self.owners.put(&mut txn, pubkey, owner)?; - - txn.commit().map_err(Into::into) + self.owners.put(txn, pubkey, owner)?; + Ok(()) } fn remove_programs_index_entry( @@ -379,9 +375,9 @@ impl AccountsDbIndex { pub(crate) fn try_recycle_allocation( &self, space: Blocks, + txn: &mut RwTransaction, ) -> AccountsDbResult { - let mut txn = self.env.begin_rw_txn()?; - let mut cursor = self.deallocations.cursor_rw(&mut txn)?; + let mut cursor = self.deallocations.cursor_rw(txn)?; // this is a neat lmdb trick where we can search for entry with matching // or greater key since we are interested in any allocation of at least // `blocks` size or greater, this works perfectly well for this case @@ -402,9 +398,6 @@ impl AccountsDbIndex { cursor.put(&remainder.to_le_bytes(), &index_value, WEMPTY)?; } - drop(cursor); - txn.commit()?; - Ok(ExistingAllocation { offset, blocks }) } @@ -438,6 +431,11 @@ impl AccountsDbIndex { }; self.deallocations.entries(&txn) } + + /// Initiate RW Transaction + pub(crate) fn rwtxn(&self) -> lmdb::Result> { + self.env.begin_rw_txn() + } } pub(crate) mod iterator; diff --git a/magicblock-accounts-db/src/index/tests.rs b/magicblock-accounts-db/src/index/tests.rs index 382c965fa..d13caa843 100644 --- a/magicblock-accounts-db/src/index/tests.rs +++ b/magicblock-accounts-db/src/index/tests.rs @@ -9,6 +9,9 @@ use solana_pubkey::Pubkey; use super::{AccountsDbIndex, Allocation}; use crate::error::AccountsDbError; +const INSERT_ACCOUNT_TXN_ERR: &str = + "failed to create transaction for account insertion"; + #[test] fn test_insert_account() { let tenv = setup(); @@ -18,14 +21,18 @@ fn test_insert_account() { allocation, } = tenv.account(); - let result = tenv.insert_account(&pubkey, &owner, allocation); + let mut txn = tenv.env.begin_rw_txn().expect(INSERT_ACCOUNT_TXN_ERR); + let result = tenv.insert_account(&pubkey, &owner, allocation, &mut txn); assert!(result.is_ok(), "failed to insert account into index"); assert!( result.unwrap().is_none(), "new account should not be reallocated" ); + txn.commit().expect("failed to commit transaction"); + let reallocation = tenv.allocation(); - let result = tenv.insert_account(&pubkey, &owner, reallocation); + let mut txn = tenv.env.begin_rw_txn().expect(INSERT_ACCOUNT_TXN_ERR); + let result = tenv.insert_account(&pubkey, &owner, reallocation, &mut txn); assert!(result.is_ok(), "failed to RE-insert account into index"); let previous_allocation = allocation.into(); assert_eq!( @@ -33,6 +40,7 @@ fn test_insert_account() { Some(previous_allocation), "account RE-insertion should return previous allocation" ); + txn.commit().expect("failed to commit transaction"); } #[test] @@ -44,8 +52,10 @@ fn test_get_account_offset() { allocation, } = tenv.account(); - tenv.insert_account(&pubkey, &owner, allocation) + let mut txn = tenv.env.begin_rw_txn().expect(INSERT_ACCOUNT_TXN_ERR); + tenv.insert_account(&pubkey, &owner, allocation, &mut txn) .expect("failed to insert account"); + txn.commit().expect("failed to commit transaction"); let result = tenv.get_account_offset(&pubkey); assert!(result.is_ok(), "failed to read offset for inserted account"); assert_eq!( @@ -81,8 +91,10 @@ fn test_reallocate_account() { allocation, } = tenv.account(); - tenv.insert_account(&pubkey, &owner, allocation) + let mut txn = tenv.env.begin_rw_txn().expect(INSERT_ACCOUNT_TXN_ERR); + tenv.insert_account(&pubkey, &owner, allocation, &mut txn) .expect("failed to insert account"); + txn.commit().expect("failed to commit transaction"); let mut txn = tenv .env @@ -120,8 +132,10 @@ fn test_remove_account() { allocation, } = tenv.account(); - tenv.insert_account(&pubkey, &owner, allocation) + let mut txn = tenv.env.begin_rw_txn().expect(INSERT_ACCOUNT_TXN_ERR); + tenv.insert_account(&pubkey, &owner, allocation, &mut txn) .expect("failed to insert account"); + txn.commit().expect("failed to commit transaction"); let result = tenv.remove_account(&pubkey); @@ -147,8 +161,10 @@ fn test_ensure_correct_owner() { allocation, } = tenv.account(); - tenv.insert_account(&pubkey, &owner, allocation) + let mut txn = tenv.env.begin_rw_txn().expect(INSERT_ACCOUNT_TXN_ERR); + tenv.insert_account(&pubkey, &owner, allocation, &mut txn) .expect("failed to insert account"); + txn.commit().expect("failed to commit transaction"); let iter = tenv.get_program_accounts_iter(&owner); assert!( iter.is_ok(), @@ -168,10 +184,13 @@ fn test_ensure_correct_owner() { drop(iter); let new_owner = Pubkey::new_unique(); + let mut txn = tenv.env.begin_rw_txn().expect(INSERT_ACCOUNT_TXN_ERR); assert!( - tenv.ensure_correct_owner(&pubkey, &new_owner).is_ok(), + tenv.ensure_correct_owner(&pubkey, &new_owner, &mut txn) + .is_ok(), "failed to ensure correct account owner" ); + txn.commit().expect("failed to commit transaction"); let result = tenv.get_program_accounts_iter(&owner); assert!( matches!(result.map(|i| i.count()), Ok(0)), @@ -197,8 +216,10 @@ fn test_program_index_cleanup() { allocation, } = tenv.account(); - tenv.insert_account(&pubkey, &owner, allocation) + let mut txn = tenv.env.begin_rw_txn().expect(INSERT_ACCOUNT_TXN_ERR); + tenv.insert_account(&pubkey, &owner, allocation, &mut txn) .expect("failed to insert account"); + txn.commit().expect("failed to commit transaction"); let mut txn = tenv .env @@ -229,8 +250,10 @@ fn test_recycle_allocation_after_realloc() { allocation, } = tenv.account(); - tenv.insert_account(&pubkey, &owner, allocation) + let mut txn = tenv.env.begin_rw_txn().expect(INSERT_ACCOUNT_TXN_ERR); + tenv.insert_account(&pubkey, &owner, allocation, &mut txn) .expect("failed to insert account"); + txn.commit().expect("failed to commit transaction"); let mut txn = tenv .env @@ -248,21 +271,25 @@ fn test_recycle_allocation_after_realloc() { "the number of deallocations should have increased after account realloc" ); - let result = tenv.try_recycle_allocation(new_allocation.blocks); + let mut txn = tenv.env.begin_rw_txn().expect(INSERT_ACCOUNT_TXN_ERR); + let result = tenv.try_recycle_allocation(new_allocation.blocks, &mut txn); assert_eq!( result.expect("failed to recycle allocation"), allocation.into() ); + txn.commit().expect("failed to commit transaction"); assert_eq!( tenv.get_delloactions_count(), 0, "the number of deallocations should have decreased after recycling" ); - let result = tenv.try_recycle_allocation(new_allocation.blocks); + let mut txn = tenv.env.begin_rw_txn().expect(INSERT_ACCOUNT_TXN_ERR); + let result = tenv.try_recycle_allocation(new_allocation.blocks, &mut txn); assert!( matches!(result, Err(AccountsDbError::NotFound)), "deallocations index should have run out of existing allocations" ); + txn.commit().expect("failed to commit transaction"); tenv.remove_account(&pubkey) .expect("failed to remove account"); assert_eq!( @@ -270,11 +297,13 @@ fn test_recycle_allocation_after_realloc() { 1, "the number of deallocations should have increased after account removal" ); - let result = tenv.try_recycle_allocation(new_allocation.blocks); + let mut txn = tenv.env.begin_rw_txn().expect(INSERT_ACCOUNT_TXN_ERR); + let result = tenv.try_recycle_allocation(new_allocation.blocks, &mut txn); assert_eq!( result.expect("failed to recycle allocation after account removal"), new_allocation.into() ); + txn.commit().expect("failed to commit transaction"); assert_eq!( tenv.get_delloactions_count(), 0, @@ -291,8 +320,10 @@ fn test_recycle_allocation_split() { allocation, } = tenv.account(); - tenv.insert_account(&pubkey, &owner, allocation) + let mut txn = tenv.env.begin_rw_txn().expect(INSERT_ACCOUNT_TXN_ERR); + tenv.insert_account(&pubkey, &owner, allocation, &mut txn) .expect("failed to insert account"); + txn.commit().expect("failed to commit transaction"); tenv.remove_account(&pubkey).unwrap(); assert_eq!( tenv.get_delloactions_count(), @@ -300,27 +331,34 @@ fn test_recycle_allocation_split() { "the number of deallocations should have increased after account removal" ); + let mut txn = tenv.env.begin_rw_txn().expect(INSERT_ACCOUNT_TXN_ERR); let result = tenv - .try_recycle_allocation(allocation.blocks / 2) + .try_recycle_allocation(allocation.blocks / 2, &mut txn) .expect("failed to recycle allocation"); assert_eq!(result.blocks, allocation.blocks / 2); assert_eq!(result.offset, allocation.offset); + txn.commit().expect("failed to commit transaction"); + + let mut txn = tenv.env.begin_rw_txn().expect(INSERT_ACCOUNT_TXN_ERR); let result = tenv - .try_recycle_allocation(allocation.blocks / 2) + .try_recycle_allocation(allocation.blocks / 2, &mut txn) .expect("failed to recycle allocation"); assert_eq!(result.blocks, allocation.blocks / 2); assert!(result.offset > allocation.offset); + txn.commit().expect("failed to commit transaction"); assert_eq!( tenv.get_delloactions_count(), 0, "the number of deallocations should have decreased after recycling" ); - let result = tenv.try_recycle_allocation(allocation.blocks); + let mut txn = tenv.env.begin_rw_txn().expect(INSERT_ACCOUNT_TXN_ERR); + let result = tenv.try_recycle_allocation(allocation.blocks, &mut txn); assert!( matches!(result, Err(AccountsDbError::NotFound)), "deallocations index should have run out of existing allocations" ); + txn.commit().expect("failed to commit transaction"); } #[test] diff --git a/magicblock-accounts-db/src/lib.rs b/magicblock-accounts-db/src/lib.rs index f2dc0e6b7..8a04ec2ca 100644 --- a/magicblock-accounts-db/src/lib.rs +++ b/magicblock-accounts-db/src/lib.rs @@ -4,6 +4,7 @@ use error::AccountsDbError; use index::{ iterator::OffsetPubkeyIter, utils::AccountOffsetFinder, AccountsDbIndex, }; +use lmdb::{RwTransaction, Transaction}; use log::{error, warn}; use magicblock_config::config::AccountsDbConfig; use magicblock_core::traits::AccountsBank; @@ -88,7 +89,20 @@ impl AccountsDb { /// Insert account with given pubkey into the database /// Note: this method removes zero lamport account from database - pub fn insert_account(&self, pubkey: &Pubkey, account: &AccountSharedData) { + pub fn insert_account( + &self, + pubkey: &Pubkey, + account: &AccountSharedData, + ) -> AccountsDbResult<()> { + let mut txn = Option::::None; + macro_rules! txn { + () => { + match txn.as_mut() { + Some(t) => t, + None => txn.insert(self.index.rwtxn()?), + } + }; + } // NOTE: we don't check for non-zero lamports since we allow to store zero-lamport accounts // for the following two cases: // - when we clone a compressed account we reflect the exact lamports it has which maybe @@ -97,23 +111,22 @@ impl AccountsDb { // find it, i.e. in the case of an escrow account to avoid doing that over and over match account { AccountSharedData::Borrowed(acc) => { - // For borrowed variants everything is already written and we just increment the - // atomic counter. New readers will see the latest update. - acc.commit(); // check whether the account's owner has changed - if !acc.owner_changed() { - return; + if acc.owner_changed() { + self.index + .ensure_correct_owner(pubkey, account.owner(), txn!()) + .inspect_err(log_err!( + "failed to ensure correct account owner for {}", + pubkey + ))?; } // and perform some index bookkeeping to ensure a correct owner - let _ = self - .index - .ensure_correct_owner(pubkey, account.owner()) - .inspect_err(log_err!( - "failed to ensure correct account owner for {}", - pubkey - )); + // For borrowed variants everything is already written and we just increment the + // atomic counter. New readers will see the latest update. + acc.commit(); } AccountSharedData::Owned(acc) => { + let txn = txn!(); let datalen = account.data().len() as u32; let block_size = self.storage.block_size() as u32; let size = AccountSharedData::serialized_size_aligned( @@ -123,7 +136,9 @@ impl AccountsDb { let blocks = self.storage.get_block_count(size); // TODO(bmuddha) perf optimization: use reallocs sparringly // https://github.com/magicblock-labs/magicblock-validator/issues/327 - let allocation = match self.index.try_recycle_allocation(blocks) + let allocation = match self + .index + .try_recycle_allocation(blocks, txn) { // if we could recycle some "hole" in the database, use it Ok(recycled) => { @@ -136,10 +151,19 @@ impl AccountsDb { Err(err) => { // This can only happen if we have catastrophic system mulfunction error!("failed to insert account, index allocation check error: {err}"); - return; + return Err(err); } }; + // update accounts index + let dealloc = self + .index + .insert_account(pubkey, account.owner(), allocation, txn) + .inspect_err(log_err!("account index insertion"))?; + if let Some(dealloc) = dealloc { + // bookkeeping for deallocated (free hole) space + self.storage.increment_deallocations(dealloc.blocks); + } // SAFETY: // Allocation object is constructed by obtaining a valid offset from storage, which // is unoccupied by other accounts, points to valid memory within mmap and is @@ -151,19 +175,136 @@ impl AccountsDb { block_size * allocation.blocks, ) }; - // update accounts index - let dealloc = self - .index - .insert_account(pubkey, account.owner(), allocation) - .inspect_err(log_err!("account index insertion")) - .ok() - .flatten(); - if let Some(dealloc) = dealloc { - // bookkeeping for deallocated (free hole) space - self.storage.increment_deallocations(dealloc.blocks); + } + } + if let Some(txn) = txn { + txn.commit()?; + } + Ok(()) + } + + pub fn insert_batch<'a>( + &self, + accounts: impl Iterator + Clone, + ) -> AccountsDbResult<()> { + let mut txn = Option::::None; + macro_rules! txn { + () => { + match txn.as_mut() { + Some(t) => t, + None => txn.insert(self.index.rwtxn()?), + } + }; + } + let mut error = Option::::None; + macro_rules! break_error { + ($error: expr, $msg: expr) => { + error!($msg, $error); + error.replace($error); + break; + }; + } + + let mut commited = 0; + for (pubkey, account) in accounts.clone() { + match account { + AccountSharedData::Borrowed(acc) => { + // check whether the account's owner has changed + if acc.owner_changed() { + if let Err(err) = self.index.ensure_correct_owner( + pubkey, + account.owner(), + txn!(), + ) { + break_error!(err, "account owner index update: {}"); + } + } + // and perform some index bookkeeping to ensure a correct owner + // For borrowed variants everything is already written and we just increment the + // atomic counter. New readers will see the latest update. + acc.commit(); + } + AccountSharedData::Owned(acc) => { + let txn = txn!(); + let datalen = account.data().len() as u32; + let block_size = self.storage.block_size() as u32; + let size = AccountSharedData::serialized_size_aligned( + datalen, block_size, + ) as usize; + + let blocks = self.storage.get_block_count(size); + // TODO(bmuddha) perf optimization: use reallocs sparringly + // https://github.com/magicblock-labs/magicblock-validator/issues/327 + let allocation = match self + .index + .try_recycle_allocation(blocks, txn) + { + // if we could recycle some "hole" in the database, use it + Ok(recycled) => { + // bookkeeping for the deallocated (free hole) space + self.storage + .decrement_deallocations(recycled.blocks); + self.storage.recycle(recycled) + } + // otherwise allocate from the end of memory map + Err(AccountsDbError::NotFound) => { + self.storage.alloc(size) + } + Err(err) => { + // This can only happen if we have catastrophic system mulfunction + break_error!(err, "failed to insert account, index allocation check error: {}"); + } + }; + + // update accounts index + let result = self.index.insert_account( + pubkey, + account.owner(), + allocation, + txn, + ); + match result { + Ok(Some(dealloc)) => { + // bookkeeping for deallocated (free hole) space + self.storage + .increment_deallocations(dealloc.blocks); + } + Ok(None) => (), + Err(err) => { + break_error!( + err, + "account index insertion failed: {}" + ); + } + } + // SAFETY: + // Allocation object is constructed by obtaining a valid offset from storage, which + // is unoccupied by other accounts, points to valid memory within mmap and is + // properly aligned to 8 bytes, so the contract of serialize_to_mmap is satisfied + unsafe { + AccountSharedData::serialize_to_mmap( + acc, + allocation.storage.as_ptr(), + block_size * allocation.blocks, + ) + }; } } + commited += 1; + } + if let Some(error) = error { + for (_, account) in accounts.take(commited) { + // # Safety + // we are only rolling back account which we have just committed, + // thus it is guaranteed that the rollback buffer is initialized + unsafe { account.rollback() }; + } + return Err(error); + } + if let Some(txn) = txn { + txn.commit()?; } + Ok(()) } /// Check whether given account is owned by any of the programs in the provided list diff --git a/magicblock-accounts-db/src/storage.rs b/magicblock-accounts-db/src/storage.rs index 0dd1851b7..2dee0b7f1 100644 --- a/magicblock-accounts-db/src/storage.rs +++ b/magicblock-accounts-db/src/storage.rs @@ -399,7 +399,7 @@ fn calculate_db_size(config: &AccountsDbConfig) -> usize { (block_num + meta_blocks) * block_size } -#[cfg_attr(test, derive(Clone, Copy))] +#[derive(Clone, Copy)] pub(crate) struct Allocation { pub(crate) storage: NonNull, pub(crate) offset: Offset, diff --git a/magicblock-accounts-db/src/tests.rs b/magicblock-accounts-db/src/tests.rs index 7e8226894..90aae2936 100644 --- a/magicblock-accounts-db/src/tests.rs +++ b/magicblock-accounts-db/src/tests.rs @@ -53,7 +53,8 @@ fn test_modify_account() { LAMPORTS, "account from the main buffer should not be affected" ); - tenv.insert_account(&pubkey, &uncommitted); + tenv.insert_account(&pubkey, &uncommitted) + .expect("failed to insert account"); committed = tenv .get_account(&pubkey) @@ -96,7 +97,8 @@ fn test_account_resize() { "uncommitted account data len should not have changed" ); - tenv.insert_account(&pubkey, &uncommitted); + tenv.insert_account(&pubkey, &uncommitted) + .expect("failed to insert account"); committed = tenv .get_account(&pubkey) @@ -121,7 +123,8 @@ fn test_alloc_reuse() { let old_addr = acc1.data().as_ptr(); acc1.set_data_from_slice(&huge_data); - tenv.insert_account(&pubkey, &acc1); + tenv.insert_account(&pubkey, &acc1) + .expect("failed to insert account"); let AccountWithPubkey { account: acc2, .. } = tenv.account(); @@ -146,16 +149,19 @@ fn test_larger_alloc_reuse() { let mut huge_data = vec![42; SPACE * 2]; acc.account.set_data_from_slice(&huge_data); - tenv.insert_account(&acc.pubkey, &acc.account); + tenv.insert_account(&acc.pubkey, &acc.account) + .expect("failed to insert account"); let mut acc2 = tenv.account(); acc2.account.set_data_from_slice(&huge_data); - tenv.insert_account(&acc2.pubkey, &acc2.account); + tenv.insert_account(&acc2.pubkey, &acc2.account) + .expect("failed to insert account"); let mut acc3 = tenv.account(); huge_data = vec![42; SPACE * 4]; acc3.account.set_data_from_slice(&huge_data); - tenv.insert_account(&acc3.pubkey, &acc3.account); + tenv.insert_account(&acc3.pubkey, &acc3.account) + .expect("failed to insert account"); acc3.account = tenv .get_account(&acc3.pubkey) .expect("third account should be in database"); @@ -163,12 +169,14 @@ fn test_larger_alloc_reuse() { let alloc_addr = acc3.account.data().as_ptr(); huge_data = vec![42; SPACE * 5]; acc3.account.set_data_from_slice(&huge_data); - tenv.insert_account(&acc3.pubkey, &acc3.account); + tenv.insert_account(&acc3.pubkey, &acc3.account) + .expect("failed to insert account"); let mut acc4 = tenv.account(); huge_data = vec![42; SPACE * 3]; acc4.account.set_data_from_slice(&huge_data); - tenv.insert_account(&acc4.pubkey, &acc4.account); + tenv.insert_account(&acc4.pubkey, &acc4.account) + .expect("failed to insert account"); acc4.account = tenv .get_account(&acc4.pubkey) .expect("fourth account should be in database"); @@ -206,10 +214,12 @@ fn test_get_all_accounts() { let mut pubkeys = HashSet::new(); pubkeys.insert(acc.pubkey); let acc2 = tenv.account(); - tenv.insert_account(&acc2.pubkey, &acc2.account); + tenv.insert_account(&acc2.pubkey, &acc2.account) + .expect("failed to insert account"); pubkeys.insert(acc2.pubkey); let acc3 = tenv.account(); - tenv.insert_account(&acc3.pubkey, &acc3.account); + tenv.insert_account(&acc3.pubkey, &acc3.account) + .expect("failed to insert account"); pubkeys.insert(acc3.pubkey); let mut pks = tenv.iter_all(); @@ -246,7 +256,8 @@ fn test_take_snapshot() { ); acc.account.set_data(ACCOUNT_DATA.to_vec()); - tenv.insert_account(&acc.pubkey, &acc.account); + tenv.insert_account(&acc.pubkey, &acc.account) + .expect("failed to insert account"); tenv.set_slot(2 * tenv.snapshot_frequency); assert!( @@ -264,7 +275,8 @@ fn test_restore_from_snapshot() { tenv.set_slot(tenv.snapshot_frequency); // trigger snapshot tenv.set_slot(tenv.snapshot_frequency + 1); acc.account.set_lamports(new_lamports); - tenv.insert_account(&acc.pubkey, &acc.account); + tenv.insert_account(&acc.pubkey, &acc.account) + .expect("failed to insert account"); let acc_committed = tenv .get_account(&acc.pubkey) @@ -302,7 +314,8 @@ fn test_get_all_accounts_after_rollback() { const ITERS: u64 = 1024; for i in 0..=ITERS { let acc = tenv.account(); - tenv.insert_account(&acc.pubkey, &acc.account); + tenv.insert_account(&acc.pubkey, &acc.account) + .expect("failed to insert account"); pks.push(acc.pubkey); tenv.set_slot(i); } @@ -310,7 +323,8 @@ fn test_get_all_accounts_after_rollback() { let mut post_snap_pks = vec![]; for i in ITERS..ITERS + tenv.snapshot_frequency { let acc = tenv.account(); - tenv.insert_account(&acc.pubkey, &acc.account); + tenv.insert_account(&acc.pubkey, &acc.account) + .expect("failed to insert account"); tenv.set_slot(i + 1); post_snap_pks.push(acc.pubkey); } @@ -349,7 +363,8 @@ fn test_db_size_after_rollback() { let last_slot = 512; for i in 0..=last_slot { let acc = tenv.account(); - tenv.insert_account(&acc.pubkey, &acc.account); + tenv.insert_account(&acc.pubkey, &acc.account) + .expect("failed to insert account"); tenv.set_slot(i); } let pre_rollback_db_size = tenv.storage_size(); @@ -391,7 +406,8 @@ fn test_zero_lamports_account() { acc.account.set_lamports(0); - tenv.insert_account(&pk, &acc.account); + tenv.insert_account(&pk, &acc.account) + .expect("failed to insert account"); // NOTE: we use empty accounts to mark escrow accounts that were not found on chain let retained_account = tenv.get_account(&pk); @@ -421,7 +437,8 @@ fn test_owner_change() { } let new_owner = Pubkey::new_unique(); acc.account.set_owner(new_owner); - tenv.insert_account(&acc.pubkey, &acc.account); + tenv.insert_account(&acc.pubkey, &acc.account) + .expect("failed to insert account"); let result = tenv.account_matches_owners(&acc.pubkey, &[OWNER]); assert!(result.is_none()); let result = tenv.get_program_accounts(&OWNER, |_| true); @@ -443,7 +460,8 @@ fn test_account_too_many_accounts() { let acc = tenv.account(); let mut oversized_account = acc.account; oversized_account.extend_from_slice(&[42; 9_000_000]); - tenv.insert_account(&acc.pubkey, &oversized_account); + tenv.insert_account(&acc.pubkey, &oversized_account) + .expect("failed to insert account"); } } @@ -455,7 +473,8 @@ fn test_account_shrinking() { // ============================================== // test set_data acc1.account.set_data(b"".to_vec()); - tenv.insert_account(&acc1.pubkey, &acc1.account); + tenv.insert_account(&acc1.pubkey, &acc1.account) + .expect("failed to insert account"); acc1.account = tenv .get_account(&acc1.pubkey) .expect("account should be inserted"); @@ -468,7 +487,8 @@ fn test_account_shrinking() { // ============================================== // test set_data_from_slice let mut acc2 = tenv.account(); - tenv.insert_account(&acc2.pubkey, &acc2.account); + tenv.insert_account(&acc2.pubkey, &acc2.account) + .expect("failed to insert account"); acc2.account = tenv .get_account(&acc2.pubkey) @@ -476,7 +496,8 @@ fn test_account_shrinking() { acc2.account.set_data_from_slice(b""); - tenv.insert_account(&acc2.pubkey, &acc2.account); + tenv.insert_account(&acc2.pubkey, &acc2.account) + .expect("failed to insert account"); acc2.account = tenv .get_account(&acc2.pubkey) .expect("account should be inserted"); @@ -489,7 +510,8 @@ fn test_account_shrinking() { // ============================================== // test set_data_from_slice let mut acc3 = tenv.account(); - tenv.insert_account(&acc3.pubkey, &acc3.account); + tenv.insert_account(&acc3.pubkey, &acc3.account) + .expect("failed to insert account"); acc3.account = tenv .get_account(&acc3.pubkey) @@ -497,7 +519,8 @@ fn test_account_shrinking() { acc3.account.resize(0, 0); - tenv.insert_account(&acc3.pubkey, &acc3.account); + tenv.insert_account(&acc3.pubkey, &acc3.account) + .expect("failed to insert account"); acc3.account = tenv .get_account(&acc3.pubkey) .expect("account should be inserted"); @@ -520,7 +543,8 @@ fn test_many_insertions_to_accountsdb() { for _ in 0..ACCOUNTNUM { let acc = tenv.account(); pubkeys.push(acc.pubkey); - tenv.insert_account(&acc.pubkey, &acc.account); + tenv.insert_account(&acc.pubkey, &acc.account) + .expect("failed to insert account"); } // test whether frequent account reallocations effectively reuse free // space in database without overflowing the database boundaries (100MB for test) @@ -537,7 +561,9 @@ fn test_many_insertions_to_accountsdb() { .expect("account should be in database"); account .set_data_from_slice(&vec![43; i % (SPACE * 20) + 13]); - tenv_arc.insert_account(pk, &account); + tenv_arc + .insert_account(pk, &account) + .expect("failed to insert account"); } }); } @@ -568,7 +594,8 @@ fn test_database_reset() { let pubkey = Pubkey::new_unique(); let account = AccountSharedData::new(LAMPORTS, SPACE, &OWNER); - adb.insert_account(&pubkey, &account); + adb.insert_account(&pubkey, &account) + .expect("failed to insert account"); assert!( adb.get_account(&pubkey).is_some(), "Account should exist before reset" @@ -646,7 +673,9 @@ impl AdbTestEnv { let mut account = AccountSharedData::new(LAMPORTS, size, &OWNER); account.data_as_mut_slice()[..INIT_DATA_LEN] .copy_from_slice(ACCOUNT_DATA); - self.adb.insert_account(&pubkey, &account); + self.adb + .insert_account(&pubkey, &account) + .expect("failed to insert account"); let account = self .get_account(&pubkey) .expect("failed to refetch newly inserted account"); diff --git a/magicblock-api/src/fund_account.rs b/magicblock-api/src/fund_account.rs index 9e3fa1284..0b392f285 100644 --- a/magicblock-api/src/fund_account.rs +++ b/magicblock-api/src/fund_account.rs @@ -35,7 +35,7 @@ pub(crate) fn fund_account_with_data( } else { AccountSharedData::new(lamports, size, &Default::default()) }; - accountsdb.insert_account(pubkey, &account); + let _ = accountsdb.insert_account(pubkey, &account); } pub(crate) fn init_validator_identity( @@ -45,7 +45,7 @@ pub(crate) fn init_validator_identity( fund_account(accountsdb, validator_id, u64::MAX / 2); let mut authority = accountsdb.get_account(validator_id).unwrap(); authority.as_borrowed_mut().unwrap().set_privileged(true); - accountsdb.insert_account(validator_id, &authority); + let _ = accountsdb.insert_account(validator_id, &authority); } /// Funds the faucet account. @@ -80,6 +80,6 @@ pub(crate) fn fund_magic_context(accountsdb: &AccountsDb) { .get_account(&magic_program::MAGIC_CONTEXT_PUBKEY) .unwrap(); magic_context.set_delegated(true); - accountsdb + let _ = accountsdb .insert_account(&magic_program::MAGIC_CONTEXT_PUBKEY, &magic_context); } diff --git a/magicblock-api/src/magic_validator.rs b/magicblock-api/src/magic_validator.rs index 31aa663f2..7c99c22a6 100644 --- a/magicblock-api/src/magic_validator.rs +++ b/magicblock-api/src/magic_validator.rs @@ -157,7 +157,7 @@ impl MagicValidator { let accountsdb = AccountsDb::new(&config.accountsdb, &config.storage, last_slot)?; for (pubkey, account) in genesis_config.accounts { - accountsdb.insert_account(&pubkey, &account.into()); + let _ = accountsdb.insert_account(&pubkey, &account.into()); } let exit = Arc::::default(); diff --git a/magicblock-processor/src/executor/callback.rs b/magicblock-processor/src/executor/callback.rs index 7aadd425d..a34a495d5 100644 --- a/magicblock-processor/src/executor/callback.rs +++ b/magicblock-processor/src/executor/callback.rs @@ -36,7 +36,7 @@ impl TransactionProcessingCallback for super::TransactionExecutor { AccountSharedData::new(1, name.len(), &native_loader::id()); account.set_data_from_slice(name.as_bytes()); account.set_executable(true); - self.accountsdb.insert_account(program_id, &account); + let _ = self.accountsdb.insert_account(program_id, &account); } fn calculate_fee( diff --git a/magicblock-processor/src/executor/processing.rs b/magicblock-processor/src/executor/processing.rs index c0c8afcfe..886eca47c 100644 --- a/magicblock-processor/src/executor/processing.rs +++ b/magicblock-processor/src/executor/processing.rs @@ -1,4 +1,5 @@ use log::*; +use magicblock_accounts_db::AccountsDbResult; use magicblock_core::{ link::{ accounts::{AccountWithSlot, LockedAccount}, @@ -12,7 +13,6 @@ use magicblock_core::{ use magicblock_metrics::metrics::{ FAILED_TRANSACTIONS_COUNT, TRANSACTION_COUNT, }; -use solana_account::ReadableAccount; use solana_pubkey::Pubkey; use solana_svm::{ account_loader::{AccountsBalances, CheckedTransactionDetails}, @@ -61,7 +61,7 @@ impl super::TransactionExecutor { // Transaction failed to load, we persist it to the // ledger, only for the convenience of the user let status = Err(err); - self.commit_failed_transaction(txn, status.clone()); + self.commit_failed_transaction(txn, status.clone(), None); FAILED_TRANSACTIONS_COUNT.inc(); tx.map(|tx| tx.send(status)); // NOTE: @@ -76,7 +76,23 @@ impl super::TransactionExecutor { // Failed transactions still pay fees, so we need to // commit the accounts even if the transaction failed let feepayer = *txn.fee_payer(); - self.commit_accounts(feepayer, &processed, is_replay); + if let Err(err) = self.commit_accounts(feepayer, &processed, is_replay) + { + let error = Err(TransactionError::CommitCancelled); + // Transaction failed to load, we persist it to the + // ledger, only for the convenience of the user + self.commit_failed_transaction( + txn, + error.clone(), + Some(vec![err.to_string()]), + ); + FAILED_TRANSACTIONS_COUNT.inc(); + tx.map(|tx| tx.send(error)); + // NOTE: + // Transactions that failed to load, cannot have touched the thread + // local storage, thus there's no need to clear it before returning + return; + } let result = processed.status(); if result.is_ok() && !is_replay { @@ -254,11 +270,13 @@ impl super::TransactionExecutor { &self, txn: SanitizedTransaction, status: TransactionResult<()>, + logs: Option>, ) { let meta = TransactionStatusMeta { status, pre_balances: vec![0; txn.message().account_keys().len()], post_balances: vec![0; txn.message().account_keys().len()], + log_messages: logs, ..Default::default() }; let signature = *txn.signature(); @@ -278,7 +296,7 @@ impl super::TransactionExecutor { feepayer: Pubkey, result: &ProcessedTransaction, is_replay: bool, - ) { + ) -> AccountsDbResult<()> { let succeeded = result.status().is_ok(); let accounts = match result { ProcessedTransaction::Executed(executed) => { @@ -301,7 +319,7 @@ impl super::TransactionExecutor { let RollbackAccounts::FeePayerOnly { fee_payer_account } = &fo.rollback_accounts else { - return; + return Ok(()); }; &[(feepayer, fee_payer_account.clone())] } @@ -314,29 +332,29 @@ impl super::TransactionExecutor { .map(|feepayer| feepayer.1.privileged()) .unwrap_or_default(); + // only persist account's update if it was actually modified, ignore + // the rest, even if an account was writeable in the transaction. + // + // We also don't persist accounts that are empty, with an exception + // for special cases, when those are inserted forcefully as placeholders + // (for example by the chainlink), those cases can be distinguished from + // others by the fact that such a transaction is always running in a + // privileged mode. + let to_commit = accounts + .iter() + .filter(|(_, acc)| acc.is_dirty() || privileged); + self.accountsdb.insert_batch(to_commit)?; + if is_replay { + return Ok(()); + } for (pubkey, account) in accounts { - // only persist account's update if it was actually modified, ignore - // the rest, even if an account was writeable in the transaction. - // - // We also don't persist accounts that are empty, with an exception - // for special cases, when those are inserted forcefully as placeholders - // (for example by the chainlink), those cases can be distinguished from - // others by the fact that such a transaction is always running in a - // privileged mode. - if !account.is_dirty() || (account.lamports() == 0 && !privileged) { - continue; - } - self.accountsdb.insert_account(pubkey, account); - - if is_replay { - continue; - } let account = AccountWithSlot { slot: self.processor.slot, account: LockedAccount::new(*pubkey, account.clone()), }; let _ = self.accounts_tx.send(account); } + Ok(()) } /// Ensure that no post execution account state violations occurred: diff --git a/magicblock-processor/src/lib.rs b/magicblock-processor/src/lib.rs index 4ab98b39b..8247d9fdf 100644 --- a/magicblock-processor/src/lib.rs +++ b/magicblock-processor/src/lib.rs @@ -41,7 +41,7 @@ pub fn build_svm_env( else { continue; }; - accountsdb.insert_account(feature_id, &account); + let _ = accountsdb.insert_account(feature_id, &account); } // We have a static rent which is setup once at startup, diff --git a/magicblock-processor/src/loader.rs b/magicblock-processor/src/loader.rs index bad775bb5..f758c7d1f 100644 --- a/magicblock-processor/src/loader.rs +++ b/magicblock-processor/src/loader.rs @@ -54,7 +54,8 @@ impl TransactionSchedulerState { &UPGRADEABLE_LOADER_ID, ); data_account.set_data(data); - self.accountsdb + let _ = self + .accountsdb .insert_account(&programdata_address, &data_account); // 2. Create and store the executable Program account. @@ -70,7 +71,7 @@ impl TransactionSchedulerState { ); exec_account_data.set_data(exec_bytes); exec_account_data.set_executable(true); - self.accountsdb.insert_account(id, &exec_account_data); + let _ = self.accountsdb.insert_account(id, &exec_account_data); Ok(()) } diff --git a/magicblock-processor/src/scheduler/state.rs b/magicblock-processor/src/scheduler/state.rs index 34423c345..c1bdd59ef 100644 --- a/magicblock-processor/src/scheduler/state.rs +++ b/magicblock-processor/src/scheduler/state.rs @@ -99,13 +99,14 @@ impl TransactionSchedulerState { if !accountsdb.contains_account(&sysvar::clock::ID) { let clock = AccountSharedData::new_data(1, &block.clock, owner); if let Ok(acc) = clock { - accountsdb.insert_account(&sysvar::clock::ID, &acc); + let _ = accountsdb.insert_account(&sysvar::clock::ID, &acc); } } if !accountsdb.contains_account(&sysvar::slot_hashes::ID) { let sh = SlotHashes::new(&[(block.slot, block.blockhash)]); if let Ok(acc) = AccountSharedData::new_data(1, &sh, owner) { - accountsdb.insert_account(&sysvar::slot_hashes::ID, &acc); + let _ = + accountsdb.insert_account(&sysvar::slot_hashes::ID, &acc); } } @@ -113,7 +114,8 @@ impl TransactionSchedulerState { if !accountsdb.contains_account(&sysvar::epoch_schedule::ID) { let es = EpochSchedule::new(DEFAULT_SLOTS_PER_EPOCH); if let Ok(acc) = AccountSharedData::new_data(1, &es, owner) { - accountsdb.insert_account(&sysvar::epoch_schedule::ID, &acc); + let _ = accountsdb + .insert_account(&sysvar::epoch_schedule::ID, &acc); } } if !accountsdb.contains_account(&sysvar::rent::ID) { @@ -126,7 +128,7 @@ impl TransactionSchedulerState { AccountSharedData::new_data(1, rent, owner).ok() }); if let Some(acc) = account { - accountsdb.insert_account(&sysvar::rent::ID, &acc); + let _ = accountsdb.insert_account(&sysvar::rent::ID, &acc); } } } diff --git a/magicblock-processor/tests/replay.rs b/magicblock-processor/tests/replay.rs index a487e6ab6..da2efd8d3 100644 --- a/magicblock-processor/tests/replay.rs +++ b/magicblock-processor/tests/replay.rs @@ -58,7 +58,7 @@ async fn create_transaction_in_ledger( // Revert accounts to their previous state to simulate `AccountsDb` being behind the ledger. for (pubkey, acc) in &pre_account_states { - env.accountsdb.insert_account(pubkey, acc); + let _ = env.accountsdb.insert_account(pubkey, acc); } // Confirm the transaction is in the ledger and retrieve it. diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index f769b03b6..58baee9b2 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -2231,10 +2231,10 @@ dependencies = [ [[package]] name = "guinea" -version = "0.5.1" +version = "0.5.2" dependencies = [ "bincode", - "magicblock-magic-program-api 0.5.1", + "magicblock-magic-program-api 0.5.2", "serde", "solana-program", ] @@ -3260,7 +3260,7 @@ dependencies = [ [[package]] name = "magicblock-account-cloner" -version = "0.5.1" +version = "0.5.2" dependencies = [ "async-trait", "bincode", @@ -3271,7 +3271,7 @@ dependencies = [ "magicblock-config", "magicblock-core", "magicblock-ledger", - "magicblock-magic-program-api 0.5.1", + "magicblock-magic-program-api 0.5.2", "magicblock-program", "magicblock-rpc-client", "rand 0.9.2", @@ -3292,7 +3292,7 @@ dependencies = [ [[package]] name = "magicblock-accounts" -version = "0.5.1" +version = "0.5.2" dependencies = [ "async-trait", "log", @@ -3314,7 +3314,7 @@ dependencies = [ [[package]] name = "magicblock-accounts-db" -version = "0.5.1" +version = "0.5.2" dependencies = [ "lmdb-rkv", "log", @@ -3330,7 +3330,7 @@ dependencies = [ [[package]] name = "magicblock-aperture" -version = "0.5.1" +version = "0.5.2" dependencies = [ "arc-swap", "base64 0.21.7", @@ -3375,7 +3375,7 @@ dependencies = [ [[package]] name = "magicblock-api" -version = "0.5.1" +version = "0.5.2" dependencies = [ "anyhow", "borsh 1.6.0", @@ -3391,7 +3391,7 @@ dependencies = [ "magicblock-config", "magicblock-core", "magicblock-ledger", - "magicblock-magic-program-api 0.5.1", + "magicblock-magic-program-api 0.5.2", "magicblock-metrics", "magicblock-processor", "magicblock-program", @@ -3430,7 +3430,7 @@ dependencies = [ [[package]] name = "magicblock-chainlink" -version = "0.5.1" +version = "0.5.2" dependencies = [ "arc-swap", "async-trait", @@ -3443,7 +3443,7 @@ dependencies = [ "magicblock-config", "magicblock-core", "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=3edb41022)", - "magicblock-magic-program-api 0.5.1", + "magicblock-magic-program-api 0.5.2", "magicblock-metrics", "solana-account", "solana-account-decoder", @@ -3481,7 +3481,7 @@ dependencies = [ [[package]] name = "magicblock-committor-program" -version = "0.5.1" +version = "0.5.2" dependencies = [ "borsh 1.6.0", "paste", @@ -3493,7 +3493,7 @@ dependencies = [ [[package]] name = "magicblock-committor-service" -version = "0.5.1" +version = "0.5.2" dependencies = [ "async-trait", "base64 0.21.7", @@ -3536,7 +3536,7 @@ dependencies = [ [[package]] name = "magicblock-config" -version = "0.5.1" +version = "0.5.2" dependencies = [ "clap", "derive_more", @@ -3554,10 +3554,10 @@ dependencies = [ [[package]] name = "magicblock-core" -version = "0.5.1" +version = "0.5.2" dependencies = [ "flume", - "magicblock-magic-program-api 0.5.1", + "magicblock-magic-program-api 0.5.2", "solana-account", "solana-account-decoder", "solana-hash", @@ -3609,7 +3609,7 @@ dependencies = [ [[package]] name = "magicblock-ledger" -version = "0.5.1" +version = "0.5.2" dependencies = [ "arc-swap", "bincode", @@ -3659,7 +3659,7 @@ dependencies = [ [[package]] name = "magicblock-magic-program-api" -version = "0.5.1" +version = "0.5.2" dependencies = [ "bincode", "serde", @@ -3668,7 +3668,7 @@ dependencies = [ [[package]] name = "magicblock-metrics" -version = "0.5.1" +version = "0.5.2" dependencies = [ "http-body-util", "hyper 1.8.1", @@ -3682,7 +3682,7 @@ dependencies = [ [[package]] name = "magicblock-processor" -version = "0.5.1" +version = "0.5.2" dependencies = [ "bincode", "log", @@ -3717,12 +3717,12 @@ dependencies = [ [[package]] name = "magicblock-program" -version = "0.5.1" +version = "0.5.2" dependencies = [ "bincode", "lazy_static", "magicblock-core", - "magicblock-magic-program-api 0.5.1", + "magicblock-magic-program-api 0.5.2", "num-derive", "num-traits", "parking_lot", @@ -3749,7 +3749,7 @@ dependencies = [ [[package]] name = "magicblock-rpc-client" -version = "0.5.1" +version = "0.5.2" dependencies = [ "log", "solana-account", @@ -3770,7 +3770,7 @@ dependencies = [ [[package]] name = "magicblock-table-mania" -version = "0.5.1" +version = "0.5.2" dependencies = [ "ed25519-dalek", "log", @@ -3796,7 +3796,7 @@ dependencies = [ [[package]] name = "magicblock-task-scheduler" -version = "0.5.1" +version = "0.5.2" dependencies = [ "bincode", "chrono", @@ -3823,7 +3823,7 @@ dependencies = [ [[package]] name = "magicblock-validator-admin" -version = "0.5.1" +version = "0.5.2" dependencies = [ "log", "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=3edb41022)", @@ -3840,7 +3840,7 @@ dependencies = [ [[package]] name = "magicblock-version" -version = "0.5.1" +version = "0.5.2" dependencies = [ "git-version", "rustc_version", @@ -4749,7 +4749,7 @@ dependencies = [ "bincode", "borsh 1.6.0", "ephemeral-rollups-sdk", - "magicblock-magic-program-api 0.5.1", + "magicblock-magic-program-api 0.5.2", "serde", "solana-program", ] @@ -4773,7 +4773,7 @@ dependencies = [ "borsh 1.6.0", "ephemeral-rollups-sdk", "magicblock-delegation-program 1.1.3 (git+https://github.com/magicblock-labs/delegation-program.git?rev=3edb41022)", - "magicblock-magic-program-api 0.5.1", + "magicblock-magic-program-api 0.5.2", "rkyv 0.7.45", "solana-program", "static_assertions", @@ -5808,7 +5808,7 @@ dependencies = [ "integration-test-tools", "log", "magicblock-core", - "magicblock-magic-program-api 0.5.1", + "magicblock-magic-program-api 0.5.2", "program-schedulecommit", "rand 0.8.5", "schedulecommit-client", @@ -5825,7 +5825,7 @@ version = "0.0.0" dependencies = [ "integration-test-tools", "magicblock-core", - "magicblock-magic-program-api 0.5.1", + "magicblock-magic-program-api 0.5.2", "program-schedulecommit", "program-schedulecommit-security", "schedulecommit-client", @@ -6226,7 +6226,7 @@ dependencies = [ [[package]] name = "solana-account" version = "2.2.1" -source = "git+https://github.com/magicblock-labs/solana-account.git?rev=57158728#571587284a525b66666291aee5174783139a1595" +source = "git+https://github.com/magicblock-labs/solana-account.git?rev=2246929#2246929c6614f60d9909fdd117aab3bc454a9775" dependencies = [ "bincode", "qualifier_attr", @@ -8544,7 +8544,7 @@ dependencies = [ [[package]] name = "solana-storage-proto" -version = "0.5.1" +version = "0.5.2" dependencies = [ "bincode", "bs58", @@ -10045,7 +10045,7 @@ dependencies = [ [[package]] name = "test-kit" -version = "0.5.1" +version = "0.5.2" dependencies = [ "env_logger 0.11.8", "guinea", diff --git a/test-integration/Cargo.toml b/test-integration/Cargo.toml index 61eb27ba0..4b08d2730 100644 --- a/test-integration/Cargo.toml +++ b/test-integration/Cargo.toml @@ -36,7 +36,9 @@ chrono = "0.4" cleanass = "0.0.1" color-backtrace = { version = "0.7" } ctrlc = "3.4.7" -ephemeral-rollups-sdk = { git = "https://github.com/magicblock-labs/ephemeral-rollups-sdk.git", rev = "36f9485", default-features = false, features = ["modular-sdk"] } +ephemeral-rollups-sdk = { git = "https://github.com/magicblock-labs/ephemeral-rollups-sdk.git", rev = "36f9485", default-features = false, features = [ + "modular-sdk", +] } futures = "0.3.31" integration-test-tools = { path = "test-tools" } isocountry = "0.3.2" @@ -55,9 +57,11 @@ magicblock-committor-program = { path = "../magicblock-committor-program", featu magicblock-committor-service = { path = "../magicblock-committor-service" } magicblock-config = { path = "../magicblock-config" } magicblock-core = { path = "../magicblock-core" } -magic-domain-program = { git = "https://github.com/magicblock-labs/magic-domain-program.git", rev = "cffcfeb", default-features = false, features = ["modular-sdk"] } +magic-domain-program = { git = "https://github.com/magicblock-labs/magic-domain-program.git", rev = "cffcfeb", default-features = false, features = [ + "modular-sdk", +] } magicblock_magic_program_api = { package = "magicblock-magic-program-api", path = "../magicblock-magic-program-api" } -magicblock-delegation-program = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "3edb41022" , features = [ +magicblock-delegation-program = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "3edb41022", features = [ "no-entrypoint", ] } magicblock-program = { path = "../programs/magicblock" } @@ -75,7 +79,7 @@ rkyv = "0.7.45" schedulecommit-client = { path = "schedulecommit/client" } serde = "1.0.217" serial_test = "3.2.0" -solana-account = { git = "https://github.com/magicblock-labs/solana-account.git", rev = "57158728" } +solana-account = { git = "https://github.com/magicblock-labs/solana-account.git", rev = "2246929" } solana-loader-v2-interface = "2.2" solana-loader-v3-interface = "4.0" solana-loader-v4-interface = "2.1" @@ -110,4 +114,4 @@ url = "2.5.0" solana-storage-proto = { path = "../storage-proto" } # same reason as above rocksdb = { git = "https://github.com/magicblock-labs/rust-rocksdb.git", rev = "6d975197" } -solana-account = { git = "https://github.com/magicblock-labs/solana-account.git", rev = "57158728" } +solana-account = { git = "https://github.com/magicblock-labs/solana-account.git", rev = "2246929" } diff --git a/test-kit/src/lib.rs b/test-kit/src/lib.rs index a7f5bc469..0ccba11d8 100644 --- a/test-kit/src/lib.rs +++ b/test-kit/src/lib.rs @@ -179,7 +179,7 @@ impl ExecutionTestEnv { let keypair = Keypair::new(); let mut account = AccountSharedData::new(lamports, space, &owner); account.set_delegated(true); - self.accountsdb.insert_account(&keypair.pubkey(), &account); + let _ = self.accountsdb.insert_account(&keypair.pubkey(), &account); keypair } @@ -204,7 +204,7 @@ impl ExecutionTestEnv { ) { let mut account = AccountSharedData::new(lamports, 0, &owner); account.set_delegated(true); - self.accountsdb.insert_account(&pubkey, &account); + let _ = self.accountsdb.insert_account(&pubkey, &account); } /// Retrieves a transaction's metadata from the ledger by its signature. @@ -338,7 +338,7 @@ pub struct CommitableAccount<'db> { impl CommitableAccount<'_> { pub fn commit(self) { - self.db.insert_account(&self.pubkey, &self.account); + let _ = self.db.insert_account(&self.pubkey, &self.account); } }