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

refactor: make ChainInclusion trait fully generic and change input to the raw AnchorProof #570

Merged
merged 1 commit into from
Oct 22, 2024

Conversation

stbrody
Copy link
Collaborator

@stbrody stbrody commented Oct 21, 2024

builds on #550 making things more fully generic and preparing for the addition of an "adm" implementation of the ChainProvider trait.

@stbrody stbrody self-assigned this Oct 21, 2024
@stbrody stbrody requested review from gvelez17 and removed request for a team October 21, 2024 19:18
/// Get the CAIP2 chain ID supported by this RPC provider
fn chain_id(&self) -> &caip2::ChainId;

/// Get the block chain transaction if it exists with the block timestamp information
async fn chain_inclusion_proof(&self, input: &Self::InclusionInput)
-> Result<TimeProof, Error>;
async fn chain_inclusion_proof(&self, input: &AnchorProof) -> Result<TimeProofResults, Error>;
Copy link
Collaborator Author

@stbrody stbrody Oct 21, 2024

Choose a reason for hiding this comment

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

this is the core of the change in this PR. Now instead of having the ChainInclusion type be generic over an InclusionInput type that must be specified for each implementation of the trait (and built by each caller of the chain_inclusion_proof function), now we just simply take the raw AnchorProof object and let the implementations decide how to interpret that object.

This avoids the callers of this function needing to know whether the AnchorProof is for an ethereum anchor or an Adm anchor and having to build up the appropriate input type accordingly. Now the caller can just blindly pass the anchor proof down into this function and trust the underlying implementation to do the right thing.

The goal is that other than the initial setup to construct the ChainInclusionProviders from the given RPC urls at startup, none of the event validation code will need to be in any way aware of which chain its providers are for, or have any chain-specific logic. All of that gets pushed down to the two implementations of the ChainInclusion trait.

Copy link
Collaborator

@nathanielc nathanielc left a comment

Choose a reason for hiding this comment

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

Overall looks good, however I have some questions below to help clear up some of my confusion.

/// Get the CAIP2 chain ID supported by this RPC provider
fn chain_id(&self) -> &caip2::ChainId;

/// Get the block chain transaction if it exists with the block timestamp information
async fn chain_inclusion_proof(&self, input: &Self::InclusionInput)
-> Result<TimeProof, Error>;
async fn chain_inclusion_proof(&self, input: &AnchorProof) -> Result<TimeProofResults, Error>;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why do we use the AnchorProof struct when it has more information than is needed by the implementations? With this API its not clear if the chain_inclusion_proof method is checking if the root cid returned matches the root cid of the input proof structure.

This API is about only getting the proof result correct? In that case I think I prefer having the associated type InclusionInput that makes it explicit what information a given provider needs in order to get the proof result.

Thoughts? Maybe I have missed the motivation behind this change.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe we do type InclusionInput: From<AnchorProof> so that callers can still use the anchor proof but then its clear that the provider itself is not validating the proof but instead just retrieving the information the proof references?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Per discussion on discord, there's unfortunately no way to do this without leaking details of the different ChainInclusion implementations for different chains into the calling code. Decided the lesser evil is taking the AnchorProof, even though its taking in more information than is needed, as it allows the EventValidation code to avoid any special logic that depends on what chain is being validated.

/// A proof of time on the blockchain
pub struct TimeProof {
/// A proof of time derived from state on the blockchain
pub struct TimeProofResults {
Copy link
Collaborator

Choose a reason for hiding this comment

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

We have lots of names for what seem like the same thing, can we consolidate on a consistent naming?

For example we have AnchorProof, TimeProofResults and chain_inclusion_proof. What is the difference between anchor, time, and chain inclusion? Do we really have three different types of proofs? Why is the function named chain_inclusion_proof when it returns a TimeProofResults?

Should the names instead be, AnchorProof, ChainInclusionProof and get_chain_inclusion_proof? Where anchor proof is a chain agnostic chain inclusion proof? I'd be fine with other names too, its just not clear how all these thing relate given their current names and the differences imply there are more entities than there really are.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yep agreed. Took your suggested names, I think those are clearer.

Copy link
Contributor

@AaronGoldman AaronGoldman left a comment

Choose a reason for hiding this comment

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

Some nits but looks good.

@@ -226,7 +226,7 @@ impl EventValidator {
Ok(validated_events)
}

/// Transforms the [`ChainInclusionError`] into a [`ValidationError`] with an appropriate message
/// Transforms the [`eth_rpc::Error`] into a [`ValidationError`] with an appropriate message
Copy link
Contributor

Choose a reason for hiding this comment

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

this seems backwards

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

How so? Function takes an eth_rpc::Error and returns a ValidationError

.map_err(|e| eth_rpc::Error::InvalidProof(e.to_string()))?,
};
let proof = provider.chain_inclusion_proof(&input).await?;
let proof = provider.chain_inclusion_proof(event.proof()).await?;
Copy link
Contributor

Choose a reason for hiding this comment

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

I know that this is the way it is now. but can we rename proof here to make clear that this is the proof from the chain and that

proof.root_cid != event.proof().root()

Is comparing the events attestation to the chain's attestation.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

good call, renamed proof to chain_proof, added a comment, and added the other root to the error message

Base automatically changed from refactor/modify-eth-rpc-trait-for-hoku to main October 22, 2024 17:52
@stbrody stbrody added this pull request to the merge queue Oct 22, 2024
Merged via the queue into main with commit 33e2f26 Oct 22, 2024
5 checks passed
@stbrody stbrody deleted the generic-chain-inclusion branch October 22, 2024 19:07
@smrz2001 smrz2001 mentioned this pull request Nov 4, 2024
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.

3 participants