use std::{error::Error, str::FromStr as _, sync::Arc};
use crate::chain_index::{
types::{BlockHash, TransactionHash},
ShieldedPool,
};
use async_trait::async_trait;
use futures::{future::join, TryFutureExt as _};
use incrementalmerkletree::frontier::CommitmentTree;
use tower::{Service, ServiceExt as _};
use zaino_common::Network;
use zaino_fetch::jsonrpsee::{
connector::{JsonRpSeeConnector, RpcRequestError},
response::{
address_deltas::{GetAddressDeltasParams, GetAddressDeltasResponse},
GetBlockError, GetBlockResponse, GetTransactionResponse, GetTreestateResponse,
},
};
use zcash_primitives::merkle_tree::{read_commitment_tree, write_commitment_tree};
use zebra_chain::{
block::TryIntoHeight, serialization::ZcashDeserialize, subtree::NoteCommitmentSubtreeIndex,
};
use zebra_rpc::{
client::{GetAddressBalanceRequest, GetAddressTxIdsRequest},
methods::{AddressBalance, GetAddressUtxos},
};
use zebra_state::{HashOrHeight, ReadRequest, ReadResponse, ReadStateService};
#[cfg(test)]
pub(crate) mod mockchain_source;
pub mod validator_connector;
pub use validator_connector::*;
#[async_trait]
pub trait BlockchainSource: Clone + Send + Sync + 'static {
async fn get_block(
&self,
id: HashOrHeight,
) -> BlockchainSourceResult<Option<Arc<zebra_chain::block::Block>>>;
async fn get_transaction(
&self,
txid: TransactionHash,
) -> BlockchainSourceResult<
Option<(
Arc<zebra_chain::transaction::Transaction>,
GetTransactionLocation,
)>,
>;
async fn get_mempool_txids(
&self,
) -> BlockchainSourceResult<Option<Vec<zebra_chain::transaction::Hash>>>;
async fn get_best_block_hash(&self)
-> BlockchainSourceResult<Option<zebra_chain::block::Hash>>;
async fn get_best_block_height(
&self,
) -> BlockchainSourceResult<Option<zebra_chain::block::Height>>;
async fn get_treestate(
&self,
id: BlockHash,
) -> BlockchainSourceResult<(Option<Vec<u8>>, Option<Vec<u8>>)>;
async fn get_subtree_roots(
&self,
pool: ShieldedPool,
start_index: u16,
max_entries: Option<u16>,
) -> BlockchainSourceResult<Vec<([u8; 32], u32)>>;
async fn get_commitment_tree_roots(
&self,
id: BlockHash,
) -> BlockchainSourceResult<(
Option<(zebra_chain::sapling::tree::Root, u64)>,
Option<(zebra_chain::orchard::tree::Root, u64)>,
)>;
async fn get_address_deltas(
&self,
params: GetAddressDeltasParams,
) -> BlockchainSourceResult<GetAddressDeltasResponse>;
async fn get_address_balance(
&self,
address_strings: GetAddressBalanceRequest,
) -> BlockchainSourceResult<AddressBalance>;
async fn get_address_txids(
&self,
request: GetAddressTxIdsRequest,
) -> BlockchainSourceResult<Vec<TransactionHash>>;
async fn get_address_utxos(
&self,
address_strings: GetAddressBalanceRequest,
) -> BlockchainSourceResult<Vec<GetAddressUtxos>>;
async fn nonfinalized_listener(
&self,
) -> Result<
Option<
tokio::sync::mpsc::Receiver<(zebra_chain::block::Hash, Arc<zebra_chain::block::Block>)>,
>,
Box<dyn Error + Send + Sync>,
>;
}
#[derive(Debug, thiserror::Error)]
pub enum BlockchainSourceError {
#[error("critical error in backing block source: {0}")]
Unrecoverable(String),
}
#[derive(thiserror::Error, Debug)]
#[error("data from validator invalid: {0}")]
pub struct InvalidData(String);
pub(crate) type BlockchainSourceResult<T> = Result<T, BlockchainSourceError>;
#[derive(Debug, Clone)]
pub enum GetTransactionLocation {
BestChain(zebra_chain::block::Height),
NonbestChain,
Mempool,
}