integritee-network / pallets

Other
10 stars 14 forks source link

Publish (merkle-root) hash as proof of sidechain execution on the parachain #145

Closed clangenb closed 1 year ago

clangenb commented 1 year ago

We do trust a TEE does things correctly, but the tee does need to prove that it did execute something at all. For indirect requests, we already do this; we publish the hash of the executed request on the chain. However, we don't do this yet for direct requests or as a result of something else. This could be done with a very simple extrinsic:

pub fn publish_hash(origin: Origin, hash: H256) {
    let mrenclave = ensure_registered_enclave(origin)?;

    // The enclave publishes a busines logic specific hash, which might be:
    // * merkle-root of some executed operations
    // * hash of a direct request that was sent aka `hash_of(trusted_call)`
    // * Other examples ??
    Self::deposit_event(Event::PublishedHash{enclave: mrenclave, hash: hash});
}

As we don't want to bloat our chain state, we only emit an event. All the indexers will still register and store the event, and you can always query archive nodes for events at a specific block height. The only thing that would not be possible is to request the hash via XCM, which I believe that we don't need it. In this case, the TEE would just send the result or whatever to the other parachain directly anyhow.

We could also use deposit_event_indexed to publish hashes with certain topics. Then, clients could subscribe to updates of a specific mrenclave. Or what if instead of just using the mrenclave as topic, we could maybe also do something like this?

/// Public a hash as a result of an enclave operation.
///
/// Clients can subscribe to the topic if it is supplied otherwise the `mrenclave` of the `origin` will be used as topic,
/// and it can still be subscribed to it.
/// 
/// `data` could be anything that is worthwile publishing. If it is a utf8-encoded 
/// string, the UIs will usually even render the text.
pub fn publish_hash(origin: Origin, hash: H256, topic: Option<T::Hash>, data: Option<Vec<u8>>) {
    let mrenclave = ensure_registered_enclave(origin)?;

    let t = topic.unwrap_or_else(|| mrenclave.clone().into());
    Self::deposit_event_indexed(&[t], Event::PublishedHash{enclave: mrenclave, hash: hash, data: data});
}
clangenb commented 1 year ago

If we still want to persist some hash to be retrieved by some other chain, I would suggest including another extrinsic, which stores hash with a certain lifetime or without, but then one needs to deposit some TEER for as long as the hash should live on the chain.

coax1d commented 1 year ago

I think this is all fine except to perhaps introduce a new type to reduce the argument size. Also bounding the Vec<u8> to some fixed size.

struct Topic {
    title: Hash,
    data: BoundedVec<u8, MAX_LEN>
} 

Then..

pub fn publish_hash(origin: Origin, hash: H256, topic: Option<Topic>) -> DispatchResult { .. }