|
3 | 3 | // see LICENSE for license details.
|
4 | 4 |
|
5 | 5 | use super::{OfflineClient, OfflineClientT};
|
| 6 | +use crate::config::Header; |
6 | 7 | use crate::custom_values::CustomValuesClient;
|
7 | 8 | use crate::{
|
8 | 9 | backend::{
|
@@ -437,17 +438,13 @@ impl<T: Config> RuntimeUpdaterStream<T> {
|
437 | 438 | Err(err) => return Some(Err(err)),
|
438 | 439 | };
|
439 | 440 |
|
440 |
| - let latest_block_ref = match self.client.backend().latest_finalized_block_ref().await { |
441 |
| - Ok(block_ref) => block_ref, |
442 |
| - Err(e) => return Some(Err(e)), |
| 441 | + let at = match wait_for_runtime_upgrade(&self.client, &runtime_version).await { |
| 442 | + Some(Ok(at)) => at, |
| 443 | + Some(Err(err)) => return Some(Err(err)), |
| 444 | + None => return None, |
443 | 445 | };
|
444 | 446 |
|
445 |
| - let metadata = match OnlineClient::fetch_metadata( |
446 |
| - self.client.backend(), |
447 |
| - latest_block_ref.hash(), |
448 |
| - ) |
449 |
| - .await |
450 |
| - { |
| 447 | + let metadata = match OnlineClient::fetch_metadata(self.client.backend(), at.hash()).await { |
451 | 448 | Ok(metadata) => metadata,
|
452 | 449 | Err(err) => return Some(Err(err)),
|
453 | 450 | };
|
@@ -484,3 +481,49 @@ impl Update {
|
484 | 481 | &self.metadata
|
485 | 482 | }
|
486 | 483 | }
|
| 484 | + |
| 485 | +/// Helper to wait until the runtime upgrade is applied on at finalized block. |
| 486 | +async fn wait_for_runtime_upgrade<T: Config>( |
| 487 | + client: &OnlineClient<T>, |
| 488 | + runtime_version: &RuntimeVersion, |
| 489 | +) -> Option<Result<T::Header, Error>> { |
| 490 | + use scale_value::At; |
| 491 | + |
| 492 | + let mut block_sub = match client.backend().stream_finalized_block_headers().await { |
| 493 | + Ok(s) => s, |
| 494 | + Err(err) => return Some(Err(err)), |
| 495 | + }; |
| 496 | + |
| 497 | + let head = loop { |
| 498 | + let (block, block_ref) = match block_sub.next().await? { |
| 499 | + Ok(n) => n, |
| 500 | + Err(err) => return Some(Err(err)), |
| 501 | + }; |
| 502 | + |
| 503 | + let key: Vec<scale_value::Value> = vec![]; |
| 504 | + let addr = crate::dynamic::storage("System", "LastRuntimeUpgrade", key); |
| 505 | + |
| 506 | + let chunk = match client.storage().at(block_ref).fetch(&addr).await { |
| 507 | + Ok(Some(v)) => v, |
| 508 | + Ok(None) => continue, |
| 509 | + Err(e) => return Some(Err(e)), |
| 510 | + }; |
| 511 | + |
| 512 | + let scale_val = match chunk.to_value() { |
| 513 | + Ok(v) => v, |
| 514 | + Err(e) => return Some(Err(e)), |
| 515 | + }; |
| 516 | + |
| 517 | + let spec_version = scale_val |
| 518 | + .at("spec_version") |
| 519 | + .and_then(|v| v.as_u128()) |
| 520 | + .expect("specVersion should exist on RuntimeVersion; qed") |
| 521 | + as u32; |
| 522 | + |
| 523 | + if spec_version >= runtime_version.spec_version { |
| 524 | + break block; |
| 525 | + } |
| 526 | + }; |
| 527 | + |
| 528 | + Some(Ok(head)) |
| 529 | +} |
0 commit comments