You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: mod.rs
    path of file: ./repos/namada/crates/apps/src/lib/node/ledger/ethereum_oracle
    
    the code of the file until where you have to start completion: pub mod control;
pub mod events;
pub mod test_tools;

use std::ops::ControlFlow;

use async_trait::async_trait;
use ethabi::Address;
use ethbridge_events::{event_codecs, EventKind};
use itertools::Either;
use namada::control_flow::time::{Constant, Duration, Instant, Sleep};
use namada::core::ethereum_events::EthereumEvent;
use namada::core::{ethereum_structs, hints};
use namada::eth_bridge::ethers;
use namada::eth_bridge::ethers::providers::{Http, Middleware, Provider};
use namada::eth_bridge::oracle::config::Config;
use namada_sdk::eth_bridge::{eth_syncing_status_timeout, SyncStatus};
use num256::Uint256;
use thiserror::Error;
use tokio::sync::mpsc::error::TryRecvError;
use tokio::sync::mpsc::Sender as BoundedSender;
use tokio::task::LocalSet;

use self::events::PendingEvent;
use super::abortable::AbortableSpawner;
use crate::node::ledger::oracle::control::Command;

/// The default amount of time the oracle will wait between processing blo
    
async fn run_oracle_aux<C: RpcClient>(mut oracle: Oracle<C>) {
    tracing::info!("Oracle is awaiting initial configuration");
    let mut config =
        match await_initial_configuration(&mut oracle.control).await {
            Some(config) => {
                tracing::info!(
                    "Oracle received initial configuration - {:?}",
                    config
                );
                config
            }
            None => {
                tracing::debug!(
                    "Oracle control channel was closed before the oracle \
                     could be configured"
                );
                return;
            }
        };

    let mut next_block_to_process = config.start_block.clone();

    loop {
        tracing::info!(
            ?next_block_to_process,
            "Checking Ethereum block for bridge events"
        );
        let res = Sleep { strategy: Constant(oracle.backoff) }.run(|| async {
            tokio::select! {
                action = try_process_eth_events(&oracle, &config, &next_block_to_process) => {
                    action.handle()
                },
                _ = oracle.sender.closed() => {
                    tracing::info!(
                        "Ethereum oracle can not send events to the ledger; the \
                        receiver has hung up. Shutting down"
                    );
                    ControlFlow::Break(Err(()))
                }
            }
        })
        .await;

        if hints::unlikely(res.is_err()) {
            break;
        }

        oracle
            .last_processed_block
            .send_replace(Some(next_block_to_process.clone()));
        // check if a new config has been sent.
        if let Some(new_config) = oracle.update_config() {
            config = new_config;
        }
        if !config.active {
            config = oracle.wait_on_reactivation().await;
        }
        next_block_to_process += 1.into();
    }
}