Skip to content

Conversation

@murerfel
Copy link
Contributor

@murerfel murerfel commented Nov 3, 2021

This is another refactoring step towards #301.

The goal is to have the functionality that was originally in the prepare_and_send_xts_and_block function in a separate crate, so that the content of sidechain_impl.rs can be moved from the enclave_runtime crate, to the sidechain crate, where it belongs.

As I studied the code, I realized that prepare_and_send_xts_and_block does 2 things that are not necessarily related:

  1. Crate and send extrinsics confirmations to the parentchain
  2. Send, i.e. distribute/gossip sidechain blocks

So I separated those 2 functionalities, which resulted in a lot of changes to the O-call API (and all its layers). In addition, I did some refactoring regarding side-effects of those functions. The nonce is now not a &mut in/out parameter, but just an in-parameter and the mutated nonce value is return in the result. The second side-effect was the signer key pair, that we retrieved in a static method. I now pass this key down as a parameter (which is abstracted by a type parameter).

Comment on lines -294 to +299
fn create_extrinsics<PB>(
fn create_extrinsics<PB, Signer>(
genesis_hash: HashFor<PB>,
signer: Signer,
calls: Vec<OpaqueCall>,
nonce: &mut u32,
) -> Result<Vec<OpaqueExtrinsic>>
mut nonce: u32,
) -> Result<(Vec<OpaqueExtrinsic>, u32)>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Take the signer as parameter (rather than having the Ed25519Seal::unseal()?; side-effect in the function) and the nonce is now an input parameter and returned in the result.

.unzip();

