use crate::GAS_MULTIPLIER;
use gear_common::{
auxiliary::gas_provider::{AuxiliaryGasProvider, GasTreeError, PlainNodeId},
gas_provider::{ConsumeResultOf, GasNodeId, LockableTree, Provider, ReservableTree, Tree},
Gas, GasMultiplier, LockId, Origin,
};
use gear_core::ids::{MessageId, ProgramId, ReservationId};
pub(crate) type PositiveImbalance = <GasTree as Tree>::PositiveImbalance;
pub(crate) type NegativeImbalance = <GasTree as Tree>::NegativeImbalance;
pub type OriginNodeDataOf = (
<GasTree as Tree>::ExternalOrigin,
GasMultiplier<<GasTree as Tree>::Funds, <GasTree as Tree>::Balance>,
<GasTree as Tree>::NodeId,
);
type GasTree = <AuxiliaryGasProvider as Provider>::GasTree;
#[derive(Debug, Default)]
pub(crate) struct GasTreeManager;
impl GasTreeManager {
pub(crate) fn create(
&self,
origin: ProgramId,
mid: MessageId,
amount: Gas,
is_reply: bool,
) -> Result<PositiveImbalance, GasTreeError> {
if !is_reply || !self.exists_and_deposit(mid) {
GasTree::create(
origin.cast(),
GAS_MULTIPLIER,
GasNodeId::from(mid.cast::<PlainNodeId>()),
amount,
)
} else {
Ok(PositiveImbalance::new(0))
}
}
pub(crate) fn create_deposit(
&self,
original_mid: MessageId,
future_reply_id: MessageId,
amount: Gas,
) -> Result<(), GasTreeError> {
GasTree::create_deposit(
GasNodeId::from(original_mid.cast::<PlainNodeId>()),
GasNodeId::from(future_reply_id.cast::<PlainNodeId>()),
amount,
)
}
pub(crate) fn split_with_value(
&self,
is_reply: bool,
original_mid: impl Origin,
new_mid: MessageId,
amount: Gas,
) -> Result<(), GasTreeError> {
if !is_reply || !GasTree::exists_and_deposit(GasNodeId::from(new_mid.cast::<PlainNodeId>()))
{
return GasTree::split_with_value(
GasNodeId::from(original_mid.cast::<PlainNodeId>()),
GasNodeId::from(new_mid.cast::<PlainNodeId>()),
amount,
);
}
Ok(())
}
pub(crate) fn split(
&self,
is_reply: bool,
original_node: impl Origin,
new_mid: MessageId,
) -> Result<(), GasTreeError> {
if !is_reply || !GasTree::exists_and_deposit(GasNodeId::from(new_mid.cast::<PlainNodeId>()))
{
return GasTree::split(
GasNodeId::from(original_node.cast::<PlainNodeId>()),
GasNodeId::from(new_mid.cast::<PlainNodeId>()),
);
}
Ok(())
}
pub(crate) fn cut(
&self,
original_node: impl Origin,
new_mid: MessageId,
amount: Gas,
) -> Result<(), GasTreeError> {
GasTree::cut(
GasNodeId::from(original_node.cast::<PlainNodeId>()),
GasNodeId::from(new_mid.cast::<PlainNodeId>()),
amount,
)
}
pub(crate) fn get_limit(&self, mid: impl Origin) -> Result<Gas, GasTreeError> {
GasTree::get_limit(GasNodeId::from(mid.cast::<PlainNodeId>()))
}
pub(crate) fn spend(
&self,
mid: MessageId,
amount: Gas,
) -> Result<NegativeImbalance, GasTreeError> {
GasTree::spend(GasNodeId::from(mid.cast::<PlainNodeId>()), amount)
}
pub(crate) fn consume(&self, mid: impl Origin) -> ConsumeResultOf<GasTree> {
GasTree::consume(GasNodeId::from(mid.cast::<PlainNodeId>()))
}
pub(crate) fn reserve_gas(
&self,
original_mid: MessageId,
reservation_id: ReservationId,
amount: Gas,
) -> Result<(), GasTreeError> {
GasTree::reserve(
GasNodeId::from(original_mid.cast::<PlainNodeId>()),
GasNodeId::from(reservation_id.cast::<PlainNodeId>()),
amount,
)
}
#[cfg(test)]
pub(crate) fn exists(&self, node_id: impl Origin) -> bool {
GasTree::exists(GasNodeId::from(node_id.cast::<PlainNodeId>()))
}
pub(crate) fn exists_and_deposit(&self, node_id: impl Origin) -> bool {
GasTree::exists_and_deposit(GasNodeId::from(node_id.cast::<PlainNodeId>()))
}
pub(crate) fn reset(&self) {
<AuxiliaryGasProvider as Provider>::reset();
}
pub(crate) fn system_unreserve(&self, message_id: MessageId) -> Result<Gas, GasTreeError> {
GasTree::system_unreserve(GasNodeId::from(message_id.cast::<PlainNodeId>()))
}
pub(crate) fn system_reserve(
&self,
message_id: MessageId,
amount: Gas,
) -> Result<(), GasTreeError> {
GasTree::system_reserve(GasNodeId::from(message_id.cast::<PlainNodeId>()), amount)
}
pub fn lock(&self, node_id: impl Origin, id: LockId, amount: Gas) -> Result<(), GasTreeError> {
GasTree::lock(GasNodeId::from(node_id.cast::<PlainNodeId>()), id, amount)
}
pub(crate) fn unlock_all(
&self,
message_id: impl Origin,
id: LockId,
) -> Result<Gas, GasTreeError> {
GasTree::unlock_all(GasNodeId::from(message_id.cast::<PlainNodeId>()), id)
}
pub(crate) fn get_origin_node(
&self,
message_id: MessageId,
) -> Result<OriginNodeDataOf, GasTreeError> {
GasTree::get_origin_node(GasNodeId::from(message_id.cast::<PlainNodeId>()))
}
}