|
1 | 1 | use super::*; |
2 | 2 | pub use ext_types::*; |
| 3 | +use rayon::prelude::*; |
3 | 4 |
|
4 | 5 | /// State RPC errors. |
5 | 6 | #[derive(Debug, thiserror::Error)] |
@@ -86,63 +87,68 @@ where |
86 | 87 | return Err(Error::ResourceLimited("Too large number of blocks".into())); |
87 | 88 | } |
88 | 89 |
|
89 | | - let api = client.runtime_api(); |
90 | | - let mut changes = vec![]; |
| 90 | + let mut headers = std::collections::VecDeque::new(); |
| 91 | + |
91 | 92 | let mut this_block = to; |
92 | 93 |
|
93 | 94 | loop { |
94 | 95 | let id = BlockId::Hash(this_block); |
95 | | - let mut header = header(client, id)?; |
96 | | - let extrinsics = client |
97 | | - .block_body(&id) |
98 | | - .map_err(|e| Error::invalid_block(id, e))? |
99 | | - .ok_or_else(|| Error::invalid_block(id, "block body not found"))?; |
100 | | - let parent_hash = *header.parent_hash(); |
101 | | - let parent_id = BlockId::Hash(parent_hash); |
102 | | - |
103 | | - if (*header.number()).into() == 0u64 { |
104 | | - let state = backend |
105 | | - .state_at(id) |
106 | | - .map_err(|e| Error::invalid_block(parent_id, e))?; |
107 | | - changes.push(StorageChanges { |
108 | | - main_storage_changes: state |
109 | | - .pairs() |
110 | | - .into_iter() |
111 | | - .map(|(k, v)| (StorageKey(k), Some(StorageKey(v)))) |
112 | | - .collect(), |
113 | | - child_storage_changes: vec![], |
114 | | - }); |
| 96 | + let header = header(client, id)?; |
| 97 | + let parent = *header.parent_hash(); |
| 98 | + headers.push_front((id, header)); |
| 99 | + if this_block == from { |
115 | 100 | break; |
116 | 101 | } |
| 102 | + this_block = parent; |
| 103 | + } |
117 | 104 |
|
118 | | - // Remove all `Seal`s as they are added by the consensus engines after building the block. |
119 | | - // On import they are normally removed by the consensus engine. |
120 | | - header.digest_mut().logs.retain(|d| d.as_seal().is_none()); |
121 | | - |
122 | | - let block = Block::new(header, extrinsics); |
123 | | - api.execute_block(&parent_id, block) |
124 | | - .map_err(|e| Error::invalid_block(id, e))?; |
| 105 | + headers |
| 106 | + .into_par_iter() |
| 107 | + .map(|(id, mut header)| -> Result<_, Error> { |
| 108 | + let api = client.runtime_api(); |
| 109 | + if (*header.number()).into() == 0u64 { |
| 110 | + let state = backend |
| 111 | + .state_at(id) |
| 112 | + .map_err(|e| Error::invalid_block(id, e))?; |
| 113 | + return Ok(StorageChanges { |
| 114 | + main_storage_changes: state |
| 115 | + .pairs() |
| 116 | + .into_iter() |
| 117 | + .map(|(k, v)| (StorageKey(k), Some(StorageKey(v)))) |
| 118 | + .collect(), |
| 119 | + child_storage_changes: vec![], |
| 120 | + }); |
| 121 | + } |
| 122 | + |
| 123 | + let extrinsics = client |
| 124 | + .block_body(&id) |
| 125 | + .map_err(|e| Error::invalid_block(id, e))? |
| 126 | + .ok_or_else(|| Error::invalid_block(id, "block body not found"))?; |
| 127 | + let parent_hash = *header.parent_hash(); |
| 128 | + let parent_id = BlockId::Hash(parent_hash); |
| 129 | + |
| 130 | + // Remove all `Seal`s as they are added by the consensus engines after building the block. |
| 131 | + // On import they are normally removed by the consensus engine. |
| 132 | + header.digest_mut().logs.retain(|d| d.as_seal().is_none()); |
| 133 | + |
| 134 | + let block = Block::new(header, extrinsics); |
| 135 | + api.execute_block(&parent_id, block) |
| 136 | + .map_err(|e| Error::invalid_block(id, e))?; |
125 | 137 |
|
126 | | - let state = backend |
127 | | - .state_at(parent_id) |
128 | | - .map_err(|e| Error::invalid_block(parent_id, e))?; |
| 138 | + let state = backend |
| 139 | + .state_at(parent_id) |
| 140 | + .map_err(|e| Error::invalid_block(parent_id, e))?; |
129 | 141 |
|
130 | | - let storage_changes = api |
131 | | - .into_storage_changes(&state, parent_hash) |
132 | | - .map_err(|e| Error::invalid_block(parent_id, e))?; |
| 142 | + let storage_changes = api |
| 143 | + .into_storage_changes(&state, parent_hash) |
| 144 | + .map_err(|e| Error::invalid_block(parent_id, e))?; |
133 | 145 |
|
134 | | - changes.push(StorageChanges { |
135 | | - main_storage_changes: storage_changes.main_storage_changes.into_(), |
136 | | - child_storage_changes: storage_changes.child_storage_changes.into_(), |
137 | | - }); |
138 | | - if this_block == from { |
139 | | - break; |
140 | | - } else { |
141 | | - this_block = parent_hash; |
142 | | - } |
143 | | - } |
144 | | - changes.reverse(); |
145 | | - Ok(changes) |
| 146 | + Ok(StorageChanges { |
| 147 | + main_storage_changes: storage_changes.main_storage_changes.into_(), |
| 148 | + child_storage_changes: storage_changes.child_storage_changes.into_(), |
| 149 | + }) |
| 150 | + }) |
| 151 | + .collect() |
146 | 152 | } |
147 | 153 |
|
148 | 154 | // Stuffs to convert ChildStorageCollection and StorageCollection types, |
|
0 commit comments