Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make enclave extrinsics mortal #1637

Merged
merged 11 commits into from
Nov 6, 2024
26 changes: 25 additions & 1 deletion app-libs/stf/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ use itp_stf_primitives::{
types::AccountId,
};
use itp_storage::{storage_double_map_key, storage_map_key, storage_value_key, StorageHasher};
use itp_types::parentchain::{Hash, ParentchainId};
use itp_types::parentchain::{BlockNumber, GenericMortality, Hash, ParentchainId};
use itp_utils::stringify::account_id_to_string;
use log::*;
use sp_runtime::generic::Era;
use std::prelude::v1::*;

pub fn get_storage_value<V: Decode>(
Expand Down Expand Up @@ -193,3 +194,26 @@ pub fn wrap_bytes(data: &[u8]) -> Vec<u8> {

bytes_wrapped
}

pub fn get_mortality(
parentchain_id: ParentchainId,
blocks_to_live: BlockNumber,
) -> Option<GenericMortality> {
let (maybe_number, maybe_hash) = match parentchain_id {
ParentchainId::Integritee =>
(ParentchainIntegritee::block_number(), ParentchainIntegritee::block_hash()),
ParentchainId::TargetA =>
(ParentchainTargetA::block_number(), ParentchainTargetA::block_hash()),
ParentchainId::TargetB =>
(ParentchainTargetB::block_number(), ParentchainTargetB::block_hash()),
};
if let Some(number) = maybe_number {
if let Some(hash) = maybe_hash {
return Some(GenericMortality {
era: Era::mortal(blocks_to_live.into(), number.into()),
mortality_checkpoint: Some(hash),
})
}
}
None
}
36 changes: 21 additions & 15 deletions app-libs/stf/src/trusted_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use crate::evm_helpers::{create_code_hash, evm_create2_address, evm_create_addre
use crate::{
guess_the_number::GuessTheNumberTrustedCall,
helpers::{
enclave_signer_account, ensure_enclave_signer_account, shard_vault,
enclave_signer_account, ensure_enclave_signer_account, get_mortality, shard_vault,
shielding_target_genesis_hash, wrap_bytes,
},
Getter, STF_SHIELDING_FEE_AMOUNT_DIVIDER,
Expand All @@ -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;
Expand Down Expand Up @@ -330,7 +330,7 @@ where
Address::from(beneficiary),
Compact(value),
));
let proxy_call = OpaqueCall::from_tuple(&(
let call = OpaqueCall::from_tuple(&(
node_metadata_repo
.get_from_metadata(|m| m.proxy_call_indexes())
.map_err(|_| StfError::InvalidMetadata)?
Expand All @@ -339,10 +339,13 @@ where
None::<ProxyType>,
vault_transfer_call,
));
let mortality =
get_mortality(parentchain_id, 32).unwrap_or_else(GenericMortality::immortal);

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, mortality },
ParentchainId::TargetA => ParentchainCall::TargetA { call, mortality },
ParentchainId::TargetB => ParentchainCall::TargetB { call, mortality },
};
calls.push(parentchain_call);
Ok(())
Expand All @@ -365,15 +368,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::<itp_types::H256>::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::<itp_types::H256>::new(),
b"shielded some funds!".to_vec(),
)),
mortality: GenericMortality::immortal(),
clangenb marked this conversation as resolved.
Show resolved Hide resolved
});
Ok(())
},
TrustedCall::timestamp_set(enclave_account, now, parentchain_id) => {
Expand Down
36 changes: 24 additions & 12 deletions core-primitives/extrinsics-factory/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -55,7 +58,7 @@ pub mod mock;
pub trait CreateExtrinsics {
fn create_extrinsics(
&self,
calls: &[OpaqueCall],
calls: &[(OpaqueCall, GenericMortality)],
extrinsics_params: Option<ParentchainAdditionalParams>,
) -> Result<Vec<OpaqueExtrinsic>>;
}
Expand Down Expand Up @@ -108,24 +111,28 @@ where
{
fn create_extrinsics(
&self,
calls: &[OpaqueCall],
calls: &[(OpaqueCall, GenericMortality)],
extrinsics_params: Option<ParentchainAdditionalParams>,
) -> Result<Vec<OpaqueExtrinsic>> {
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())
})?;

