Skip to content

Commit

Permalink
Merge pull request input-output-hk#1685 from input-output-hk/djo/1645…
Browse files Browse the repository at this point in the history
…/prune_ctx_in_signer

Prune cardano transactions in signer after block range roots computation
  • Loading branch information
Alenar authored May 17, 2024
2 parents 2fe74c2 + e258352 commit 9104258
Show file tree
Hide file tree
Showing 18 changed files with 596 additions and 213 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ As a minor extension, we have adopted a slightly different versioning convention

- Support computation of the Cardano Transactions signature and proving with the pre-computed Block Range Merkle Roots retrieved from the database.

- Prune Cardano Transactions from the signer database after the Block Range Merkle Roots have been computed.

- Update website and explorer user interface to use the new mithril logo.

- Crates versions:
Expand Down
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion internal/mithril-persistence/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mithril-persistence"
version = "0.1.11"
version = "0.1.12"
description = "Common types, interfaces, and utilities to persist data for Mithril nodes."
authors = { workspace = true }
edition = { workspace = true }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
use anyhow::Context;
use sqlite::Value;

use mithril_common::entities::BlockNumber;
use mithril_common::StdResult;

use crate::database::record::CardanoTransactionRecord;
use crate::sqlite::{
EntityCursor, Provider, SourceAlias, SqLiteEntity, SqliteConnection, WhereCondition,
};

/// Query to delete old [CardanoTransactionRecord] from the sqlite database
pub struct DeleteCardanoTransactionProvider<'conn> {
connection: &'conn SqliteConnection,
}

impl<'conn> Provider<'conn> for DeleteCardanoTransactionProvider<'conn> {
type Entity = CardanoTransactionRecord;

fn get_connection(&'conn self) -> &'conn SqliteConnection {
self.connection
}

fn get_definition(&self, condition: &str) -> String {
// it is important to alias the fields with the same name as the table
// since the table cannot be aliased in a RETURNING statement in SQLite.
let projection = Self::Entity::get_projection()
.expand(SourceAlias::new(&[("{:cardano_tx:}", "cardano_tx")]));

format!("delete from cardano_tx where {condition} returning {projection}")
}
}

impl<'conn> DeleteCardanoTransactionProvider<'conn> {
/// Create a new instance
pub fn new(connection: &'conn SqliteConnection) -> Self {
Self { connection }
}

fn get_prune_condition(
&self,
block_number_threshold: BlockNumber,
) -> StdResult<WhereCondition> {
let threshold = Value::Integer(block_number_threshold.try_into().with_context(|| {
format!("Failed to convert threshold `{block_number_threshold}` to i64")
})?);

Ok(WhereCondition::new("block_number < ?*", vec![threshold]))
}

/// Prune the cardano transaction data below the given threshold.
pub fn prune(
&self,
block_number_threshold: BlockNumber,
) -> StdResult<EntityCursor<CardanoTransactionRecord>> {
let filters = self.get_prune_condition(block_number_threshold)?;

self.find(filters)
}
}

#[cfg(test)]
mod tests {
use crate::database::provider::{
GetCardanoTransactionProvider, InsertCardanoTransactionProvider,
};
use crate::database::test_helper::cardano_tx_db_connection;
use crate::sqlite::GetAllProvider;

use super::*;

fn insert_transactions(connection: &SqliteConnection, records: Vec<CardanoTransactionRecord>) {
let provider = InsertCardanoTransactionProvider::new(connection);
let condition = provider.get_insert_many_condition(records).unwrap();
let mut cursor = provider.find(condition).unwrap();
cursor.next().unwrap();
}

fn test_transaction_set() -> Vec<CardanoTransactionRecord> {
vec![
CardanoTransactionRecord::new("tx-hash-0", 10, 50, "block-hash-10", 1),
CardanoTransactionRecord::new("tx-hash-1", 10, 51, "block-hash-10", 1),
CardanoTransactionRecord::new("tx-hash-2", 11, 52, "block-hash-11", 1),
CardanoTransactionRecord::new("tx-hash-3", 11, 53, "block-hash-11", 1),
CardanoTransactionRecord::new("tx-hash-4", 12, 54, "block-hash-12", 1),
CardanoTransactionRecord::new("tx-hash-5", 12, 55, "block-hash-12", 1),
]
}

#[test]
fn test_prune_work_even_without_transactions_in_db() {
let connection = cardano_tx_db_connection().unwrap();

let prune_provider = DeleteCardanoTransactionProvider::new(&connection);
let cursor = prune_provider
.prune(100)
.expect("pruning shouldn't crash without transactions stored");
assert_eq!(0, cursor.count());
}

#[test]
fn test_prune_all_data_if_given_block_number_is_larger_than_stored_number_of_block() {
let connection = cardano_tx_db_connection().unwrap();
insert_transactions(&connection, test_transaction_set());

let prune_provider = DeleteCardanoTransactionProvider::new(&connection);
let cursor = prune_provider.prune(100_000).unwrap();
assert_eq!(test_transaction_set().len(), cursor.count());

let get_provider = GetCardanoTransactionProvider::new(&connection);
let cursor = get_provider.get_all().unwrap();
assert_eq!(0, cursor.count());
}

#[test]
fn test_prune_keep_all_tx_of_last_block_if_given_number_of_block_is_zero() {
let connection = cardano_tx_db_connection().unwrap();
insert_transactions(&connection, test_transaction_set());

let prune_provider = DeleteCardanoTransactionProvider::new(&connection);
let cursor = prune_provider.prune(0).unwrap();
assert_eq!(0, cursor.count());

let get_provider = GetCardanoTransactionProvider::new(&connection);
let cursor = get_provider.get_all().unwrap();
assert_eq!(test_transaction_set().len(), cursor.count());
}

#[test]
fn test_prune_data_of_below_given_blocks() {
let connection = cardano_tx_db_connection().unwrap();
insert_transactions(&connection, test_transaction_set());

let prune_provider = DeleteCardanoTransactionProvider::new(&connection);
let cursor = prune_provider.prune(12).unwrap();
assert_eq!(4, cursor.count());

let get_provider = GetCardanoTransactionProvider::new(&connection);
let cursor = get_provider.get_all().unwrap();
assert_eq!(2, cursor.count());
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
mod delete_cardano_transaction;
mod get_cardano_transaction;
mod insert_cardano_transaction;

pub use delete_cardano_transaction::*;
pub use get_cardano_transaction::*;
pub use insert_cardano_transaction::*;
Loading

0 comments on commit 9104258

Please sign in to comment.