use miden_node_db::sqlite::{DbValue, ToSqlValue, WriteTx};
use miden_node_tracing::miden_instrument;
use miden_protocol::Word;
use miden_protocol::account::AccountId;
use miden_protocol::block::BlockNumber;
use miden_protocol::note::{NoteAssets, NoteDetails, NoteStorage, Nullifier};
use miden_standards::note::NetworkAccountTarget;
use crate::COMPONENT;
use crate::db::NoteRecord;
use crate::errors::DatabaseError;
const SQL: &str = include_str!("insert_note.sql");
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(i64)]
pub(crate) enum NetworkNoteType {
None = 0,
SingleTarget = 1,
}
impl ToSqlValue for NetworkNoteType {
fn to_sql_value(&self) -> DbValue {
DbValue::integer(*self as i64)
}
}
#[miden_instrument(
target = COMPONENT,
err,
)]
pub(crate) fn insert_notes(
tx: &WriteTx<'_>,
notes: &[(NoteRecord, Option<Nullifier>)],
) -> Result<usize, DatabaseError> {
let mut count = 0;
for (note, nullifier) in notes {
count += insert_note(tx, note, *nullifier)?;
}
Ok(count)
}
fn insert_note(
tx: &WriteTx<'_>,
note: &NoteRecord,
nullifier: Option<Nullifier>,
) -> Result<usize, DatabaseError> {
let target_account_id: Option<AccountId> = NetworkAccountTarget::try_from(¬e.attachments)
.ok()
.map(|target| target.target_id());
let network_note_type = if target_account_id.is_some() && !note.metadata.is_private() {
NetworkNoteType::SingleTarget
} else {
NetworkNoteType::None
};
let batch_index = index_column(note.note_index.batch_idx());
let note_index = index_column(note.note_index.note_idx_in_batch());
let note_type = note.metadata.note_type() as u8;
let details = note.details.as_ref();
let assets: Option<&NoteAssets> = details.map(NoteDetails::assets);
let storage: Option<&NoteStorage> = details.map(NoteDetails::storage);
let script_root: Option<Word> = details.map(|d| Word::from(d.script().root()));
let serial_num: Option<Word> = details.map(NoteDetails::serial_num);
Ok(tx.execute(
SQL,
&[
¬e.block_num,
&batch_index,
¬e_index,
¬e.note_id,
¬e_type,
¬e.metadata.sender(),
¬e.metadata.tag(),
&network_note_type,
&target_account_id,
¬e.attachments,
¬e.inclusion_path,
&None::<BlockNumber>,
&nullifier,
&assets,
&storage,
&script_root,
&serial_num,
],
)?)
}
fn index_column(index: usize) -> u32 {
u32::try_from(index).expect("note indices are bounded well below u32::MAX")
}