#![deny(missing_docs)]
use error::{BigBangError, CriticalError};
pub use essential_node_db as db;
use essential_node_types::{block_notify::BlockTx, BigBang};
use essential_relayer::Relayer;
use essential_types::ContentAddress;
pub use handles::node::Handle;
pub use validate::validate_dry_run;
pub use validate::validate_solution_set_dry_run;
use validation::validation_stream;
mod error;
mod handles;
#[cfg(any(feature = "test-utils", test))]
#[allow(missing_docs)]
pub mod test_utils;
pub mod validate;
mod validation;
#[derive(Clone, Debug)]
pub struct RunConfig {
pub relayer_source_endpoint: Option<String>,
pub run_validation: bool,
}
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
pub async fn ensure_big_bang_block(
conn_pool: &db::ConnectionPool,
big_bang: &BigBang,
) -> Result<ContentAddress, BigBangError> {
let bb_block = big_bang.block();
let bb_block_ca = essential_hash::content_addr(&bb_block);
#[cfg(feature = "tracing")]
tracing::debug!("Big Bang Block CA: {bb_block_ca}");
match conn_pool.list_blocks(0..1).await?.into_iter().next() {
None => {
#[cfg(feature = "tracing")]
tracing::debug!("Big Bang Block not found - inserting into DB");
let bbb_ca = bb_block_ca.clone();
conn_pool
.acquire_then(|conn| {
db::with_tx(conn, move |tx| {
db::insert_block(tx, &bb_block)?;
db::finalize_block(tx, &bbb_ca)?;
Ok::<_, rusqlite::Error>(())
})
})
.await?;
}
Some(block) => {
let ca = essential_hash::content_addr(&block);
if ca != bb_block_ca {
return Err(BigBangError::UnexpectedBlock {
expected: bb_block_ca,
found: ca,
});
}
#[cfg(feature = "tracing")]
tracing::debug!("Big Bang Block already exists");
}
}
if conn_pool.get_validation_progress().await?.is_none() {
#[cfg(feature = "tracing")]
tracing::debug!("Starting validation progress at Big Bang Block CA");
conn_pool
.update_validation_progress(bb_block_ca.clone())
.await?;
}
Ok(bb_block_ca)
}
pub fn run(
conn_pool: db::ConnectionPool,
conf: RunConfig,
contract_registry: ContentAddress,
program_registry: ContentAddress,
block_notify: BlockTx,
) -> Result<Handle, CriticalError> {
let RunConfig {
run_validation,
relayer_source_endpoint,
} = conf;
let relayer_handle = if let Some(relayer_source_endpoint) = relayer_source_endpoint {
let relayer = Relayer::new(relayer_source_endpoint.as_str())?;
Some(relayer.run(conn_pool.clone(), block_notify.clone())?)
} else {
None
};
let validation_handle = if run_validation {
Some(validation_stream(
conn_pool.clone(),
contract_registry,
program_registry,
block_notify.new_listener(),
)?)
} else {
None
};
Ok(Handle::new(relayer_handle, validation_handle))
}