//! Conversions between `indexer_service_protocol` types and `lee/lee_core` types. use lee_core::account::Nonce; use crate::{ Account, AccountId, BedrockStatus, Block, BlockBody, BlockHeader, BlockIngestError, Ciphertext, Commitment, CommitmentSetDigest, Data, EncryptedAccountData, EphemeralPublicKey, HashType, IndexerStatus, IndexerSyncState, Nullifier, PrivacyPreservingMessage, PrivacyPreservingTransaction, ProgramDeploymentMessage, ProgramDeploymentTransaction, ProgramId, Proof, PublicKey, PublicMessage, PublicTransaction, Signature, StallReason, Transaction, ValidityWindow, WitnessSet, }; // ============================================================================ // Account-related conversions // ============================================================================ impl From<[u32; 8]> for ProgramId { fn from(value: [u32; 8]) -> Self { Self(value) } } impl From for [u32; 8] { fn from(value: ProgramId) -> Self { value.0 } } impl From for AccountId { fn from(value: lee_core::account::AccountId) -> Self { Self { value: value.into_value(), } } } impl From for lee_core::account::AccountId { fn from(value: AccountId) -> Self { let AccountId { value } = value; Self::new(value) } } impl From for Account { fn from(value: lee_core::account::Account) -> Self { let lee_core::account::Account { program_owner, balance, data, nonce, } = value; Self { program_owner: program_owner.into(), balance, data: data.into(), nonce: nonce.0, } } } impl TryFrom for lee_core::account::Account { type Error = lee_core::account::data::DataTooBigError; fn try_from(value: Account) -> Result { let Account { program_owner, balance, data, nonce, } = value; Ok(Self { program_owner: program_owner.into(), balance, data: data.try_into()?, nonce: Nonce(nonce), }) } } impl From for Data { fn from(value: lee_core::account::Data) -> Self { Self(value.into_inner()) } } impl TryFrom for lee_core::account::Data { type Error = lee_core::account::data::DataTooBigError; fn try_from(value: Data) -> Result { Self::try_from(value.0) } } // ============================================================================ // Commitment and Nullifier conversions // ============================================================================ impl From for Commitment { fn from(value: lee_core::Commitment) -> Self { Self(value.to_byte_array()) } } impl From for lee_core::Commitment { fn from(value: Commitment) -> Self { Self::from_byte_array(value.0) } } impl From for Nullifier { fn from(value: lee_core::Nullifier) -> Self { Self(value.to_byte_array()) } } impl From for lee_core::Nullifier { fn from(value: Nullifier) -> Self { Self::from_byte_array(value.0) } } impl From for CommitmentSetDigest { fn from(value: lee_core::CommitmentSetDigest) -> Self { Self(value) } } impl From for lee_core::CommitmentSetDigest { fn from(value: CommitmentSetDigest) -> Self { value.0 } } // ============================================================================ // Encryption-related conversions // ============================================================================ impl From for Ciphertext { fn from(value: lee_core::encryption::Ciphertext) -> Self { Self(value.into_inner()) } } impl From for lee_core::encryption::Ciphertext { fn from(value: Ciphertext) -> Self { Self::from_inner(value.0) } } impl From for EphemeralPublicKey { fn from(value: lee_core::encryption::EphemeralPublicKey) -> Self { Self(value.0) } } impl From for lee_core::encryption::EphemeralPublicKey { fn from(value: EphemeralPublicKey) -> Self { Self(value.0) } } // ============================================================================ // Signature and PublicKey conversions // ============================================================================ impl From for Signature { fn from(value: lee::Signature) -> Self { let lee::Signature { value } = value; Self(value) } } impl From for lee::Signature { fn from(value: Signature) -> Self { let Signature(sig_value) = value; Self { value: sig_value } } } impl From for PublicKey { fn from(value: lee::PublicKey) -> Self { Self(*value.value()) } } impl TryFrom for lee::PublicKey { type Error = lee::error::LeeError; fn try_from(value: PublicKey) -> Result { Self::try_new(value.0) } } // ============================================================================ // Proof conversions // ============================================================================ impl From for Proof { fn from(value: lee::privacy_preserving_transaction::circuit::Proof) -> Self { Self(value.into_inner()) } } impl From for lee::privacy_preserving_transaction::circuit::Proof { fn from(value: Proof) -> Self { Self::from_inner(value.0) } } // ============================================================================ // EncryptedAccountData conversions // ============================================================================ impl From for EncryptedAccountData { fn from(value: lee::privacy_preserving_transaction::message::EncryptedAccountData) -> Self { Self { ciphertext: value.ciphertext.into(), epk: value.epk.into(), view_tag: value.view_tag, } } } impl From for lee::privacy_preserving_transaction::message::EncryptedAccountData { fn from(value: EncryptedAccountData) -> Self { Self { ciphertext: value.ciphertext.into(), epk: value.epk.into(), view_tag: value.view_tag, } } } // ============================================================================ // Transaction Message conversions // ============================================================================ impl From for PublicMessage { fn from(value: lee::public_transaction::Message) -> Self { let lee::public_transaction::Message { program_id, account_ids, nonces, instruction_data, } = value; Self { program_id: program_id.into(), account_ids: account_ids.into_iter().map(Into::into).collect(), nonces: nonces.iter().map(|x| x.0).collect(), instruction_data, } } } impl From for lee::public_transaction::Message { fn from(value: PublicMessage) -> Self { let PublicMessage { program_id, account_ids, nonces, instruction_data, } = value; Self::new_preserialized( program_id.into(), account_ids.into_iter().map(Into::into).collect(), nonces .iter() .map(|x| lee_core::account::Nonce(*x)) .collect(), instruction_data, ) } } impl From for PrivacyPreservingMessage { fn from(value: lee::privacy_preserving_transaction::message::Message) -> Self { let lee::privacy_preserving_transaction::message::Message { public_actions, nonces, private_actions, block_validity_window, timestamp_validity_window, } = value; Self { public_account_ids: public_actions.iter().map(|a| a.account_id.into()).collect(), nonces: nonces.iter().map(|x| x.0).collect(), public_post_states: public_actions .into_iter() .map(|a| a.post_state.into()) .collect(), encrypted_private_post_states: private_actions .iter() .map(|a| a.encrypted_post_state.clone().into()) .collect(), new_commitments: private_actions .iter() .map(|a| a.commitment.into()) .collect(), new_nullifiers: private_actions .into_iter() .map(|a| (a.nullifier.into(), a.root.into())) .collect(), block_validity_window: block_validity_window.into(), timestamp_validity_window: timestamp_validity_window.into(), } } } impl TryFrom for lee::privacy_preserving_transaction::message::Message { type Error = lee::error::LeeError; fn try_from(value: PrivacyPreservingMessage) -> Result { let PrivacyPreservingMessage { public_account_ids, nonces, public_post_states, encrypted_private_post_states, new_commitments, new_nullifiers, block_validity_window, timestamp_validity_window, } = value; let public_post_states = public_post_states .into_iter() .map(TryInto::try_into) .collect::, _>>() .map_err(|e| lee::error::LeeError::InvalidInput(format!("{e}")))?; let public_actions = public_account_ids .into_iter() .map(Into::into) .zip(public_post_states) .map(|(account_id, post_state)| { lee::privacy_preserving_transaction::message::PublicActionWithID { account_id, post_state, } }) .collect(); let private_actions = new_commitments .into_iter() .map(Into::into) .zip( new_nullifiers .into_iter() .map(|(n, d)| (n.into(), d.into())), ) .zip(encrypted_private_post_states.into_iter().map(Into::into)) .map(|((commitment, (nullifier, root)), encrypted_post_state)| { lee_core::PrivateAction { nullifier, root, commitment, encrypted_post_state, } }) .collect(); Ok(Self { public_actions, nonces: nonces .iter() .map(|x| lee_core::account::Nonce(*x)) .collect(), private_actions, block_validity_window: block_validity_window .try_into() .map_err(|e| lee::error::LeeError::InvalidInput(format!("{e}")))?, timestamp_validity_window: timestamp_validity_window .try_into() .map_err(|e| lee::error::LeeError::InvalidInput(format!("{e}")))?, }) } } impl From for ProgramDeploymentMessage { fn from(value: lee::program_deployment_transaction::Message) -> Self { Self { bytecode: value.into_bytecode(), } } } impl From for lee::program_deployment_transaction::Message { fn from(value: ProgramDeploymentMessage) -> Self { let ProgramDeploymentMessage { bytecode } = value; Self::new(bytecode) } } // ============================================================================ // WitnessSet conversions // ============================================================================ impl From for WitnessSet { fn from(value: lee::public_transaction::WitnessSet) -> Self { Self { signatures_and_public_keys: value .signatures_and_public_keys() .iter() .map(|(sig, pk)| (sig.clone().into(), pk.clone().into())) .collect(), proof: None, } } } impl From for WitnessSet { fn from(value: lee::privacy_preserving_transaction::witness_set::WitnessSet) -> Self { let (sigs_and_pks, proof) = value.into_raw_parts(); Self { signatures_and_public_keys: sigs_and_pks .into_iter() .map(|(sig, pk)| (sig.into(), pk.into())) .collect(), proof: Some(proof.into()), } } } impl TryFrom for lee::privacy_preserving_transaction::witness_set::WitnessSet { type Error = lee::error::LeeError; fn try_from(value: WitnessSet) -> Result { let WitnessSet { signatures_and_public_keys, proof, } = value; let signatures_and_public_keys = signatures_and_public_keys .into_iter() .map(|(sig, pk)| Ok((sig.into(), pk.try_into()?))) .collect::, Self::Error>>()?; Ok(Self::from_raw_parts( signatures_and_public_keys, proof .map(Into::into) .ok_or_else(|| lee::error::LeeError::InvalidInput("Missing proof".to_owned()))?, )) } } // ============================================================================ // Transaction conversions // ============================================================================ impl From for PublicTransaction { fn from(value: lee::PublicTransaction) -> Self { let hash = HashType(value.hash()); let lee::PublicTransaction { message, witness_set, } = value; Self { hash, message: message.into(), witness_set: witness_set.into(), } } } impl TryFrom for lee::PublicTransaction { type Error = lee::error::LeeError; fn try_from(value: PublicTransaction) -> Result { let PublicTransaction { hash: _, message, witness_set, } = value; let WitnessSet { signatures_and_public_keys, proof: _, } = witness_set; Ok(Self::new( message.into(), lee::public_transaction::WitnessSet::from_raw_parts( signatures_and_public_keys .into_iter() .map(|(sig, pk)| Ok((sig.into(), pk.try_into()?))) .collect::, Self::Error>>()?, ), )) } } impl From for PrivacyPreservingTransaction { fn from(value: lee::PrivacyPreservingTransaction) -> Self { let hash = HashType(value.hash()); let lee::PrivacyPreservingTransaction { message, witness_set, } = value; Self { hash, message: message.into(), witness_set: witness_set.into(), } } } impl TryFrom for lee::PrivacyPreservingTransaction { type Error = lee::error::LeeError; fn try_from(value: PrivacyPreservingTransaction) -> Result { let PrivacyPreservingTransaction { hash: _, message, witness_set, } = value; Ok(Self::new(message.try_into()?, witness_set.try_into()?)) } } impl From for ProgramDeploymentTransaction { fn from(value: lee::ProgramDeploymentTransaction) -> Self { let hash = HashType(value.hash()); let lee::ProgramDeploymentTransaction { message } = value; Self { hash, message: message.into(), } } } impl From for lee::ProgramDeploymentTransaction { fn from(value: ProgramDeploymentTransaction) -> Self { let ProgramDeploymentTransaction { hash: _, message } = value; Self::new(message.into()) } } impl From for Transaction { fn from(value: common::transaction::LeeTransaction) -> Self { match value { common::transaction::LeeTransaction::Public(tx) => Self::Public(tx.into()), common::transaction::LeeTransaction::PrivacyPreserving(tx) => { Self::PrivacyPreserving(tx.into()) } common::transaction::LeeTransaction::ProgramDeployment(tx) => { Self::ProgramDeployment(tx.into()) } } } } impl TryFrom for common::transaction::LeeTransaction { type Error = lee::error::LeeError; fn try_from(value: Transaction) -> Result { match value { Transaction::Public(tx) => Ok(Self::Public(tx.try_into()?)), Transaction::PrivacyPreserving(tx) => Ok(Self::PrivacyPreserving(tx.try_into()?)), Transaction::ProgramDeployment(tx) => Ok(Self::ProgramDeployment(tx.into())), } } } // ============================================================================ // Block conversions // ============================================================================ impl From for BlockHeader { fn from(value: common::block::BlockHeader) -> Self { let common::block::BlockHeader { block_id, prev_block_hash, hash, timestamp, signature, } = value; Self { block_id, prev_block_hash: prev_block_hash.into(), hash: hash.into(), timestamp, signature: signature.into(), } } } impl TryFrom for common::block::BlockHeader { type Error = lee::error::LeeError; fn try_from(value: BlockHeader) -> Result { let BlockHeader { block_id, prev_block_hash, hash, timestamp, signature, } = value; Ok(Self { block_id, prev_block_hash: prev_block_hash.into(), hash: hash.into(), timestamp, signature: signature.into(), }) } } impl From for BlockBody { fn from(value: common::block::BlockBody) -> Self { let common::block::BlockBody { transactions } = value; let transactions = transactions .into_iter() .map(|tx| match tx { common::transaction::LeeTransaction::Public(tx) => Transaction::Public(tx.into()), common::transaction::LeeTransaction::PrivacyPreserving(tx) => { Transaction::PrivacyPreserving(tx.into()) } common::transaction::LeeTransaction::ProgramDeployment(tx) => { Transaction::ProgramDeployment(tx.into()) } }) .collect(); Self { transactions } } } impl TryFrom for common::block::BlockBody { type Error = lee::error::LeeError; fn try_from(value: BlockBody) -> Result { let BlockBody { transactions } = value; let transactions = transactions .into_iter() .map(|tx| { let lee_tx: common::transaction::LeeTransaction = tx.try_into()?; Ok::<_, lee::error::LeeError>(lee_tx) }) .collect::, _>>()?; Ok(Self { transactions }) } } impl From for Block { fn from(value: common::block::Block) -> Self { let common::block::Block { header, body, bedrock_status, } = value; Self { header: header.into(), body: body.into(), bedrock_status: bedrock_status.into(), } } } impl TryFrom for common::block::Block { type Error = lee::error::LeeError; fn try_from(value: Block) -> Result { let Block { header, body, bedrock_status, } = value; Ok(Self { header: header.try_into()?, body: body.try_into()?, bedrock_status: bedrock_status.into(), }) } } impl From for BedrockStatus { fn from(value: common::block::BedrockStatus) -> Self { match value { common::block::BedrockStatus::Pending => Self::Pending, common::block::BedrockStatus::Safe => Self::Safe, common::block::BedrockStatus::Finalized => Self::Finalized, } } } impl From for common::block::BedrockStatus { fn from(value: BedrockStatus) -> Self { match value { BedrockStatus::Pending => Self::Pending, BedrockStatus::Safe => Self::Safe, BedrockStatus::Finalized => Self::Finalized, } } } impl From for HashType { fn from(value: common::HashType) -> Self { Self(value.0) } } impl From for common::HashType { fn from(value: HashType) -> Self { Self(value.0) } } // ============================================================================ // ValidityWindow conversions // ============================================================================ impl From> for ValidityWindow { fn from(value: lee_core::program::ValidityWindow) -> Self { Self((value.start(), value.end())) } } impl TryFrom for lee_core::program::ValidityWindow { type Error = lee_core::program::InvalidWindow; fn try_from(value: ValidityWindow) -> Result { value.0.try_into() } } // ============================================================================ // Indexer status conversions // ============================================================================ impl From for IndexerSyncState { fn from(value: indexer_core::status::IndexerSyncState) -> Self { match value { indexer_core::status::IndexerSyncState::Starting => Self::Starting, indexer_core::status::IndexerSyncState::Syncing => Self::Syncing, indexer_core::status::IndexerSyncState::CaughtUp => Self::CaughtUp, indexer_core::status::IndexerSyncState::Error => Self::Error, indexer_core::status::IndexerSyncState::Stalled => Self::Stalled, } } } impl From for BlockIngestError { fn from(value: indexer_core::BlockIngestError) -> Self { match value { indexer_core::BlockIngestError::Deserialize(msg) => Self::Deserialize(msg), indexer_core::BlockIngestError::UnexpectedBlockId { expected, got } => { Self::UnexpectedBlockId { expected, got } } indexer_core::BlockIngestError::BrokenChainLink { expected_prev, got_prev, } => Self::BrokenChainLink { expected_prev: expected_prev.into(), got_prev: got_prev.into(), }, indexer_core::BlockIngestError::HashMismatch { computed, header } => { Self::HashMismatch { computed: computed.into(), header: header.into(), } } indexer_core::BlockIngestError::EmptyBlock => Self::EmptyBlock, indexer_core::BlockIngestError::InvalidClockTransaction => { Self::InvalidClockTransaction } indexer_core::BlockIngestError::NonPublicGenesisTransaction => { Self::NonPublicGenesisTransaction } indexer_core::BlockIngestError::StateTransition { tx_index, reason } => { Self::StateTransition { tx_index, reason } } } } } impl From for StallReason { fn from(value: indexer_core::StallReason) -> Self { let indexer_core::StallReason { block_id, block_hash, prev_block_hash, l1_slot, error, first_seen, orphans_since, } = value; Self { block_id, block_hash: block_hash.map(Into::into), prev_block_hash: prev_block_hash.map(Into::into), l1_slot: l1_slot.into_inner(), error: error.into(), first_seen, orphans_since, } } } impl From for IndexerStatus { fn from(value: indexer_core::status::IndexerStatus) -> Self { let indexer_core::status::IndexerStatus { sync, indexed_block_id, stall_reason, } = value; Self { state: sync.state.into(), last_error: sync.last_error, indexed_block_id, stall_reason: stall_reason.map(Into::into), } } }