Skip to content

Commit

Permalink
Fix initial sync on target A/B by fixing mortality checkpoint source …
Browse files Browse the repository at this point in the history
…and ancestry mismatch error (#1666)

* fix mortality checkpoint parentchain_id and add logs

* event log declutter

* try to fix import queue mismatch

* remove shield confirmation extrinsic. never used

* cleanup

* log cleanup

* cleanup

* TargetX creation header is now latest finalized, not latest

* logging

* enable target-b shielding and make account-funding more robust

* clippy
  • Loading branch information
brenzi authored Dec 20, 2024
1 parent 8a08a89 commit 0d56e12
Show file tree
Hide file tree
Showing 17 changed files with 224 additions and 173 deletions.
224 changes: 112 additions & 112 deletions Cargo.lock

Large diffs are not rendered by default.

17 changes: 15 additions & 2 deletions app-libs/parentchain-interface/src/event_subscriber.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ use alloc::sync::Arc;
use core::sync::atomic::{AtomicBool, Ordering};
use itp_api_client_types::ParentchainApi;
use itp_types::parentchain::{AddedSgxEnclave, BalanceTransfer, ExtrinsicFailed, ParentchainId};
use log::warn;
use log::{debug, warn};
use sp_runtime::DispatchError;
use substrate_api_client::SubscribeEvents;
use substrate_api_client::{ac_primitives::Header, GetChainInfo, SubscribeEvents};

pub fn subscribe_to_parentchain_events(
api: &ParentchainApi,
Expand All @@ -32,6 +32,17 @@ pub fn subscribe_to_parentchain_events(
let mut subscription = api.subscribe_events().unwrap();
while !shutdown_flag.load(Ordering::Relaxed) {
let events = subscription.next_events_from_metadata().unwrap().unwrap();
if let Some(header) = api.get_header(None).unwrap() {
let maybe_finalized_number =
api.get_header(api.get_finalized_head().unwrap()).unwrap().map(|h| h.number);
debug!(
"[{}] New block {} {} (finalized: {:?})",
parentchain_id,
header.number,
header.hash(),
maybe_finalized_number
);
};

for event in events.iter() {
let event = event.unwrap();
Expand Down Expand Up @@ -68,6 +79,8 @@ pub fn subscribe_to_parentchain_events(
_ => continue,
},
"ParaInclusion" => continue,
"Session" => continue,
"Grandpa" => continue,
"MessageQueue" => continue,
"TransactionPayment" => continue,
"Treasury" => continue,
Expand Down
58 changes: 51 additions & 7 deletions app-libs/parentchain-interface/src/target_b/event_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,71 @@
*/

use codec::Encode;
pub use ita_sgx_runtime::{Balance, Index};

use ita_stf::TrustedCallSigned;
use ita_stf::{Getter, TrustedCall, TrustedCallSigned};
use itc_parentchain_indirect_calls_executor::error::Error;
use itp_stf_primitives::traits::IndirectExecutor;
use itp_types::parentchain::{AccountId, FilterEvents, HandleParentchainEvents};
use itp_stf_primitives::{traits::IndirectExecutor, types::TrustedOperation};
use itp_types::parentchain::{
AccountId, FilterEvents, HandleParentchainEvents, ParentchainError, ParentchainId,
};
use itp_utils::hex::hex_encode;
use log::*;

pub struct ParentchainEventHandler {}

impl ParentchainEventHandler {
fn shield_funds<Executor: IndirectExecutor<TrustedCallSigned, Error>>(
executor: &Executor,
account: &AccountId,
amount: Balance,
) -> Result<(), Error> {
trace!("[TargetB] shielding for {:?} amount {}", account, amount,);
let shard = executor.get_default_shard();
// todo: ensure this parentchain is assigned for the shard vault!
let trusted_call = TrustedCall::balance_shield(
executor.get_enclave_account()?,
account.clone(),
amount,
ParentchainId::TargetB,
);
let signed_trusted_call = executor.sign_call_with_self(&trusted_call, &shard)?;
let trusted_operation =
TrustedOperation::<TrustedCallSigned, Getter>::indirect_call(signed_trusted_call);

let encrypted_trusted_call = executor.encrypt(&trusted_operation.encode())?;
executor.submit_trusted_call(shard, encrypted_trusted_call);

Ok(())
}
}

impl<Executor> HandleParentchainEvents<Executor, TrustedCallSigned, Error>
for ParentchainEventHandler
where
Executor: IndirectExecutor<TrustedCallSigned, Error>,
{
fn handle_events(
_executor: &Executor,
_events: impl FilterEvents,
_vault_account: &AccountId,
executor: &Executor,
events: impl FilterEvents,
vault_account: &AccountId,
) -> Result<(), Error> {
debug!("not handling any events for target B");
let filter_events = events.get_transfer_events();
trace!(
"[TargetB] filtering transfer events to shard vault account: {}",
hex_encode(vault_account.encode().as_slice())
);
if let Ok(events) = filter_events {
events
.iter()
.filter(|&event| event.to == *vault_account)
.try_for_each(|event| {
info!("[TargetB] found transfer event to shard vault account: {} will shield to {}", event.amount, hex_encode(event.from.encode().as_ref()));
Self::shield_funds(executor, &event.from, event.amount)
})
.map_err(|_| ParentchainError::ShieldFundsFailure)?;
}
Ok(())
}
}
23 changes: 1 addition & 22 deletions app-libs/stf/src/trusted_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,7 @@ use ita_sgx_runtime::{
ParentchainIntegritee, Runtime, SessionProxyCredentials, SessionProxyRole, System,
};
use itp_node_api::metadata::{provider::AccessNodeMetadata, NodeMetadataTrait};
use itp_node_api_metadata::{
pallet_balances::BalancesCallIndexes, pallet_enclave_bridge::EnclaveBridgeCallIndexes,
pallet_proxy::ProxyCallIndexes,
};
use itp_node_api_metadata::{pallet_balances::BalancesCallIndexes, pallet_proxy::ProxyCallIndexes};
use itp_stf_interface::ExecuteCall;
use itp_stf_primitives::{
error::StfError,
Expand All @@ -63,7 +60,6 @@ use sp_core::{
crypto::{AccountId32, UncheckedFrom},
ed25519,
};
use sp_io::hashing::blake2_256;
use sp_runtime::{traits::Verify, MultiAddress, MultiSignature};
use std::{format, prelude::v1::*, sync::Arc, vec};

Expand Down Expand Up @@ -275,7 +271,6 @@ where
// todo! spending limits according to role https://github.com/integritee-network/worker/issues/1656
let sender = self.call.sender_account().clone();

let call_hash = blake2_256(&self.call.encode());
let system_nonce = System::account_nonce(&sender);
ensure!(self.nonce == system_nonce, Self::Error::InvalidNonce(self.nonce, system_nonce));

Expand Down Expand Up @@ -419,22 +414,6 @@ where
std::println!("⣿STF⣿ 🛡 will shield to {}", account_id_to_string(&who));
shield_funds(&who, value)?;
store_note(&enclave_account, self.call, vec![who])?;

// Send proof of execution on chain.
let mortality =
get_mortality(parentchain_id, 32).unwrap_or_else(GenericMortality::immortal);
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,
});
Ok(())
},
TrustedCall::timestamp_set(enclave_account, now, parentchain_id) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use crate::{
error::{Error, Result},
DispatchBlockImport,
};
use core::cmp::min;
use itc_parentchain_block_importer::ImportParentchainBlocks;
use itp_import_queue::{PeekQueue, PopFromQueue, PushToQueue};
use log::trace;
Expand Down Expand Up @@ -182,18 +183,18 @@ where
let blocks_to_import =
self.import_queue.pop_until(predicate).map_err(Error::ImportQueue)?;

let events_to_import = self
.events_queue
.pop_from_front_until(blocks_to_import.len())
.map_err(Error::ImportQueue)?;
let depth = min(self.events_queue.peek_queue_size().unwrap_or(0), blocks_to_import.len());
let events_to_import =
self.events_queue.pop_from_front_until(depth).map_err(Error::ImportQueue)?;

let latest_imported_block = blocks_to_import.last().map(|b| (*b).clone());
let parentchain_id = self.block_importer.parentchain_id();
trace!(
"[{:?}] Import of parentchain blocks and events has been triggered, importing {} blocks and {} events from queue",
"[{:?}] Import of parentchain blocks and events has been triggered, importing {} blocks and {} events of {} blocks from queue",
parentchain_id,
blocks_to_import.len(),
events_to_import.len(),
depth
);

self.block_importer
Expand Down
6 changes: 4 additions & 2 deletions core/parentchain/block-importer/src/block_importer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ impl<
if let Some(creation_block) = self.shard_creation_info.for_parentchain(id) {
if signed_block.block.header().number < creation_block.number {
trace!(
"fast-syncing block import, ignoring any invocations before block {:}",
"[{:?}] fast-syncing block import, ignoring any invocations before block {:}",
id,
creation_block.number
);
continue
Expand Down Expand Up @@ -180,7 +181,8 @@ impl<
};
calls.push((opaque_call, mortality));
},
Ok(None) => trace!("omitting confirmation call to non-integritee parentchain"),
Ok(None) =>
trace!("[{:?}] omitting confirmation call to non-integritee parentchain", id),
Err(e) => error!("[{:?}] Error executing relevant extrinsics: {:?}", id, e),
};

Expand Down
2 changes: 1 addition & 1 deletion core/parentchain/light-client/src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ impl<B: Block, LightClientState: Decode + Encode + Debug> LightClientSealing
fs::File::open(self.db_path())
.or_else(|e| {
warn!(
"can't open db at {:?}. error: {:?}. trying restore backup at {:?}",
"can't open db at {:?}. reason: {:?}. trying restore backup at {:?}",
self.db_path(),
e,
self.backup_path()
Expand Down
4 changes: 2 additions & 2 deletions enclave-runtime/src/attestation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,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::ParentchainId, OpaqueCall};
use itp_utils::write_slice_and_whitespace_pad;
use log::*;
use sgx_types::*;
Expand Down Expand Up @@ -393,7 +393,7 @@ pub fn generate_ias_skip_ra_extrinsic_from_der_cert_internal(
fn create_extrinsics(call: OpaqueCall) -> EnclaveResult<OpaqueExtrinsic> {
let extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?;
let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?;
let mortality = try_mortality(64, &ocall_api);
let mortality = try_mortality(64, &ocall_api, ParentchainId::Integritee);
let extrinsics = extrinsics_factory.create_extrinsics(&[(call, mortality)], None)?;

Ok(extrinsics[0].clone())
Expand Down
2 changes: 1 addition & 1 deletion enclave-runtime/src/shard_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,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 ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?;
let mortality = try_mortality(64, &ocall_api);
let mortality = try_mortality(64, &ocall_api, ParentchainId::Integritee);
let xts = extrinsics_factory
.create_extrinsics(&[(opaque_call, mortality)], None)
.map_err(|e| Error::Other(e.into()))?;
Expand Down
6 changes: 3 additions & 3 deletions enclave-runtime/src/shard_vault.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ pub(crate) fn init_proxied_shard_vault_internal(
));

info!("[{:?}] vault funding call: 0x{}", parentchain_id, hex::encode(call.0.clone()));
let mortality = try_mortality(64, &ocall_api);
let mortality = try_mortality(64, &ocall_api, parentchain_id);
let xts = enclave_extrinsics_factory.create_extrinsics(&[(call, mortality)], None)?;

//this extrinsic must be included in a block before we can move on. otherwise the next will fail
Expand All @@ -213,7 +213,7 @@ pub(crate) fn init_proxied_shard_vault_internal(
));

info!("[{:?}] add proxy call: 0x{}", parentchain_id, hex::encode(call.0.clone()));
let mortality = try_mortality(64, &ocall_api);
let mortality = try_mortality(64, &ocall_api, parentchain_id);
let xts = vault_extrinsics_factory.create_extrinsics(&[(call, mortality)], None)?;

ocall_api.send_to_parentchain(xts, &parentchain_id, false)?;
Expand Down Expand Up @@ -268,7 +268,7 @@ pub(crate) fn add_shard_vault_proxy(
));

info!("proxied add proxy call: 0x{}", hex::encode(call.0.clone()));
let mortality = try_mortality(64, &ocall_api);
let mortality = try_mortality(64, &ocall_api, parentchain_id);
let xts = enclave_extrinsics_factory.create_extrinsics(&[(call, mortality)], None)?;

ocall_api.send_to_parentchain(xts, &ParentchainId::Integritee, false)?;
Expand Down
9 changes: 6 additions & 3 deletions enclave-runtime/src/teeracle/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@ use ita_oracle::{
use itp_component_container::ComponentGetter;
use itp_extrinsics_factory::CreateExtrinsics;
use itp_node_api::metadata::{pallet_teeracle::TeeracleCallIndexes, provider::AccessNodeMetadata};
use itp_types::{parentchain::GenericMortality, OpaqueCall};
use itp_types::{
parentchain::{GenericMortality, ParentchainId},
OpaqueCall,
};
use itp_utils::write_slice_and_whitespace_pad;
use log::*;
use sgx_types::sgx_status_t;
Expand All @@ -50,7 +53,7 @@ fn update_weather_data_internal(weather_info: WeatherInfo) -> Result<Vec<OpaqueE
let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?;

let mut extrinsic_calls: Vec<(OpaqueCall, GenericMortality)> = Vec::new();
let mortality = try_mortality(16, &ocall_api);
let mortality = try_mortality(16, &ocall_api, ParentchainId::Integritee);
let open_meteo_weather_oracle = create_open_meteo_weather_oracle(ocall_api);

match get_longitude(weather_info, open_meteo_weather_oracle) {
Expand Down Expand Up @@ -212,7 +215,7 @@ fn update_market_data_internal(
let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?;

let mut extrinsic_calls: Vec<(OpaqueCall, GenericMortality)> = Vec::new();
let mortality = try_mortality(16, &ocall_api);
let mortality = try_mortality(16, &ocall_api, ParentchainId::Integritee);
// Get the exchange rate
let trading_pair = TradingPair { crypto_currency, fiat_currency };

Expand Down
11 changes: 6 additions & 5 deletions enclave-runtime/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,12 +308,13 @@ pub(crate) fn get_stf_enclave_signer_from_solo_or_parachain() -> Result<Arc<Encl
Ok(stf_enclave_signer)
}

pub(crate) fn try_mortality(blocks_to_live: u64, ocall_api: &OcallApi) -> GenericMortality {
pub(crate) fn try_mortality(
blocks_to_live: u64,
ocall_api: &OcallApi,
parentchain_id: ParentchainId,
) -> GenericMortality {
let response: Option<WorkerResponse<ParentchainHeader, Vec<u8>>> = ocall_api
.worker_request(
[WorkerRequest::LatestParentchainHeaderUnverified].into(),
&ParentchainId::Integritee,
)
.worker_request([WorkerRequest::LatestParentchainHeaderUnverified].into(), &parentchain_id)
.ok()
.iter()
.filter_map(|r| r.first().cloned())
Expand Down
2 changes: 1 addition & 1 deletion service/src/account_funding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ pub fn setup_reasonable_account_funding(
let free = api.get_free_balance(accountid)?;
let missing_funds = needed.saturating_sub(free);

if missing_funds < needed * 2 / 3 {
if missing_funds < needed / 10 {
return Ok(())
}

Expand Down
2 changes: 1 addition & 1 deletion service/src/main_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -815,7 +815,7 @@ where
});

// we attempt to set shard creation for this parentchain in case it hasn't been done before
let api_head = node_api.get_header(None).unwrap().unwrap();
let api_head = node_api.get_header(node_api.get_finalized_head().unwrap()).unwrap().unwrap();
// TODO: #1451: Fix api-client type hacks
let head = Header::decode(&mut api_head.encode().as_slice())
.expect("Can decode previously encoded header; qed");
Expand Down
16 changes: 12 additions & 4 deletions service/src/ocall_bridge/worker_on_chain_ocall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use std::{
};
use substrate_api_client::{
ac_primitives,
ac_primitives::{serde_impls::StorageKey, SubstrateHeader},
ac_primitives::{serde_impls::StorageKey, Header, SubstrateHeader},
GetAccountInformation, GetChainInfo, GetStorage, SubmitAndWatch, SubmitExtrinsic, XtStatus,
};

Expand Down Expand Up @@ -91,7 +91,7 @@ where
request: Vec<u8>,
parentchain_id: Vec<u8>,
) -> OCallBridgeResult<Vec<u8>> {
debug!(" Entering ocall_worker_request");
debug!("[{:?}] Entering ocall_worker_request", parentchain_id);

let requests: Vec<WorkerRequest> = Decode::decode(&mut request.as_slice())?;
if requests.is_empty() {
Expand All @@ -109,10 +109,18 @@ where
{
header
} else {
warn!("failed to fetch parentchain header. can't answer WorkerRequest");
warn!(
"[{:?}] failed to fetch parentchain header. can't answer WorkerRequest",
parentchain_id
);
return Ok(Vec::<u8>::new().encode())
};

trace!(
"[{:?}] Last finalized header {} {:?}",
parentchain_id,
header.number,
header.hash()
);
let resp: Vec<WorkerResponse<ParentchainHeader, Vec<u8>>> = requests
.into_iter()
.map(|req| match req {
Expand Down
2 changes: 1 addition & 1 deletion service/src/parentchain_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ where
let max_blocknumber_in_chunk =
block_chunk_to_sync.last().map_or_else(|| 0, |b| b.block.header.number());
if max_blocknumber_in_chunk < creation_block.number {
trace!("skipping invocations for fast-sync for blocks older than shard creation: {} < {}", max_blocknumber_in_chunk, creation_block.number);
trace!("[{:?}] skipping invocations for fast-sync for blocks older than shard creation: {} < {}", id, max_blocknumber_in_chunk, creation_block.number);
true
} else {
false
Expand Down
Loading

0 comments on commit 0d56e12

Please sign in to comment.