diff --git a/app-libs/stf/src/trusted_call.rs b/app-libs/stf/src/trusted_call.rs index 542fac2f48..a2ec6b05d8 100644 --- a/app-libs/stf/src/trusted_call.rs +++ b/app-libs/stf/src/trusted_call.rs @@ -53,7 +53,7 @@ use itp_stf_primitives::{ types::{AccountId, KeyPair, ShardIdentifier, Signature, TrustedOperation}, }; use itp_types::{ - parentchain::{ParentchainCall, ParentchainId, ProxyType}, + parentchain::{GenericMortality, ParentchainCall, ParentchainId, ProxyType}, Address, Moment, OpaqueCall, }; use itp_utils::stringify::account_id_to_string; @@ -340,9 +340,18 @@ where vault_transfer_call, )); let parentchain_call = match parentchain_id { - ParentchainId::Integritee => ParentchainCall::Integritee(proxy_call), - ParentchainId::TargetA => ParentchainCall::TargetA(proxy_call), - ParentchainId::TargetB => ParentchainCall::TargetB(proxy_call), + ParentchainId::Integritee => ParentchainCall::Integritee { + call: proxy_call, + mortality: GenericMortality::immortal(), + }, + ParentchainId::TargetA => ParentchainCall::TargetA { + call: proxy_call, + mortality: GenericMortality::immortal(), + }, + ParentchainId::TargetB => ParentchainCall::TargetB { + call: proxy_call, + mortality: GenericMortality::immortal(), + }, }; calls.push(parentchain_call); Ok(()) @@ -365,15 +374,18 @@ where shield_funds(who, value)?; // Send proof of execution on chain. - calls.push(ParentchainCall::Integritee(OpaqueCall::from_tuple(&( - node_metadata_repo - .get_from_metadata(|m| m.publish_hash_call_indexes()) - .map_err(|_| StfError::InvalidMetadata)? - .map_err(|_| StfError::InvalidMetadata)?, - call_hash, - Vec::::new(), - b"shielded some funds!".to_vec(), - )))); + calls.push(ParentchainCall::Integritee { + call: OpaqueCall::from_tuple(&( + node_metadata_repo + .get_from_metadata(|m| m.publish_hash_call_indexes()) + .map_err(|_| StfError::InvalidMetadata)? + .map_err(|_| StfError::InvalidMetadata)?, + call_hash, + Vec::::new(), + b"shielded some funds!".to_vec(), + )), + mortality: GenericMortality::immortal(), + }); Ok(()) }, TrustedCall::timestamp_set(enclave_account, now, parentchain_id) => { diff --git a/core-primitives/extrinsics-factory/src/lib.rs b/core-primitives/extrinsics-factory/src/lib.rs index fd55dfccb7..4dc9b964b0 100644 --- a/core-primitives/extrinsics-factory/src/lib.rs +++ b/core-primitives/extrinsics-factory/src/lib.rs @@ -38,9 +38,12 @@ use itp_node_api::{ metadata::{provider::AccessNodeMetadata, NodeMetadata}, }; use itp_nonce_cache::{MutateNonce, Nonce}; -use itp_types::{parentchain::AccountId, OpaqueCall}; +use itp_types::{ + parentchain::{AccountId, GenericMortality}, + OpaqueCall, +}; use sp_core::H256; -use sp_runtime::{generic::Era, OpaqueExtrinsic}; +use sp_runtime::OpaqueExtrinsic; use std::{sync::Arc, vec::Vec}; use substrate_api_client::ac_compose_macros::compose_extrinsic_offline; @@ -55,7 +58,7 @@ pub mod mock; pub trait CreateExtrinsics { fn create_extrinsics( &self, - calls: &[OpaqueCall], + calls: &[(OpaqueCall, GenericMortality)], extrinsics_params: Option, ) -> Result>; } @@ -108,16 +111,12 @@ where { fn create_extrinsics( &self, - calls: &[OpaqueCall], + calls: &[(OpaqueCall, GenericMortality)], extrinsics_params: Option, ) -> Result> { let mut nonce_lock = self.nonce_cache.load_for_mutation()?; let mut nonce_value = nonce_lock.0; - let additional_extrinsic_params = extrinsics_params.unwrap_or_else(|| { - ParentchainAdditionalParams::new().era(Era::Immortal, self.genesis_hash).tip(0) - }); - let (runtime_spec_version, runtime_transaction_version) = self.node_metadata_repository.get_from_metadata(|m| { (m.get_runtime_version(), m.get_runtime_transaction_version()) @@ -125,7 +124,15 @@ where let extrinsics_buffer: Vec = calls .iter() - .map(|call| { + .map(|(call, mortality)| { + let additional_extrinsic_params = extrinsics_params.unwrap_or_else(|| { + ParentchainAdditionalParams::new() + .era( + mortality.era, + mortality.mortality_checkpoint.unwrap_or(self.genesis_hash), + ) + .tip(0) + }); let extrinsic_params = ParentchainExtrinsicParams::new( runtime_spec_version, runtime_transaction_version, diff --git a/core-primitives/extrinsics-factory/src/mock.rs b/core-primitives/extrinsics-factory/src/mock.rs index 4e1923210e..dfa6017a86 100644 --- a/core-primitives/extrinsics-factory/src/mock.rs +++ b/core-primitives/extrinsics-factory/src/mock.rs @@ -17,7 +17,7 @@ use crate::{error::Result, CreateExtrinsics}; use itp_node_api::api_client::ParentchainAdditionalParams; -use itp_types::OpaqueCall; +use itp_types::{parentchain::GenericMortality, OpaqueCall}; use sp_runtime::OpaqueExtrinsic; use std::vec::Vec; @@ -30,7 +30,7 @@ pub struct ExtrinsicsFactoryMock; impl CreateExtrinsics for ExtrinsicsFactoryMock { fn create_extrinsics( &self, - _calls: &[OpaqueCall], + _calls: &[(OpaqueCall, GenericMortality)], _additional_params: Option, ) -> Result> { // Intention was to map an OpaqueCall to some dummy OpaqueExtrinsic, diff --git a/core-primitives/stf-executor/src/executor.rs b/core-primitives/stf-executor/src/executor.rs index 566cf669cf..a61792ef1b 100644 --- a/core-primitives/stf-executor/src/executor.rs +++ b/core-primitives/stf-executor/src/executor.rs @@ -141,17 +141,17 @@ where for call in extrinsic_call_backs.clone() { match call { - ParentchainCall::Integritee(opaque_call) => trace!( - "trusted_call wants to send encoded call to [Integritee] parentchain: 0x{}", - hex::encode(opaque_call.encode()) + ParentchainCall::Integritee { call, mortality } => trace!( + "trusted_call wants to send encoded call to [Integritee] parentchain: 0x{} with mortality {:?}", + hex::encode(call.encode()), mortality ), - ParentchainCall::TargetA(opaque_call) => trace!( - "trusted_call wants to send encoded call to [TargetA] parentchain: 0x{}", - hex::encode(opaque_call.encode()) + ParentchainCall::TargetA { call, mortality } => trace!( + "trusted_call wants to send encoded call to [TargetA] parentchain: 0x{} with mortality {:?}", + hex::encode(call.encode()), mortality ), - ParentchainCall::TargetB(opaque_call) => trace!( - "trusted_call wants to send encoded call to [TargetB] parentchain: 0x{}", - hex::encode(opaque_call.encode()) + ParentchainCall::TargetB { call, mortality } => trace!( + "trusted_call wants to send encoded call to [TargetB] parentchain: 0x{} with mortality {:?}", + hex::encode(call.encode()), mortality ), } } diff --git a/core-primitives/types/src/parentchain.rs b/core-primitives/types/src/parentchain.rs index f8690e45ac..fc65172d3d 100644 --- a/core-primitives/types/src/parentchain.rs +++ b/core-primitives/types/src/parentchain.rs @@ -27,7 +27,9 @@ use serde::{Deserialize, Serialize}; pub use sidechain_primitives::SidechainBlockConfirmation; use sp_core::bounded::alloc; use sp_runtime::{ - generic::Header as HeaderG, traits::BlakeTwo256, DispatchError, MultiAddress, MultiSignature, + generic::{Era, Header as HeaderG}, + traits::BlakeTwo256, + DispatchError, MultiAddress, MultiSignature, }; use substrate_api_client::{ ac_node_api::StaticEvent, @@ -283,32 +285,45 @@ impl From for () { fn from(_: ParentchainError) -> Self {} } +// All info for additionalParam except tip whi +#[derive(Encode, Debug, Clone, PartialEq, Eq)] +pub struct GenericMortality { + pub era: Era, + pub mortality_checkpoint: Option, +} + +impl GenericMortality { + pub fn immortal() -> Self { + Self { era: Era::Immortal, mortality_checkpoint: None } + } +} + /// a wrapper to target calls to specific parentchains #[derive(Encode, Debug, Clone, PartialEq, Eq)] pub enum ParentchainCall { - Integritee(OpaqueCall), - TargetA(OpaqueCall), - TargetB(OpaqueCall), + Integritee { call: OpaqueCall, mortality: GenericMortality }, + TargetA { call: OpaqueCall, mortality: GenericMortality }, + TargetB { call: OpaqueCall, mortality: GenericMortality }, } impl ParentchainCall { - pub fn as_integritee(&self) -> Option { - if let Self::Integritee(call) = self { - Some(call.clone()) + pub fn as_integritee(&self) -> Option<(OpaqueCall, GenericMortality)> { + if let Self::Integritee { call, mortality } = self { + Some((call.clone(), mortality.clone())) } else { None } } - pub fn as_target_a(&self) -> Option { - if let Self::TargetA(call) = self { - Some(call.clone()) + pub fn as_target_a(&self) -> Option<(OpaqueCall, GenericMortality)> { + if let Self::TargetA { call, mortality } = self { + Some((call.clone(), mortality.clone())) } else { None } } - pub fn as_target_b(&self) -> Option { - if let Self::TargetB(call) = self { - Some(call.clone()) + pub fn as_target_b(&self) -> Option<(OpaqueCall, GenericMortality)> { + if let Self::TargetB { call, mortality } = self { + Some((call.clone(), mortality.clone())) } else { None } @@ -316,19 +331,19 @@ impl ParentchainCall { pub fn as_opaque_call_for(&self, parentchain_id: ParentchainId) -> Option { match parentchain_id { ParentchainId::Integritee => - if let Self::Integritee(call) = self { + if let Self::Integritee { call, mortality: _ } = self { Some(call.clone()) } else { None }, ParentchainId::TargetA => - if let Self::TargetA(call) = self { + if let Self::TargetA { call, mortality: _ } = self { Some(call.clone()) } else { None }, ParentchainId::TargetB => - if let Self::TargetB(call) = self { + if let Self::TargetB { call, mortality: _ } = self { Some(call.clone()) } else { None diff --git a/core/offchain-worker-executor/src/executor.rs b/core/offchain-worker-executor/src/executor.rs index 30433d5012..f07b2cc33c 100644 --- a/core/offchain-worker-executor/src/executor.rs +++ b/core/offchain-worker-executor/src/executor.rs @@ -28,7 +28,10 @@ use itp_stf_interface::system_pallet::SystemPalletEventInterface; use itp_stf_primitives::{traits::TrustedCallVerification, types::TrustedOperationOrHash}; use itp_stf_state_handler::{handle_state::HandleState, query_shard_state::QueryShardState}; use itp_top_pool_author::traits::AuthorApi; -use itp_types::{parentchain::ParentchainCall, OpaqueCall, ShardIdentifier, H256}; +use itp_types::{ + parentchain::{GenericMortality, ParentchainCall}, + OpaqueCall, ShardIdentifier, H256, +}; use log::*; use sp_runtime::traits::Block; use std::{marker::PhantomData, sync::Arc, time::Duration, vec::Vec}; @@ -185,15 +188,15 @@ impl< } fn send_parentchain_effects(&self, parentchain_effects: Vec) -> Result<()> { - let integritee_calls: Vec = parentchain_effects + let integritee_calls: Vec<(OpaqueCall, GenericMortality)> = parentchain_effects .iter() .filter_map(|parentchain_call| parentchain_call.as_integritee()) .collect(); - let target_a_calls: Vec = parentchain_effects + let target_a_calls: Vec<(OpaqueCall, GenericMortality)> = parentchain_effects .iter() .filter_map(|parentchain_call| parentchain_call.as_target_a()) .collect(); - let target_b_calls: Vec = parentchain_effects + let target_b_calls: Vec<(OpaqueCall, GenericMortality)> = parentchain_effects .iter() .filter_map(|parentchain_call| parentchain_call.as_target_b()) .collect(); @@ -204,10 +207,10 @@ impl< target_b_calls.len() ); if !target_a_calls.is_empty() { - warn!("sending extrinsics to target A unimplemented") + warn!("sending extrinsics to target A unimplemented for OCW") }; if !target_b_calls.is_empty() { - warn!("sending extrinsics to target B unimplemented") + warn!("sending extrinsics to target B unimplemented for OCW") }; let extrinsics = diff --git a/core/parentchain/block-importer/src/block_importer.rs b/core/parentchain/block-importer/src/block_importer.rs index becb9e9a6b..7302395e9c 100644 --- a/core/parentchain/block-importer/src/block_importer.rs +++ b/core/parentchain/block-importer/src/block_importer.rs @@ -28,12 +28,12 @@ use itp_extrinsics_factory::CreateExtrinsics; use itp_stf_executor::traits::StfUpdateState; use itp_stf_interface::ShardCreationInfo; use itp_types::{ - parentchain::{IdentifyParentchain, ParentchainId}, + parentchain::{GenericMortality, IdentifyParentchain, ParentchainId}, OpaqueCall, H256, }; use log::*; use sp_runtime::{ - generic::SignedBlock as SignedBlockG, + generic::{Era, SignedBlock as SignedBlockG}, traits::{Block as ParentchainBlockTrait, Header as HeaderT, NumberFor}, }; use std::{marker::PhantomData, sync::Arc, vec, vec::Vec}; @@ -118,7 +118,7 @@ impl< blocks_to_import: Vec, events_to_import: Vec>, ) -> Result<()> { - let mut calls = Vec::::new(); + let mut calls = Vec::<(OpaqueCall, GenericMortality)>::new(); let id = self.validator_accessor.parentchain_id(); debug!( @@ -172,7 +172,15 @@ impl< .execute_indirect_calls_in_extrinsics(&block, &raw_events) { Ok(Some(confirm_processed_parentchain_block_call)) => { - calls.push(confirm_processed_parentchain_block_call); + let opaque_call = confirm_processed_parentchain_block_call; + // if we have significant downtime, this mortality means we will not confirm all imported blocks + /* + let mortality = GenericMortality { + era: Era::Mortal(300, 0), + mortality_checkpoint: Some(block.hash()), + };*/ + let mortality = GenericMortality::immortal(); + calls.push((opaque_call, mortality)); }, Ok(None) => trace!("omitting confirmation call to non-integritee parentchain"), Err(e) => error!("[{:?}] Error executing relevant extrinsics: {:?}", id, e), @@ -186,7 +194,7 @@ impl< ); } - // Create extrinsics for all `unshielding` and `block processed` calls we've gathered. + // Create extrinsics for all `block processed` calls we've gathered. let parentchain_extrinsics = self.extrinsics_factory.create_extrinsics(calls.as_slice(), None)?; diff --git a/enclave-runtime/src/attestation.rs b/enclave-runtime/src/attestation.rs index f91a0ad7e4..72a8590d79 100644 --- a/enclave-runtime/src/attestation.rs +++ b/enclave-runtime/src/attestation.rs @@ -46,7 +46,7 @@ use itp_node_api::metadata::{ }; use itp_node_api_metadata::NodeMetadata; use itp_settings::worker::MR_ENCLAVE_SIZE; -use itp_types::OpaqueCall; +use itp_types::{parentchain::GenericMortality, OpaqueCall}; use itp_utils::write_slice_and_whitespace_pad; use log::*; use sgx_types::*; @@ -390,7 +390,8 @@ pub fn generate_ias_skip_ra_extrinsic_from_der_cert_internal( fn create_extrinsics(call: OpaqueCall) -> EnclaveResult { let extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; - let extrinsics = extrinsics_factory.create_extrinsics(&[call], None)?; + let extrinsics = + extrinsics_factory.create_extrinsics(&[(call, GenericMortality::immortal())], None)?; Ok(extrinsics[0].clone()) } diff --git a/enclave-runtime/src/shard_config.rs b/enclave-runtime/src/shard_config.rs index a22e79eb0d..3ee7cf2e47 100644 --- a/enclave-runtime/src/shard_config.rs +++ b/enclave-runtime/src/shard_config.rs @@ -38,6 +38,7 @@ use itp_types::{ use itp_utils::hex::hex_encode; use log::*; +use itp_types::parentchain::GenericMortality; use teerex_primitives::EnclaveFingerprint; pub(crate) fn init_shard_config(shard: ShardIdentifier) -> EnclaveResult<()> { @@ -56,7 +57,7 @@ pub(crate) fn init_shard_config(shard: ShardIdentifier) -> EnclaveResult<()> { let opaque_call = OpaqueCall::from_tuple(&(call, shard, shard_config, BlockNumber::from(0u8))); debug!("encoded call: {}", hex_encode(opaque_call.encode().as_slice())); let xts = extrinsics_factory - .create_extrinsics(&[opaque_call], None) + .create_extrinsics(&[(opaque_call, GenericMortality::immortal())], None) .map_err(|e| Error::Other(e.into()))?; info!("Initializing or touching shard config on integritee network. awaiting inclusion before continuing"); diff --git a/enclave-runtime/src/shard_vault.rs b/enclave-runtime/src/shard_vault.rs index 0f2ea89d8b..e62ec64da2 100644 --- a/enclave-runtime/src/shard_vault.rs +++ b/enclave-runtime/src/shard_vault.rs @@ -43,7 +43,7 @@ use itp_sgx_crypto::key_repository::AccessKey; use itp_stf_interface::{parentchain_pallet::ParentchainPalletInstancesInterface, ShardVaultQuery}; use itp_stf_state_handler::{handle_state::HandleState, query_shard_state::QueryShardState}; use itp_types::{ - parentchain::{AccountId, Address, Balance, ParentchainId, ProxyType}, + parentchain::{AccountId, Address, Balance, GenericMortality, ParentchainId, ProxyType}, OpaqueCall, ShardIdentifier, }; use log::*; @@ -189,7 +189,8 @@ pub(crate) fn init_proxied_shard_vault_internal( )); info!("[{:?}] vault funding call: 0x{}", parentchain_id, hex::encode(call.0.clone())); - let xts = enclave_extrinsics_factory.create_extrinsics(&[call], None)?; + let xts = enclave_extrinsics_factory + .create_extrinsics(&[(call, GenericMortality::immortal())], None)?; //this extrinsic must be included in a block before we can move on. otherwise the next will fail ocall_api.send_to_parentchain(xts, &parentchain_id, true)?; @@ -212,7 +213,8 @@ pub(crate) fn init_proxied_shard_vault_internal( )); info!("[{:?}] add proxy call: 0x{}", parentchain_id, hex::encode(call.0.clone())); - let xts = vault_extrinsics_factory.create_extrinsics(&[call], None)?; + let xts = vault_extrinsics_factory + .create_extrinsics(&[(call, GenericMortality::immortal())], None)?; ocall_api.send_to_parentchain(xts, &parentchain_id, false)?; Ok(()) @@ -266,7 +268,8 @@ pub(crate) fn add_shard_vault_proxy( )); info!("proxied add proxy call: 0x{}", hex::encode(call.0.clone())); - let xts = enclave_extrinsics_factory.create_extrinsics(&[call], None)?; + let xts = enclave_extrinsics_factory + .create_extrinsics(&[(call, GenericMortality::immortal())], None)?; ocall_api.send_to_parentchain(xts, &ParentchainId::Integritee, false)?; Ok(()) diff --git a/enclave-runtime/src/top_pool_execution.rs b/enclave-runtime/src/top_pool_execution.rs index e9dd8402d2..ed533a5117 100644 --- a/enclave-runtime/src/top_pool_execution.rs +++ b/enclave-runtime/src/top_pool_execution.rs @@ -56,7 +56,7 @@ use itp_sgx_crypto::key_repository::AccessKey; use itp_stf_state_handler::query_shard_state::QueryShardState; use itp_time_utils::duration_now; use itp_types::{ - parentchain::{ParentchainCall, ParentchainId, SidechainBlockConfirmation}, + parentchain::{GenericMortality, ParentchainCall, ParentchainId, SidechainBlockConfirmation}, Block, OpaqueCall, H256, }; use its_primitives::{ @@ -333,7 +333,7 @@ where debug!("Proposing {} sidechain block(s) (broadcasting to peers)", blocks.len()); ocall_api.propose_sidechain_blocks(blocks)?; - let calls: Vec = parentchain_calls + let calls: Vec<(OpaqueCall, GenericMortality)> = parentchain_calls .iter() .filter_map(|parentchain_call| parentchain_call.as_integritee()) .collect(); @@ -344,7 +344,7 @@ where let validator_access = get_validator_accessor_from_integritee_solo_or_parachain()?; validator_access.execute_mut_on_validator(|v| v.send_extrinsics(xts))?; } - let calls: Vec = parentchain_calls + let calls: Vec<(OpaqueCall, GenericMortality)> = parentchain_calls .iter() .filter_map(|parentchain_call| parentchain_call.as_target_a()) .collect(); @@ -355,7 +355,7 @@ where let validator_access = get_validator_accessor_from_target_a_solo_or_parachain()?; validator_access.execute_mut_on_validator(|v| v.send_extrinsics(xts))?; } - let calls: Vec = parentchain_calls + let calls: Vec<(OpaqueCall, GenericMortality)> = parentchain_calls .iter() .filter_map(|parentchain_call| parentchain_call.as_target_b()) .collect(); diff --git a/sidechain/consensus/common/src/block_import_confirmation_handler.rs b/sidechain/consensus/common/src/block_import_confirmation_handler.rs index ec8a9f29da..7b0757d94e 100644 --- a/sidechain/consensus/common/src/block_import_confirmation_handler.rs +++ b/sidechain/consensus/common/src/block_import_confirmation_handler.rs @@ -23,7 +23,10 @@ use itp_extrinsics_factory::CreateExtrinsics; use itp_node_api_metadata::{pallet_sidechain::SidechainCallIndexes, NodeMetadataTrait}; use itp_node_api_metadata_provider::AccessNodeMetadata; use itp_settings::worker::BLOCK_NUMBER_FINALIZATION_DIFF; -use itp_types::{parentchain::SidechainBlockConfirmation, OpaqueCall, ShardIdentifier}; +use itp_types::{ + parentchain::{GenericMortality, SidechainBlockConfirmation}, + OpaqueCall, ShardIdentifier, +}; use its_primitives::traits::Header as HeaderTrait; use log::*; use sp_runtime::traits::Block as ParentchainBlockTrait; @@ -130,7 +133,7 @@ impl< let xts = self .extrinsics_factory - .create_extrinsics(&[opaque_call], None) + .create_extrinsics(&[(opaque_call, GenericMortality::immortal())], None) .map_err(|e| Error::Other(e.into()))?; debug!("Sending sidechain block import confirmation extrinsic..");