Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test StateProviderFactory implementation of BlockchainProvider2<DB> #10353

Closed
Tracked by #10322
shekhirin opened this issue Aug 15, 2024 · 8 comments · Fixed by #10697
Closed
Tracked by #10322

Test StateProviderFactory implementation of BlockchainProvider2<DB> #10353

shekhirin opened this issue Aug 15, 2024 · 8 comments · Fixed by #10697
Assignees
Labels
A-blockchain-tree Related to sidechains, reorgs and pending blocks A-db Related to the database C-test A change that impacts how or what we test

Comments

@shekhirin
Copy link
Collaborator

No description provided.

@shekhirin shekhirin added A-db Related to the database C-test A change that impacts how or what we test A-blockchain-tree Related to sidechains, reorgs and pending blocks labels Aug 15, 2024
@malik672
Copy link
Contributor

@shekhirin assign me

@shekhirin
Copy link
Collaborator Author

@malik672 this one is more tricky, I recommend you checking other issues for adding tests to BlockchainProvider2 that are similar to the ones that I've already addressed

@malik672
Copy link
Contributor

@shekhirin sounds like a challenge......, I will take it

@malik672
Copy link
Contributor

malik672 commented Aug 16, 2024

@shekhirin came up with this, is it valid

`

#[cfg(test)]

mod tests {

use super::*;
use reth_db::{mock::DatabaseMock, DatabaseError};
use reth_primitives::{Address, StorageKey};
use std::sync::Arc;

fn setup_provider() -> BlockchainProvider2<DatabaseMock> {
    let db = DatabaseMock::default();
    let provider_factory = ProviderFactory::new(db.clone(), Arc::new(ChainSpec::default()), StaticFileProvider::default());
    BlockchainProvider2::new(provider_factory).unwrap()
}

#[test]
fn test_latest() {
    let provider = setup_provider();
    let latest_state = provider.latest();
    assert!(latest_state.is_ok());
}

#[test]
fn test_history_by_block_number() {
    let provider = setup_provider();
    let block_number = 100;
    let state = provider.history_by_block_number(block_number);
    assert!(state.is_ok());
}

#[test]
fn test_history_by_block_hash() {
    let provider = setup_provider();
    let block_hash = B256::random();
    let state = provider.history_by_block_hash(block_hash);

    assert!(state.is_ok());
}

#[test]
fn test_state_by_block_hash() {
    let provider = setup_provider();
    let block_hash = B256::random();
    let state = provider.state_by_block_hash(block_hash);
    
    assert!(state.is_ok());
}

#[test]
fn test_pending() {
    let provider = setup_provider();
    let pending_state = provider.pending();
    
    assert!(pending_state.is_ok());
}

#[test]
fn test_pending_state_by_hash() {
    let provider = setup_provider();
    let block_hash = B256::random();
    let pending_state = provider.pending_state_by_hash(block_hash).unwrap();

    assert!(pending_state.is_some() || pending_state.is_none());
}

#[test]
fn test_state_by_block_number_or_tag() {
    let provider = setup_provider();
    
    let latest_state = provider.state_by_block_number_or_tag(BlockNumberOrTag::Latest);
    assert!(latest_state.is_ok());
    
    let finalized_state = provider.state_by_block_number_or_tag(BlockNumberOrTag::Finalized);
    assert!(finalized_state.is_ok());
    
    let safe_state = provider.state_by_block_number_or_tag(BlockNumberOrTag::Safe);
    assert!(safe_state.is_ok());
    
    let earliest_state = provider.state_by_block_number_or_tag(BlockNumberOrTag::Earliest);
    assert!(earliest_state.is_ok());
    
    let pending_state = provider.state_by_block_number_or_tag(BlockNumberOrTag::Pending);
    assert!(pending_state.is_ok());
    
    let number_state = provider.state_by_block_number_or_tag(BlockNumberOrTag::Number(100));
    assert!(number_state.is_ok());
}

#[test]
fn test_state_provider_methods() {
    let provider = setup_provider();
    let state_provider = provider.latest().unwrap();

    let address = Address::random();
    let account = state_provider.basic_account(address).unwrap();
    assert!(account.is_some() || account.is_none());
    
    let storage = state_provider.storage(address, StorageKey::random()).unwrap();
    assert!(storage.is_some() || storage.is_none());
    
    let code = state_provider.bytecode_by_hash(B256::random()).unwrap();
    assert!(code.is_some() || code.is_none());
}

#[test]
fn test_error_handling() {
    let provider = setup_provider();
  
    let result = provider.history_by_block_number(u64::MAX);
    assert!(result.is_err());
   
    let result = provider.history_by_block_hash(B256::random());
    assert!(result.is_err());
}

}

`

