forest/message_pool/msgpool/
provider.rs1use crate::blocks::{CachingBlockHeader, Tipset, TipsetKey};
5use crate::chain::index::ResolveNullTipset;
6use crate::chain::{ChainStore, HeadChanges};
7use crate::message::{ChainMessage, SignedMessage};
8use crate::message_pool::errors::Error;
9use crate::message_pool::msg_pool::{
10 MAX_ACTOR_PENDING_MESSAGES, MAX_UNTRUSTED_ACTOR_PENDING_MESSAGES,
11};
12use crate::networks::Height;
13use crate::prelude::*;
14use crate::shim::{
15 address::{Address, Protocol::*},
16 econ::TokenAmount,
17 message::Message,
18 state_tree::{ActorState, StateTree},
19};
20use crate::utils::db::CborStoreExt;
21use auto_impl::auto_impl;
22use tokio::sync::broadcast;
23
24#[auto_impl(Arc)]
28pub trait Provider {
29 fn subscribe_head_changes(&self) -> broadcast::Receiver<HeadChanges>;
31 fn get_heaviest_tipset(&self) -> Tipset;
33 fn put_message(&self, msg: &ChainMessage) -> Result<Cid, Error>;
36 fn get_actor_after(&self, addr: &Address, ts: &Tipset) -> Result<ActorState, Error>;
40 fn messages_for_block(
42 &self,
43 h: &CachingBlockHeader,
44 ) -> Result<(Vec<Message>, Vec<SignedMessage>), Error>;
45 fn load_tipset(&self, tsk: &TipsetKey) -> Result<Tipset, Error>;
47 fn chain_compute_base_fee(&self, ts: &Tipset) -> Result<TokenAmount, Error>;
49 fn resolve_to_deterministic_address_at_finality(
52 &self,
53 addr: &Address,
54 ts: &Tipset,
55 ) -> Result<Address, Error>;
56 fn messages_for_tipset(&self, ts: &Tipset) -> Result<Arc<Vec<ChainMessage>>, Error>;
58 fn max_actor_pending_messages(&self) -> u64 {
60 MAX_ACTOR_PENDING_MESSAGES
61 }
62 fn max_untrusted_actor_pending_messages(&self) -> u64 {
64 MAX_UNTRUSTED_ACTOR_PENDING_MESSAGES
65 }
66}
67
68impl Provider for ChainStore {
69 fn subscribe_head_changes(&self) -> broadcast::Receiver<HeadChanges> {
70 self.subscribe_head_changes()
71 }
72
73 fn get_heaviest_tipset(&self) -> Tipset {
74 self.heaviest_tipset()
75 }
76
77 fn put_message(&self, msg: &ChainMessage) -> Result<Cid, Error> {
78 let cid = self
79 .db()
80 .put_cbor_default(msg)
81 .map_err(|err| Error::Other(err.to_string()))?;
82 Ok(cid)
83 }
84
85 fn get_actor_after(&self, addr: &Address, ts: &Tipset) -> Result<ActorState, Error> {
86 let state = StateTree::new_from_root(self.db(), ts.parent_state())
87 .map_err(|e| Error::Other(e.to_string()))?;
88 Ok(state.get_required_actor(addr)?)
89 }
90
91 fn messages_for_block(
92 &self,
93 h: &CachingBlockHeader,
94 ) -> Result<(Vec<Message>, Vec<SignedMessage>), Error> {
95 crate::chain::block_messages(self.db(), h).map_err(|err| err.into())
96 }
97
98 fn load_tipset(&self, tsk: &TipsetKey) -> Result<Tipset, Error> {
99 Ok(self.chain_index().load_required_tipset(tsk)?)
100 }
101
102 fn chain_compute_base_fee(&self, ts: &Tipset) -> Result<TokenAmount, Error> {
103 let smoke_height = self.chain_config().epoch(Height::Smoke);
104 let firehorse_height = self.chain_config().epoch(Height::FireHorse);
105 crate::chain::compute_base_fee(self.db(), ts, smoke_height, firehorse_height)
106 .map_err(|err| err.into())
107 }
108
109 fn resolve_to_deterministic_address_at_finality(
110 &self,
111 addr: &Address,
112 ts: &Tipset,
113 ) -> Result<Address, Error> {
114 match addr.protocol() {
115 BLS | Secp256k1 | Delegated => Ok(*addr),
116 Actor => Err(Error::Other(
117 "Cannot resolve actor address to key address".into(),
118 )),
119 _ => {
120 let lookback_ts = if ts.epoch() > self.chain_config().policy.chain_finality {
121 self.chain_index()
122 .load_required_tipset_by_height_blocking(
123 ts.epoch() - self.chain_config().policy.chain_finality,
124 ts.clone(),
125 ResolveNullTipset::TakeOlder,
126 )
127 .map_err(|e| Error::Other(e.to_string()))?
128 } else {
129 ts.clone()
131 };
132
133 let state = StateTree::new_from_root(self.db(), lookback_ts.parent_state())
134 .map_err(|e| Error::Other(e.to_string()))?;
135 state
136 .resolve_to_deterministic_address(self.db(), *addr)
137 .map_err(|e| Error::Other(e.to_string()))
138 }
139 }
140 }
141
142 fn messages_for_tipset(&self, ts: &Tipset) -> Result<Arc<Vec<ChainMessage>>, Error> {
143 ChainStore::messages_for_tipset(self, ts).map_err(Into::into)
144 }
145}
146
147pub trait ProviderExt {
148 async fn resolve_to_deterministic_address_at_finality_async(
150 &self,
151 addr: Address,
152 ts: Tipset,
153 ) -> Result<Address, Error>;
154}
155
156impl<T> ProviderExt for T
157where
158 T: Provider + ShallowClone + Send + Sync + 'static,
159{
160 async fn resolve_to_deterministic_address_at_finality_async(
161 &self,
162 addr: Address,
163 ts: Tipset,
164 ) -> Result<Address, Error> {
165 let this = self.shallow_clone();
166 tokio::task::spawn_blocking(move || {
167 this.resolve_to_deterministic_address_at_finality(&addr, &ts)
168 })
169 .await
170 .context("tokio join error")?
171 }
172}