let extrinsics_buffer: Vec<OpaqueExtrinsic> = 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,
Expand Down Expand Up @@ -172,7 +179,10 @@ pub mod tests {
node_metadata_repo,
);

let opaque_calls = [OpaqueCall(vec![3u8; 42]), OpaqueCall(vec![12u8, 78])];
let opaque_calls = [
(OpaqueCall(vec![3u8; 42]), GenericMortality::immortal()),
(OpaqueCall(vec![12u8, 78]), GenericMortality::immortal()),
brenzi marked this conversation as resolved.
Show resolved Hide resolved
];
let xts = extrinsics_factory.create_extrinsics(&opaque_calls, None).unwrap();

assert_eq!(opaque_calls.len(), xts.len());
Expand All @@ -197,8 +207,10 @@ pub mod tests {
StaticExtrinsicSigner::<_, PairSignature>::new(test_account2()),
nonce_cache2.clone(),
);

let opaque_calls = [OpaqueCall(vec![3u8; 42]), OpaqueCall(vec![12u8, 78])];
let opaque_calls = [
(OpaqueCall(vec![3u8; 42]), GenericMortality::immortal()),
(OpaqueCall(vec![12u8, 78]), GenericMortality::immortal()),
];
let xts = extrinsics_factory.create_extrinsics(&opaque_calls, None).unwrap();

assert_eq!(opaque_calls.len(), xts.len());
Expand Down
4 changes: 2 additions & 2 deletions core-primitives/extrinsics-factory/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -30,7 +30,7 @@ pub struct ExtrinsicsFactoryMock;
impl CreateExtrinsics for ExtrinsicsFactoryMock {
fn create_extrinsics(
&self,
_calls: &[OpaqueCall],
_calls: &[(OpaqueCall, GenericMortality)],
_additional_params: Option<ParentchainAdditionalParams>,
) -> Result<Vec<OpaqueExtrinsic>> {
// Intention was to map an OpaqueCall to some dummy OpaqueExtrinsic,
Expand Down
18 changes: 9 additions & 9 deletions core-primitives/stf-executor/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
),
}
}
Expand Down
8 changes: 5 additions & 3 deletions core-primitives/stf-executor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ mod tests {
use super::*;
use itp_sgx_externalities::SgxExternalities;
use itp_test::mock::stf_mock::{GetterMock, TrustedCallSignedMock};
use itp_types::OpaqueCall;
use itp_types::{parentchain::GenericMortality, OpaqueCall};

#[test]
fn is_success_works() {
Expand Down Expand Up @@ -234,8 +234,10 @@ mod tests {
int: u8,
) -> (ExecutedOperation<TrustedCallSignedMock, GetterMock>, H256) {
let hash = H256::from([int; 32]);
let opaque_call: Vec<ParentchainCall> =
vec![ParentchainCall::Integritee(OpaqueCall(vec![int; 10]))];
let opaque_call: Vec<ParentchainCall> = vec![ParentchainCall::Integritee {
call: OpaqueCall(vec![int; 10]),
mortality: GenericMortality::immortal(),
}];
let operation =
ExecutedOperation::success(hash, TrustedOperationOrHash::Hash(hash), opaque_call);
(operation, hash)
Expand Down
47 changes: 31 additions & 16 deletions core-primitives/types/src/parentchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -283,52 +285,65 @@ impl From<ParentchainError> 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<Hash>,
}

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<OpaqueCall> {
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<OpaqueCall> {
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<OpaqueCall> {
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
}
}
pub fn as_opaque_call_for(&self, parentchain_id: ParentchainId) -> Option<OpaqueCall> {
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
Expand Down
15 changes: 9 additions & 6 deletions core/offchain-worker-executor/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -185,15 +188,15 @@ impl<
}

fn send_parentchain_effects(&self, parentchain_effects: Vec<ParentchainCall>) -> Result<()> {
let integritee_calls: Vec<OpaqueCall> = 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<OpaqueCall> = 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<OpaqueCall> = parentchain_effects
let target_b_calls: Vec<(OpaqueCall, GenericMortality)> = parentchain_effects
.iter()
.filter_map(|parentchain_call| parentchain_call.as_target_b())
.collect();
Expand All @@ -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 =
Expand Down
Loading
Loading