1#![warn(missing_docs)]
28
29mod custom_api;
30mod genesis_block_builder;
31
32use crate::custom_api::{TrieBackendApi, TrieDeltaBackendFor};
33pub use custom_api::{CollectedStorageChanges, DeltaBackend, create_delta_backend};
34pub use genesis_block_builder::CustomGenesisBlockBuilder;
35use parity_scale_codec::Encode;
36use sc_client_api::{ExecutorProvider, backend};
37use sp_api::{ProvideRuntimeApi, TransactionOutcome};
38pub use sp_block_builder::BlockBuilder as BlockBuilderApi;
39use sp_blockchain::{ApplyExtrinsicFailed, Error};
40use sp_core::traits::CodeExecutor;
41use sp_runtime::Digest;
42use sp_runtime::traits::{Block as BlockT, Hash, HashingFor, Header as HeaderT, NumberFor, One};
43use sp_state_machine::OverlayedChanges;
44use std::collections::VecDeque;
45use std::sync::Arc;
46
47pub struct BuiltBlock<Block: BlockT> {
52    pub block: Block,
54    pub storage_changes: CollectedStorageChanges<HashingFor<Block>>,
56}
57
58impl<Block: BlockT> BuiltBlock<Block> {
59    pub fn into_inner(self) -> (Block, CollectedStorageChanges<HashingFor<Block>>) {
61        (self.block, self.storage_changes)
62    }
63}
64
65pub struct BlockBuilder<Client, Block: BlockT, Backend: backend::Backend<Block>, Exec> {
67    extrinsics: VecDeque<Block::Extrinsic>,
68    api: TrieBackendApi<Client, Block, Backend, Exec>,
69}
70
71impl<Client, Block, Backend, Exec> BlockBuilder<Client, Block, Backend, Exec>
72where
73    Block: BlockT,
74    Client: ProvideRuntimeApi<Block> + ExecutorProvider<Block>,
75    Client::Api: BlockBuilderApi<Block>,
76    Backend: backend::Backend<Block>,
77    Exec: CodeExecutor,
78{
79    #[allow(clippy::too_many_arguments)]
85    pub fn new(
86        client: Arc<Client>,
87        parent_hash: Block::Hash,
88        parent_number: NumberFor<Block>,
89        inherent_digests: Digest,
90        backend: Arc<Backend>,
91        exec: Arc<Exec>,
92        mut extrinsics: VecDeque<Block::Extrinsic>,
93        maybe_inherent_data: Option<sp_inherents::InherentData>,
94    ) -> Result<Self, Error> {
95        let mut api = TrieBackendApi::new(parent_hash, parent_number, client, backend, exec)?;
96        let header = <Block::Header as HeaderT>::new(
97            parent_number + One::one(),
98            Default::default(),
99            Default::default(),
100            parent_hash,
101            inherent_digests,
102        );
103
104        api.execute_in_transaction(
105            |api: &TrieBackendApi<Client, Block, Backend, Exec>,
106             backend: &TrieDeltaBackendFor<Backend::State, Block>,
107             overlayed_changes: &mut OverlayedChanges<HashingFor<Block>>| {
108                match api.initialize_block(header, backend, overlayed_changes) {
109                    Ok(_) => TransactionOutcome::Commit(Ok(())),
110                    Err(e) => TransactionOutcome::Rollback(Err(e)),
111                }
112            },
113        )?;
114
115        if let Some(inherent_data) = maybe_inherent_data {
116            let inherent_extrinsics = Self::create_inherents(&mut api, inherent_data)?;
117
118            for inherent_extrinsic in inherent_extrinsics.into_iter().rev() {
120                extrinsics.push_front(inherent_extrinsic)
121            }
122        }
123
124        Ok(Self { extrinsics, api })
125    }
126
127    fn execute_extrinsics(&mut self) -> Result<(), Error> {
129        for (index, xt) in self.extrinsics.iter().enumerate() {
130            let res = self.api.execute_in_transaction(
131                |api: &TrieBackendApi<Client, Block, Backend, Exec>,
132                 backend: &TrieDeltaBackendFor<Backend::State, Block>,
133                 overlayed_changes: &mut OverlayedChanges<HashingFor<Block>>| {
134                    match api.apply_extrinsic(xt.clone(), backend, overlayed_changes) {
135                        Ok(Ok(_)) => TransactionOutcome::Commit(Ok(())),
136                        Ok(Err(tx_validity)) => TransactionOutcome::Rollback(Err(
137                            ApplyExtrinsicFailed::Validity(tx_validity).into(),
138                        )),
139                        Err(e) => TransactionOutcome::Rollback(Err(e)),
140                    }
141                },
142            );
143
144            if let Err(e) = res {
145                tracing::debug!("Apply extrinsic at index {index} failed: {e}");
146            }
147        }
148
149        Ok(())
150    }
151
152    fn collect_storage_changes(&mut self) -> Option<CollectedStorageChanges<HashingFor<Block>>> {
153        self.api.collect_storage_changes()
154    }
155
156    pub fn prepare_storage_changes_before(
158        &mut self,
159        extrinsic_index: usize,
160    ) -> Result<CollectedStorageChanges<HashingFor<Block>>, Error> {
161        for (index, xt) in self.extrinsics.iter().enumerate() {
162            if index == extrinsic_index {
163                return self
164                    .collect_storage_changes()
165                    .ok_or(Error::Execution(Box::new("No execution is done")));
166            }
167
168            self.api.execute_in_transaction(
170                |api: &TrieBackendApi<Client, Block, Backend, Exec>,
171                 backend: &TrieDeltaBackendFor<Backend::State, Block>,
172                 overlayed_changes: &mut OverlayedChanges<HashingFor<Block>>| {
173                    match api.apply_extrinsic(xt.clone(), backend, overlayed_changes) {
174                        Ok(Ok(_)) => TransactionOutcome::Commit(Ok(())),
175                        Ok(Err(tx_validity)) => TransactionOutcome::Rollback(Err(
176                            ApplyExtrinsicFailed::Validity(tx_validity).into(),
177                        )),
178                        Err(e) => TransactionOutcome::Rollback(Err(e)),
179                    }
180                },
181            )?;
182        }
183
184        Err(Error::Execution(Box::new(format!(
185            "Invalid extrinsic index, got: {}, max: {}",
186            extrinsic_index,
187            self.extrinsics.len()
188        ))))
189    }
190
191    pub fn prepare_storage_changes_before_finalize_block(
193        &mut self,
194    ) -> Result<CollectedStorageChanges<HashingFor<Block>>, Error> {
195        self.execute_extrinsics()?;
196        self.collect_storage_changes()
197            .ok_or(Error::Execution(Box::new("No execution is done")))
198    }
199
200    pub fn build(mut self) -> Result<BuiltBlock<Block>, Error> {
206        self.execute_extrinsics()?;
207        let header = self.api.execute_in_transaction(
208            |api: &TrieBackendApi<Client, Block, Backend, Exec>,
209             backend: &TrieDeltaBackendFor<Backend::State, Block>,
210             overlayed_changes: &mut OverlayedChanges<HashingFor<Block>>| {
211                match api.finalize_block(backend, overlayed_changes) {
212                    Ok(header) => TransactionOutcome::Commit(Ok(header)),
213                    Err(e) => TransactionOutcome::Rollback(Err(e)),
214                }
215            },
216        )?;
217
218        debug_assert_eq!(
219            header.extrinsics_root().clone(),
220            HashingFor::<Block>::ordered_trie_root(
221                self.extrinsics.iter().map(Encode::encode).collect(),
222                sp_core::storage::StateVersion::V1
223            ),
224        );
225
226        let storage_changes = self
227            .collect_storage_changes()
228            .expect("must always have the storage changes due to execution above");
229
230        Ok(BuiltBlock {
231            block: Block::new(header, self.extrinsics.into()),
232            storage_changes,
233        })
234    }
235
236    pub(crate) fn create_inherents(
240        api: &mut TrieBackendApi<Client, Block, Backend, Exec>,
241        inherent_data: sp_inherents::InherentData,
242    ) -> Result<VecDeque<Block::Extrinsic>, Error> {
243        let exts = api.execute_in_transaction(
244            |api: &TrieBackendApi<Client, Block, Backend, Exec>,
245             backend: &TrieDeltaBackendFor<Backend::State, Block>,
246             overlayed_changes: &mut OverlayedChanges<HashingFor<Block>>| {
247                TransactionOutcome::Rollback(api.inherent_extrinsics(
250                    inherent_data,
251                    backend,
252                    overlayed_changes,
253                ))
254            },
255        )?;
256        Ok(VecDeque::from(exts))
257    }
258}
259
260