soil_client/client_api/
execution_extensions.rs1use parking_lot::RwLock;
14use std::{marker::PhantomData, sync::Arc};
15use subsoil::core::traits::{ReadRuntimeVersion, ReadRuntimeVersionExt};
16use subsoil::externalities::{Extension, Extensions};
17use subsoil::runtime::traits::{Block as BlockT, NumberFor};
18
19pub trait ExtensionsFactory<Block: BlockT>: Send + Sync {
23 fn extensions_for(&self, block_hash: Block::Hash, block_number: NumberFor<Block>)
28 -> Extensions;
29}
30
31impl<Block: BlockT> ExtensionsFactory<Block> for () {
32 fn extensions_for(&self, _: Block::Hash, _: NumberFor<Block>) -> Extensions {
33 Extensions::new()
34 }
35}
36
37impl<Block: BlockT, T: ExtensionsFactory<Block>> ExtensionsFactory<Block> for Vec<T> {
38 fn extensions_for(
39 &self,
40 block_hash: Block::Hash,
41 block_number: NumberFor<Block>,
42 ) -> Extensions {
43 let mut exts = Extensions::new();
44 exts.extend(self.iter().map(|e| e.extensions_for(block_hash, block_number)));
45 exts
46 }
47}
48
49pub struct ExtensionBeforeBlock<Block: BlockT, Ext> {
51 before: NumberFor<Block>,
52 _marker: PhantomData<fn(Ext) -> Ext>,
53}
54
55impl<Block: BlockT, Ext> ExtensionBeforeBlock<Block, Ext> {
56 pub fn new(before: NumberFor<Block>) -> Self {
60 Self { before, _marker: PhantomData }
61 }
62}
63
64impl<Block: BlockT, Ext: Default + Extension> ExtensionsFactory<Block>
65 for ExtensionBeforeBlock<Block, Ext>
66{
67 fn extensions_for(&self, _: Block::Hash, block_number: NumberFor<Block>) -> Extensions {
68 let mut exts = Extensions::new();
69
70 if block_number < self.before {
71 exts.register(Ext::default());
72 }
73
74 exts
75 }
76}
77
78pub struct ExecutionExtensions<Block: BlockT> {
83 extensions_factory: RwLock<Box<dyn ExtensionsFactory<Block>>>,
84 read_runtime_version: Arc<dyn ReadRuntimeVersion>,
85}
86
87impl<Block: BlockT> ExecutionExtensions<Block> {
88 pub fn new(
90 extensions_factory: Option<Box<dyn ExtensionsFactory<Block>>>,
91 read_runtime_version: Arc<dyn ReadRuntimeVersion>,
92 ) -> Self {
93 Self {
94 extensions_factory: extensions_factory
95 .map(RwLock::new)
96 .unwrap_or_else(|| RwLock::new(Box::new(()))),
97 read_runtime_version,
98 }
99 }
100
101 pub fn set_extensions_factory(&self, maker: impl ExtensionsFactory<Block> + 'static) {
103 *self.extensions_factory.write() = Box::new(maker);
104 }
105
106 pub fn extensions(
108 &self,
109 block_hash: Block::Hash,
110 block_number: NumberFor<Block>,
111 ) -> Extensions {
112 let mut extensions =
113 self.extensions_factory.read().extensions_for(block_hash, block_number);
114
115 extensions.register(ReadRuntimeVersionExt::new(self.read_runtime_version.clone()));
116 extensions
117 }
118}