use miden_node_db::sqlite::WriteTx;
use miden_node_tracing::miden_instrument;
use miden_protocol::block::BlockNumber;
use miden_protocol::note::NoteHeader;
use miden_protocol::transaction::{
InputNoteCommitment,
OrderedTransactionHeaders,
TransactionHeader,
};
use crate::COMPONENT;
use crate::errors::DatabaseError;
const SQL: &str = include_str!("insert_transaction.sql");
#[miden_instrument(
target = COMPONENT,
err,
)]
pub(crate) fn insert_transactions(
tx: &WriteTx<'_>,
block_num: BlockNumber,
transactions: &OrderedTransactionHeaders,
) -> Result<usize, DatabaseError> {
let mut count = 0;
for header in transactions.as_slice() {
count += insert_transaction(tx, block_num, header)?;
}
Ok(count)
}
fn insert_transaction(
tx: &WriteTx<'_>,
block_num: BlockNumber,
header: &TransactionHeader,
) -> Result<usize, DatabaseError> {
let input_notes: Vec<InputNoteCommitment> = header.input_notes().iter().cloned().collect();
let input_notes = miden_node_persistence::encode(&input_notes);
let output_notes: Vec<NoteHeader> = header.output_notes().to_vec();
let output_notes = miden_node_persistence::encode(&output_notes);
Ok(tx.execute(
SQL,
&[
&header.id(),
&header.account_id(),
&block_num,
&header.initial_state_commitment(),
&header.final_state_commitment(),
&input_notes,
&output_notes,
&estimated_sync_record_size(header),
],
)?)
}
#[expect(
clippy::cast_possible_wrap,
reason = "We will not approach the item count where i64 and usize cause issues"
)]
fn estimated_sync_record_size(header: &TransactionHeader) -> i64 {
const HEADER_BASE_SIZE_BYTES: usize = 4 + 32 + 16 + 64;
const INPUT_NOTE_COMMITMENT_SIZE_BYTES: usize = 64;
const OUTPUT_NOTE_SYNC_RECORD_SIZE_BYTES: usize = 700;
const CONSUMED_NOTE_REF_SIZE_BYTES: usize = 64;
let input_notes_size = (header.input_notes().num_notes() as usize)
* (INPUT_NOTE_COMMITMENT_SIZE_BYTES + CONSUMED_NOTE_REF_SIZE_BYTES);
let output_notes_size = header.output_notes().len() * OUTPUT_NOTE_SYNC_RECORD_SIZE_BYTES;
(HEADER_BASE_SIZE_BYTES + input_notes_size + output_notes_size) as i64
}