@malik672
Copy link
Contributor

malik672 commented Aug 16, 2024

#[cfg(test)]
mod tests {
    use std::sync::Arc;
    use reth_chain_state::{ExecutedBlock, NewCanonicalChain};
    use reth_primitives::{Account, Address, BlockNumberOrTag, B256, U256};
    use super::StateProviderFactory;
    use reth_testing_utils::generators::{self, random_block_range};
    use crate::{providers::BlockchainProvider2, test_utils::create_test_provider_factory, BlockWriter};

    #[test]
    fn test_state_provider_factory() -> Result<(), ()> {
        let mut rng = generators::rng();
        let factory = create_test_provider_factory();

    
        let blocks = random_block_range(&mut rng, 0..=10, B256::ZERO, 0..1);
        let database_blocks = blocks[0..5].to_vec();
        let in_memory_blocks = blocks[5..].to_vec();
        let mut blocks_iter = blocks.into_iter();

     
        let provider_rw = factory.provider_rw().unwrap();
        for block in (0..5).map_while(|_| blocks_iter.next()) {
            let sealed_block = block.seal_with_senders().expect("failed to seal block with senders");
            provider_rw.insert_historical_block(sealed_block.clone()).unwrap();
      
            let address = Address::random();
            let account = Account::default();
            provider_rw.insert_block(block.seal_with_senders().unwrap());
        }
        provider_rw.commit().unwrap();

        let provider = BlockchainProvider2::new(factory).unwrap();

        let chain = NewCanonicalChain::Commit {
            new: blocks_iter
                .map(|block| {
                    let senders = block.senders().expect("failed to recover senders");
                    ExecutedBlock::new(
                        Arc::new(block),
                        Arc::new(senders),
                        Default::default(),
                        Default::default(),
                        Default::default(),
                    )
                })
                .collect(),
        };
        provider.canonical_in_memory_state.update_chain(chain);
        provider
            .canonical_in_memory_state
            .set_canonical_head(in_memory_blocks.last().unwrap().clone().header);

        let latest_state = provider.latest().unwrap();
        assert_eq!(memory_state.block_hash(memory_block.number).unwrap().unwrap(), memory_block.hash());


        let db_block = database_blocks.last().unwrap();
        let historical_state = provider.history_by_block_number(db_block.number);
        assert!(historical_state.is_ok());
        let historical_state = historical_state.unwrap();
        assert_eq!(memory_state.block_hash(memory_block.number).unwrap().unwrap(), memory_block.hash());

      
        let memory_block = in_memory_blocks.first().unwrap();
        let memory_state = provider.history_by_block_hash(memory_block.hash());
        assert!(memory_state.is_ok());
        let memory_state = memory_state.unwrap();
        assert_eq!(memory_state.block_hash(memory_block.number).unwrap().unwrap(), memory_block.hash());

        let latest_state = provider.state_by_block_number_or_tag(BlockNumberOrTag::Latest).unwrap();
        assert_eq!(memory_state.block_hash(memory_block.number).unwrap().unwrap(), memory_block.hash());

        let earliest_state = provider.state_by_block_number_or_tag(BlockNumberOrTag::Earliest).unwrap();

        let pending_state = provider.pending().unwrap();
        assert_eq!(memory_state.block_hash(memory_block.number).unwrap().unwrap(), memory_block.hash());


        Ok(())
    }
}

@shekhirin

@shekhirin
Copy link
Collaborator Author

@malik672 yeah, this is the right direction, but you also need to query retrieved states and verify that they return correct values

@jenpaff
Copy link
Collaborator

jenpaff commented Sep 3, 2024

@malik672 @shekhirin are you still actively working on this? alternatively I can also pick this up / help so we can wrap up the issue #10322

@shekhirin
Copy link
Collaborator Author

@jenpaff assigned to you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-blockchain-tree Related to sidechains, reorgs and pending blocks A-db Related to the database C-test A change that impacts how or what we test
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

3 participants