Closed Kailai-Wang closed 1 year ago
Yeah, we definitely want to consider extrinsic statuses of parentchain extrinsics, happy to merge a PR! I will formulate some thoughts for this PR here.
I had problems understanding the comment:
// One solution is to change the block type to
sp_runtime::generic::Block
orsp_runtime::generic::SignedBlock
, // this will however affect many structs or files, like block_importer, block_import_dispatcher, consensus and so on.
But, I think I get it now, it is because you silently change the data format that the OpaqueExtrinsic
contains, sometimes it contains the xt_status, and sometimes it doesn't. This is indeed be a bit dangerous in the sense of: it needs to be documented well, so we know exactly where OpaqueExtrinsic
contains the tx status, and where it doesn't.
Security issue: However, there is definitely one security issue that needs to be adressed:
// In the service, in the untrusted world.
for block in &block_chunk_to_sync {
let block_events = self.parentchain_api.events(Some(block.block.hash()))?;
events.push(block_events);
}
Here, we fetch the events of a particular block with a storage query. However, we don't check the corresponding storage proof. Hence, a malicious operator could modify the untrusted function that syncs the parentchain blocks, and do the following:
To mitigate this, we need to pass in the full event list into the enclave to verify corresponding storage proof inside the enclave, and do the filtering for the events that we care about inside the enclave. So to add some pseudocode about what needs to be done to get the storage proofs:
let events_storage_key = storage_key(blalbal);
let events = self.parentchain_api.events(Some(block_hash));
let events_proof = self.parentchain_api.storage_proof(events_storage_key);
// we need to sync the blocks, events, events_proof together into the enclave
// and do the necessary filtering inside.
Also, in the future, we might want to detect, when the worker is still syncing the parentchain because then it won't care about the events. #1215 might help here, but I consider this a future problem.
Also, I think I would like to extend the description maybe:
pub struct OpaqueExtrinsicWithStatus {
pub xt: OpaqueExtrinsic,
pub status: XtStatus,
}
// I think we can skip the dispatch info.
pub enum XtStatus {
ExtrinsicSuccess,
ExtrinsicFailed { dispatch_error: DispatchError },
}
Thanks @clangenb ! We definitely haven't forgotten this issue and understand your concerns. However, we have been focusing on the product launch recently and didn't have time to look further into it
The potential risk isn't a big problem for us as of now because we are the only worker operators. But I strongly agree it should be solved later, we'll note this down and come back to this after the product launch.
Closed by #1272
We noticed this problem in https://github.com/litentry/litentry-parachain/issues/1092
Quote:
We also have a workaround for this: https://github.com/litentry/litentry-parachain/pull/1193
A bit hacky though as we wanted to have as few changes as possible. We append a status flag to the found extrinsics during parentchain syncing and parse it in the indirect-calls-executor, with customised encoding/decoding of
OpaqueExtrinsics
:Please let us know if you are happy with it, if so we can submit a PR.