use super::storage::{
assets::AssetDetails,
balances::TotalBalanceAmount,
};
use crate::fuel_core_graphql_api::storage::coins::CoinsToSpendIndexKey;
use async_trait::async_trait;
use fuel_core_services::stream::BoxStream;
use fuel_core_storage::{
Error as StorageError,
Result as StorageResult,
StorageInspect,
StorageRead,
iter::{
BoxedIter,
IterDirection,
},
tables::{
BlobData,
Coins,
ContractsAssets,
ContractsRawCode,
Messages,
StateTransitionBytecodeVersions,
UploadedBytecodes,
},
};
use fuel_core_tx_status_manager::TxStatusMessage;
use fuel_core_txpool::TxPoolStats;
use fuel_core_types::{
blockchain::{
block::CompressedBlock,
consensus::Consensus,
header::{
ConsensusParametersVersion,
StateTransitionBytecodeVersion,
},
primitives::{
BlockId,
DaBlockHeight,
},
},
entities::relayer::{
message::{
MerkleProof,
Message,
},
transaction::RelayedTransactionStatus,
},
fuel_tx::{
Bytes32,
ConsensusParameters,
Salt,
Transaction,
TxId,
TxPointer,
UtxoId,
},
fuel_types::{
Address,
AssetId,
BlockHeight,
ContractId,
Nonce,
},
fuel_vm::interpreter::Memory,
services::{
executor::{
DryRunResult,
StorageReadReplayEvent,
},
graphql_api::ContractBalance,
p2p::PeerInfo,
transaction_status::{
self,
TransactionStatus,
},
},
tai64::Tai64,
};
use std::sync::Arc;
pub struct CoinsToSpendIndexIter<'a> {
pub big_coins_iter: BoxedIter<'a, Result<CoinsToSpendIndexKey, StorageError>>,
pub dust_coins_iter: BoxedIter<'a, Result<CoinsToSpendIndexKey, StorageError>>,
}
pub trait OffChainDatabase: Send + Sync {
fn block_height(&self, block_id: &BlockId) -> StorageResult<BlockHeight>;
fn tx_status(
&self,
tx_id: &TxId,
) -> StorageResult<transaction_status::TransactionExecutionStatus>;
fn balance(
&self,
owner: &Address,
asset_id: &AssetId,
base_asset_id: &AssetId,
) -> StorageResult<TotalBalanceAmount>;
fn balances<'a>(
&'a self,
owner: &Address,
start: Option<AssetId>,
base_asset_id: &'a AssetId,
direction: IterDirection,
) -> BoxedIter<'a, StorageResult<(AssetId, TotalBalanceAmount)>>;
fn owned_coins_ids(
&self,
owner: &Address,
start_coin: Option<UtxoId>,
direction: IterDirection,
) -> BoxedIter<'_, StorageResult<UtxoId>>;
fn owned_message_ids(
&self,
owner: &Address,
start_message_id: Option<Nonce>,
direction: IterDirection,
) -> BoxedIter<'_, StorageResult<Nonce>>;
fn owned_transactions_ids(
&self,
owner: Address,
start: Option<TxPointer>,
direction: IterDirection,
) -> BoxedIter<'_, StorageResult<(TxPointer, TxId)>>;
fn coins_to_spend_index(
&self,
owner: &Address,
asset_id: &AssetId,
) -> CoinsToSpendIndexIter<'_>;
fn contract_salt(&self, contract_id: &ContractId) -> StorageResult<Salt>;
fn old_block(&self, height: &BlockHeight) -> StorageResult<CompressedBlock>;
fn old_blocks(
&self,
height: Option<BlockHeight>,
direction: IterDirection,
) -> BoxedIter<'_, StorageResult<CompressedBlock>>;
fn old_block_consensus(&self, height: &BlockHeight) -> StorageResult<Consensus>;
fn old_transaction(&self, id: &TxId) -> StorageResult<Option<Transaction>>;
fn relayed_tx_status(
&self,
id: Bytes32,
) -> StorageResult<Option<RelayedTransactionStatus>>;
fn message_is_spent(&self, nonce: &Nonce) -> StorageResult<bool>;
fn asset_info(&self, asset_id: &AssetId) -> StorageResult<Option<AssetDetails>>;
}
pub trait OnChainDatabase:
Send
+ Sync
+ DatabaseBlocks
+ DatabaseMessages
+ StorageInspect<Coins, Error = StorageError>
+ StorageRead<BlobData, Error = StorageError>
+ StorageInspect<StateTransitionBytecodeVersions, Error = StorageError>
+ StorageInspect<UploadedBytecodes, Error = StorageError>
+ DatabaseContracts
+ DatabaseChain
+ DatabaseMessageProof
{
}
pub trait DatabaseBlocks {
fn transaction(&self, tx_id: &TxId) -> StorageResult<Transaction>;
fn block(&self, height: &BlockHeight) -> StorageResult<CompressedBlock>;
fn blocks(
&self,
height: Option<BlockHeight>,
direction: IterDirection,
) -> BoxedIter<'_, StorageResult<CompressedBlock>>;
fn latest_height(&self) -> StorageResult<BlockHeight>;
fn consensus(&self, id: &BlockHeight) -> StorageResult<Consensus>;
}
pub trait DatabaseDaCompressedBlocks: Send + Sync {
fn da_compressed_block(&self, height: &BlockHeight) -> StorageResult<Vec<u8>>;
}
pub trait DatabaseMessages: StorageInspect<Messages, Error = StorageError> {
fn all_messages(
&self,
start_message_id: Option<Nonce>,
direction: IterDirection,
) -> BoxedIter<'_, StorageResult<Message>>;
fn message_exists(&self, nonce: &Nonce) -> StorageResult<bool>;
}
pub trait DatabaseRelayedTransactions {
fn transaction_status(
&self,
id: Bytes32,
) -> StorageResult<Option<RelayedTransactionStatus>>;
}
pub trait DatabaseContracts:
StorageInspect<ContractsRawCode, Error = StorageError>
+ StorageInspect<ContractsAssets, Error = StorageError>
{
fn contract_balances(
&self,
contract: ContractId,
start_asset: Option<AssetId>,
direction: IterDirection,
) -> BoxedIter<'_, StorageResult<ContractBalance>>;
fn contract_storage_slots(
&self,
contract: ContractId,
) -> BoxedIter<'_, StorageResult<(Bytes32, Vec<u8>)>>;
fn contract_storage_balances(
&self,
contract: ContractId,
) -> BoxedIter<'_, StorageResult<ContractBalance>>;
}
pub trait DatabaseChain {
fn da_height(&self) -> StorageResult<DaBlockHeight>;
}
#[async_trait]
pub trait TxPoolPort: Send + Sync {
async fn transaction(&self, id: TxId) -> anyhow::Result<Option<Transaction>>;
async fn insert(&self, txs: Transaction) -> anyhow::Result<()>;
fn latest_pool_stats(&self) -> TxPoolStats;
}
#[async_trait]
pub trait TxStatusManager: Send + Sync {
async fn status(&self, tx_id: TxId) -> anyhow::Result<Option<TransactionStatus>>;
async fn tx_update_subscribe(
&self,
tx_id: TxId,
) -> anyhow::Result<BoxStream<TxStatusMessage>>;
fn subscribe_txs_updates(
&self,
) -> anyhow::Result<BoxStream<anyhow::Result<(TxId, TransactionStatus)>>>;
}
#[async_trait]
pub trait BlockProducerPort: Send + Sync {
async fn dry_run_txs(
&self,
transactions: Vec<Transaction>,
height: Option<BlockHeight>,
time: Option<Tai64>,
utxo_validation: Option<bool>,
gas_price: Option<u64>,
record_storage_reads: bool,
) -> anyhow::Result<DryRunResult>;
async fn storage_read_replay(
&self,
height: BlockHeight,
) -> anyhow::Result<Vec<StorageReadReplayEvent>>;
}
#[async_trait::async_trait]
pub trait ConsensusModulePort: Send + Sync {
async fn manually_produce_blocks(
&self,
start_time: Option<Tai64>,
number_of_blocks: u32,
) -> anyhow::Result<()>;
}
pub trait DatabaseMessageProof: Send + Sync {
fn block_history_proof(
&self,
message_block_height: &BlockHeight,
commit_block_height: &BlockHeight,
) -> StorageResult<MerkleProof>;
}
#[async_trait::async_trait]
pub trait P2pPort: Send + Sync {
async fn all_peer_info(&self) -> anyhow::Result<Vec<PeerInfo>>;
}
pub trait GasPriceEstimate: Send + Sync {
fn worst_case_gas_price(&self, height: BlockHeight) -> Option<u64>;
}
#[async_trait::async_trait]
pub trait MemoryPool {
type Memory: Memory + Send + Sync + 'static;
async fn get_memory(&self) -> Self::Memory;
}
pub mod worker {
use super::super::storage::blocks::FuelBlockIdsToHeights;
use crate::{
fuel_core_graphql_api::storage::{
coins::OwnedCoins,
contracts::ContractsInfo,
messages::{
OwnedMessageIds,
SpentMessages,
},
},
graphql_api::storage::{
assets::AssetsInfo,
balances::{
CoinBalances,
MessageBalances,
},
coins::CoinsToSpendIndex,
old::{
OldFuelBlockConsensus,
OldFuelBlocks,
OldTransactions,
},
relayed_transactions::RelayedTransactionStatuses,
},
};
use derive_more::Display;
use fuel_core_services::stream::BoxStream;
use fuel_core_storage::{
Error as StorageError,
Result as StorageResult,
StorageMutate,
};
use fuel_core_types::{
fuel_tx::{
Address,
Bytes32,
},
fuel_types::BlockHeight,
services::{
block_importer::SharedImportResult,
transaction_status::{
self,
TransactionStatus,
},
},
};
pub trait OnChainDatabase: Send + Sync {
fn latest_height(&self) -> StorageResult<Option<BlockHeight>>;
}
pub trait OffChainDatabase: Send + Sync {
type Transaction<'a>: OffChainDatabaseTransaction
where
Self: 'a;
fn latest_height(&self) -> StorageResult<Option<BlockHeight>>;
fn transaction(&mut self) -> Self::Transaction<'_>;
fn balances_indexation_enabled(&self) -> StorageResult<bool>;
fn coins_to_spend_indexation_enabled(&self) -> StorageResult<bool>;
fn asset_metadata_indexation_enabled(&self) -> StorageResult<bool>;
}
#[derive(Copy, Clone, Debug, Display, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub enum BlockAt {
Specific(BlockHeight),
Genesis,
}
pub trait OffChainDatabaseTransaction:
StorageMutate<OwnedMessageIds, Error = StorageError>
+ StorageMutate<OwnedCoins, Error = StorageError>
+ StorageMutate<FuelBlockIdsToHeights, Error = StorageError>
+ StorageMutate<ContractsInfo, Error = StorageError>
+ StorageMutate<OldFuelBlocks, Error = StorageError>
+ StorageMutate<OldFuelBlockConsensus, Error = StorageError>
+ StorageMutate<OldTransactions, Error = StorageError>
+ StorageMutate<SpentMessages, Error = StorageError>
+ StorageMutate<RelayedTransactionStatuses, Error = StorageError>
+ StorageMutate<CoinBalances, Error = StorageError>
+ StorageMutate<MessageBalances, Error = StorageError>
+ StorageMutate<CoinsToSpendIndex, Error = StorageError>
+ StorageMutate<AssetsInfo, Error = StorageError>
{
fn record_tx_id_owner(
&mut self,
owner: &Address,
block_height: BlockHeight,
tx_idx: u16,
tx_id: &Bytes32,
) -> StorageResult<()>;
fn update_tx_status(
&mut self,
id: &Bytes32,
status: transaction_status::TransactionExecutionStatus,
) -> StorageResult<Option<transaction_status::TransactionExecutionStatus>>;
fn increase_tx_count(&mut self, new_txs_count: u64) -> StorageResult<u64>;
fn get_tx_count(&self) -> StorageResult<u64>;
fn commit(self) -> StorageResult<()>;
}
pub trait BlockImporter: Send + Sync {
fn block_events(&self) -> BoxStream<SharedImportResult>;
fn block_event_at_height(
&self,
height: BlockAt,
) -> anyhow::Result<SharedImportResult>;
}
pub trait TxStatusCompletion: Send + Sync {
fn send_complete(
&self,
id: Bytes32,
block_height: &BlockHeight,
status: TransactionStatus,
);
}
}
#[cfg_attr(feature = "test-helpers", mockall::automock)]
pub trait ChainStateProvider: Send + Sync {
fn current_consensus_params(&self) -> Arc<ConsensusParameters>;
fn current_consensus_parameters_version(&self) -> ConsensusParametersVersion;
fn consensus_params_at_version(
&self,
version: &ConsensusParametersVersion,
) -> anyhow::Result<Arc<ConsensusParameters>>;
fn current_stf_version(&self) -> StateTransitionBytecodeVersion;
}
pub trait OnChainDatabaseAt: Send + Sync {
fn contract_slot_values(
&self,
contract_id: ContractId,
storage_slots: Vec<Bytes32>,
) -> BoxedIter<'_, StorageResult<(Bytes32, Vec<u8>)>>;
fn contract_balance_values(
&self,
contract_id: ContractId,
assets: Vec<AssetId>,
) -> BoxedIter<'_, StorageResult<ContractBalance>>;
}
pub trait OffChainDatabaseAt: Send + Sync {}