prepare_and_send_xts_and_block::<_, SB, _, _>(
ocall_api.send_sidechain_blocks(blocks)?;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sending the sidechain blocks is now done by just calling the corresponding method on ocall_api

if !confirmation_calls.is_empty() {
debug!("Enclave wants to send {} extrinsics", confirmation_calls.len());
for call in confirmation_calls.into_iter() {
api.send_extrinsic(hex_encode(call.encode()), XtStatus::Ready).unwrap();
Copy link
Contributor Author

@murerfel murerfel Nov 3, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just saw this in the review here: We have some unwraps still in this part of the code. We should probably fix this at some point?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, totally agreed! Does anything speak against fixing it in this PR? 😇

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Time is the reason 😝 For now we have to live with it I think, otherwise I will never be able to get through this refactoring in this sprint 😄 We have many places where we still use unwrap() instead of proper error handling. I think we should fix all of those in one go.

@murerfel murerfel self-assigned this Nov 3, 2021
@murerfel murerfel force-pushed the feature/fm-trusted-call-handler branch from 174fc87 to 12743a4 Compare November 3, 2021 15:33
@murerfel murerfel force-pushed the feature/fm-separate-send-xts-send-blocks branch 2 times, most recently from a0edcd9 to 7468e12 Compare November 4, 2021 09:24
Base automatically changed from feature/fm-trusted-call-handler to master November 4, 2021 10:30
@murerfel murerfel force-pushed the feature/fm-separate-send-xts-send-blocks branch from 7468e12 to 0b6cbd9 Compare November 4, 2021 15:09
@murerfel murerfel requested review from clangenb and haerdib November 8, 2021 11:41
@murerfel murerfel marked this pull request as ready for review November 8, 2021 11:41
@murerfel murerfel force-pushed the feature/fm-separate-send-xts-send-blocks branch from 0b6cbd9 to 99980a2 Compare November 8, 2021 12:31
Copy link
Contributor

@haerdib haerdib left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good all in all I think. I left some comments ;)

confirmations: Vec<u8>,
signed_blocks: Vec<u8>,
) -> OCallBridgeResult<()>;
fn send_sidechain_blocks(&self, signed_blocks: Vec<u8>) -> OCallBridgeResult<()>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renaming suggestion (@clangenb may correct me here): propose_sidechain_blocks

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I agree, and I think we should actually move the function from another place. The current location was confusing for me. This function gossips the sidechain blocks to peer-validateers now, it has nothing to do with WorkerOnchainBridge.

However, I see now that cleanly separating the sidechain stuff means that we kind of need to replicate some structure from the core-primitives domain into the sidechain domain. This might also be an overkill, so we might just make an extra trait here called SidechainBridge or so?

Finally, @haerdib I think you need to become consistent with your sidechain-block naming. In the teerex pallet, you introduced the calls like propose_sidechainblock. ;)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will do the re-naming and create a new bridge, called SideChainBridge, to where I'll move that function.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, you're right @clangenb . Sorry for that - sidechainblocks it is ;)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBH I don't really like propose_sidechainblocks, it's just not how you would write it in English. Sidechain can be a composed noun, but sidechainblock is more like you would form the word in German than in English (where I'd prefer sidechain block)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can agree with both, as long as we stay consistent, I guess.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I guess you could argue that we are in an emerging field, and we henceforth coin the term 'Sidechainblock`, I don't have a strong preference here, but except for the pallet, we have been going with 'sidechain block' until now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets go with _block then. I'll adapt the pallet.

Copy link
Contributor Author

@murerfel murerfel Nov 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For sidechain and parentchain I can agree to have it as a compound noun. But I believe it's very rare in English to have a compound noun made of three words. Otherwise, using your argument, we could also have: parentchainblockconfirmationheader - which is what you would have in German, but definitely not in English

) -> OCallBridgeResult<()>;
fn send_sidechain_blocks(&self, signed_blocks: Vec<u8>) -> OCallBridgeResult<()>;

fn send_confirmations(&self, confirmations: Vec<u8>) -> OCallBridgeResult<()>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renaming suggestion (@clangenb may correct me here): send_confirmations_to_layer_one or something like that..?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We decided not to use layer_one anymore but rather relative naming as there might be multiple hierarchies, so I'd suggest:

send_to_parentchain(&self, extrinsics_vec_encoded)

The current naming is actually wrong. The 'confirmations' may also contain callbacks from the trustedcall's execution.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 I will re-name the function

if !confirmation_calls.is_empty() {
debug!("Enclave wants to send {} extrinsics", confirmation_calls.len());
for call in confirmation_calls.into_iter() {
api.send_extrinsic(hex_encode(call.encode()), XtStatus::Ready).unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, totally agreed! Does anything speak against fixing it in this PR? 😇

Copy link
Contributor

@clangenb clangenb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor comments but looks nice; divide and conquer!

.send_block_and_confirmation::<SB>(extrinsics, blocks)
.map_err(|e| Error::Other(format!("Failed to send block and confirmation: {}", e).into()))
ocall_api.send_confirmations(extrinsics).map_err(|e| {
Error::Other(format!("Failed to send block and confirmation: {}", e).into())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now, it only sends confirmations, no? :)

Comment on lines 136 to 148
Authority: Pair<Public = sp_core::ed25519::Public>,
Authority::Public: Encode,
PB: Block<Hash = H256>,
SB: SignedBlock<Public = Authority::Public, Signature = MultiSignature> + 'static,
SB: SignedBlock<Public = sp_core::ed25519::Public, Signature = MultiSignature> + 'static,
SB::Block: SidechainBlockT<ShardIdentifier = H256, Public = Authority::Public>,
Authority: Pair<Public = SB::Public>,
Authority::Public: Encode,
SB::Signature: From<Authority::Signature>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you invert the relation here? Now we also we have a definition cycle:

Authority: Pair<Public = SB::Public> 
SB::Signature: From<Authority::Signature>,

Anyhow, I think the block should not have the MultiSignature in the future but just Authority::Signature, but I could not change that easily when introducing aura ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be consistent, everywhere else we have the authority being defined by the sidechain block public type. Only here it was different, so I changed it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are probably right regarding the definition cycle. So I might have to invert it again, but then do it in all the places where we have these constraint definitions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I see. Good catch in that case! 😄

I think you can leave it until we introduce the change that makes the following possible:

	SB: SignedBlock<Public = Authority::Public, Signature = Authority::Signature + 'static,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well now that you mentioned the cyclic definition path, it's bugging me as well. I'll try to change it (and hope I don't shoot myself in the foot with those trait constraints)

confirmations: Vec<u8>,
signed_blocks: Vec<u8>,
) -> OCallBridgeResult<()>;
fn send_sidechain_blocks(&self, signed_blocks: Vec<u8>) -> OCallBridgeResult<()>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I agree, and I think we should actually move the function from another place. The current location was confusing for me. This function gossips the sidechain blocks to peer-validateers now, it has nothing to do with WorkerOnchainBridge.

However, I see now that cleanly separating the sidechain stuff means that we kind of need to replicate some structure from the core-primitives domain into the sidechain domain. This might also be an overkill, so we might just make an extra trait here called SidechainBridge or so?

Finally, @haerdib I think you need to become consistent with your sidechain-block naming. In the teerex pallet, you introduced the calls like propose_sidechainblock. ;)

) -> OCallBridgeResult<()>;
fn send_sidechain_blocks(&self, signed_blocks: Vec<u8>) -> OCallBridgeResult<()>;

fn send_confirmations(&self, confirmations: Vec<u8>) -> OCallBridgeResult<()>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We decided not to use layer_one anymore but rather relative naming as there might be multiple hierarchies, so I'd suggest:

send_to_parentchain(&self, extrinsics_vec_encoded)

The current naming is actually wrong. The 'confirmations' may also contain callbacks from the trustedcall's execution.

Felix Müller added 3 commits November 9, 2021 08:59
@murerfel murerfel force-pushed the feature/fm-separate-send-xts-send-blocks branch from 472a0e2 to 98451ba Compare November 9, 2021 08:00
Comment on lines 74 to 76
pub trait EnclaveSideChainOCallApi: Clone + Debug + Send + Sync {
fn propose_sidechain_blocks<SB: Encode>(&self, signed_blocks: Vec<SB>) -> SgxResult<()>;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extraced the propose_sidechain_blocks to a separate trait and ocall bridge everywhere

Copy link
Contributor

@clangenb clangenb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only wondering about case conventions, otherwise it looks very good!

) -> SgxResult<Vec<WorkerResponse<V>>>;
}

pub trait EnclaveSideChainOCallApi: Clone + Debug + Send + Sync {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency, the trait should contain Sidechain not SideChain (capital C).

use itp_ocall_api::{alloc::prelude::v1::Vec, EnclaveSideChainOCallApi};
use sgx_types::{sgx_status_t, SgxResult};

impl EnclaveSideChainOCallApi for OcallApi {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again the capital 'C'

@@ -0,0 +1,43 @@
/*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Woah, even a separate file. 😄

#[error("Propose sidechain block failed: {0}")]
ProposeSideChainBlock(String),
#[error("Sending extrinsics to parentchain failed: {0}")]
SendExtrinsicsToParentChain(String),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also the capital 'C'. :)

use log::*;
use std::sync::Arc;

pub struct SideChainOCall<S, D> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now I wonder. Did you make it on purpose with the capital 'C's in the CamelCase names? I'd prefer it to be consistent with the snake_case versoin.

@murerfel
Copy link
Contributor Author

murerfel commented Nov 9, 2021

hmm either I've gone completely crazy, or GitHub does not let me answer to comments anymore, I just have the 'Resolve Conversation' option 😮
Regarding the naming of SideChain @clangenb : you are absolutely right, it should be Sidechain to be consistent with the snake case sidechain. My bad 😄

Copy link
Contributor

@clangenb clangenb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, I am surprised that we'd have so many SideChains left. Thanks for fixing.

OCallBridgeError::GetIasSocket(_) => sgx_status_t::SGX_ERROR_UNEXPECTED,
OCallBridgeError::SendBlockAndConfirmation(_) => sgx_status_t::SGX_ERROR_UNEXPECTED,
OCallBridgeError::ProposeSidechainBlock(_) => sgx_status_t::SGX_ERROR_UNEXPECTED,
OCallBridgeError::SendExtrinsicsToParentChain(_) => sgx_status_t::SGX_ERROR_UNEXPECTED,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh, I also found one :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah parentchain - yes I've only checked for sidechain 😛 another search and replace commit then

Copy link
Contributor

@haerdib haerdib left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only minor comments. Hence, I'm approving.

match sidechain_api.propose_sidechain_blocks(signed_blocks_vec) {
Ok(_) => sgx_status_t::SGX_SUCCESS,
Err(e) => {
error!("send sidechain blocks failed: {:?}", e);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
error!("send sidechain blocks failed: {:?}", e);
error!("Proposing sidechain blocks failed: {:?}", e);


fn send_block_and_confirmation(
fn send_to_parentchain(
confirmations: *const u8,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since these have been renamed in woker_on_chain_ocall.rs, should we also rename them to extrinsics_encoded here? Or it that taking it too far?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, you're right - I missed that one when re-naming

Comment on lines -817 to +842
SB: SignedBlockT<Public = sp_core::ed25519::Public, Signature = MultiSignature>,
SB: SignedBlockT<Public = Signer::Public, Signature = MultiSignature>,
SB::Block: SidechainBlockT<ShardIdentifier = H256, Public = sp_core::ed25519::Public>,
SB::Signature: From<Signer::Signature>,
RpcAuthor:
AuthorApi<H256, PB::Hash> + SendState<Hash = PB::Hash> + OnBlockCreated<Hash = PB::Hash>,
StateHandler: QueryShardState,
StfExecutor: StfExecuteTimedCallsBatch<Externalities = SgxExternalities>
+ StfExecuteGenericUpdate<Externalities = SgxExternalities>,
Signer: Pair<Public = sp_core::ed25519::Public>,
Signer::Public: Encode,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed the trait bounds definition now, such that the SignedBlock::Public type is defined by the Signer::Public type

Also re-name the 'confirmations' to 'extrinsics'
@murerfel murerfel merged commit e58c934 into master Nov 9, 2021
@murerfel murerfel deleted the feature/fm-separate-send-xts-send-blocks branch November 9, 2021 11:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants