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

Adds HostFunctions to tendermint-light-client-verifier #1138

Closed
wants to merge 14 commits into from

Conversation

seunlanlege
Copy link

This encapsulates all crypto (hasing, signature verifications) behind a trait, so downstream crates can delegate these functions to host functions

@thanethomson
Copy link
Contributor

thanethomson commented Jun 11, 2022

@seunlanlege what's the context for this PR? We usually insist on having an issue associated with a PR so that there's at least opportunity for discussion, context sharing and planning/coordination before someone submits a PR.

@seunlanlege
Copy link
Author

hi @thanethomson you can find the discussion thread here: informalsystems/ibc-rs#2110

cc: @adizere

@seunlanlege
Copy link
Author

One thing to note is that tendermint-light-client depends on tendermint-light-client-verifier so i think it makes sense that someone from informal refactors tendermint-light-client with the new changes as i don't have enough context on this code.

@tony-iqlusion
Copy link
Collaborator

Why are you downgrading k256? This will cause incompatibilities with TMKMS.

Also if this trait is supposed to be cryptography-related functionality, shouldn't it have something like Crypto in its name, rather than Host*?

@seunlanlege
Copy link
Author

Why are you downgrading k256? This will cause incompatibilities with TMKMS.

@Wizdave97

Also if this trait is supposed to be cryptography-related functionality, shouldn't it have something like Crypto in its name, rather than Host*?

yes for now it is related to crypto functionality, but its more semantically correct to call them HostFunctions (a la wasm) because they could potentially be extended for other native-optimized non-crypto operations.

@seunlanlege
Copy link
Author

@tony-iqlusion @thanethomson please approve CI steps so we can start to move this PR along 🙏🏿

Comment on lines 10 to 14
/// Verify an ed25519 signature
fn ed25519_verify(sig: &[u8], msg: &[u8], pub_key: &[u8]) -> bool;

/// verify secp256k1 signatures
fn secp256k1_verify(sig: &[u8], message: &[u8], public: &[u8]) -> bool;
Copy link
Collaborator

@tony-iqlusion tony-iqlusion Jun 20, 2022

Choose a reason for hiding this comment

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

Using a bool for signature verification is a dangerous API which has lead to cryptographic vulnerabilities in practice:

https://github.com/libp2p/rust-libp2p/pull/1127/files

The signature crate, already used by tendermint-rs, provides a well thought-out type safe trait-based approach to encapsulating signing and verification providers for various digital signature algorithms.

TMKMS uses this to support hardware signers for signatures, for example (e.g. Ledger, YubiHSM2)

Likewise the digest crate provides an abstraction over hash functions.

.gitignore Outdated Show resolved Hide resolved

[dependencies]
tendermint = { version = "0.24.0-pre.2", path = "../tendermint", default-features = false }
derive_more = { version = "0.99.5", default-features = false, features = ["display"] }
serde = { version = "1.0.106", default-features = false }
time = { version = "0.3.5", default-features = false }
flex-error = { version = "0.4.4", default-features = false }
sp-std = { version = "4.0.0", default-features = false }
Copy link
Collaborator

Choose a reason for hiding this comment

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

Shouldn't this be an optional dependency?

Copy link
Author

Choose a reason for hiding this comment

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

its a drop in replacement for the std lib, so no default features means core, std features means std

@tony-iqlusion
Copy link
Collaborator

tony-iqlusion commented Jun 20, 2022

yes for now it is related to crypto functionality, but its more semantically correct to call them HostFunctions (a la wasm)

I think it is semantically quite unclear what the trait's name means.

The particular meaning of "host" in that content relates specifically to WASM, i.e. "outside the VM". But this crate is intended to be used, and indeed is primarily used, in environments other than WASM, where "host" has many other meanings such as hostnames.

because they could potentially be extended for other native-optimized non-crypto operations.

That sounds like YAGNI, and really I would suggest against a trait which has both cryptographic and non-cryptographic responsibilities unless the cryptography is tightly-coupled to the non-cryptographic functionality in some inseparable way.

Copy link
Contributor

@thanethomson thanethomson left a comment

Choose a reason for hiding this comment

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

I also have to agree with @tony-iqlusion in terms of the naming of the Host* entities. If there's even a need in future to broaden their functionality, I'd rather have multiple separate smaller traits, each focusing on one area of functionality.

.gitignore Outdated Show resolved Hide resolved
light-client-js/Cargo.toml Outdated Show resolved Hide resolved
light-client-js/Cargo.toml Outdated Show resolved Hide resolved
Comment on lines +42 to +43
sp-std = { version = "4.0.0", default-features = false }
sp-core = { version = "6.0.0", features = ["full_crypto"], optional = true }
Copy link
Contributor

Choose a reason for hiding this comment

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

Are these dependencies really necessary?

Copy link
Author

Choose a reason for hiding this comment

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

yes its used for tests and std end-users

Copy link
Member

Choose a reason for hiding this comment

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

Can we instead use core and alloc crates? We would rather avoid introducing Substrate-specific dependencies into the light client.

@xla
Copy link
Contributor

xla commented Jun 20, 2022

@seunlanlege what's the context for this PR? We usually insist on having an issue associated with a PR so that there's at least opportunity for discussion, context sharing and planning/coordination before someone submits a PR.

If this is the required process, linking to a discussion on another repository is not sufficient. There also seems to be quite a lot of reservation over the general approach, which indicates that a precursor in the form of a problem statement and a suggested design is necessary.

@tony-iqlusion
Copy link
Collaborator

As a general design, I'd suggest using existing traits to express the required functionality (e.g. Digest, Signer, Verifier), and either generic type parameters or associated types to describe concrete implementations.

@seunlanlege
Copy link
Author

As a general design, I'd suggest using existing traits to express the required functionality (e.g. Digest, Signer, Verifier), and either generic type parameters or associated types to describe concrete implementations.

I took a look at the crate and it doesn't seem that they can be used for the work that we're doing.

This PR is part of a general ibc-rs refactor Issue: https://github.com/informalsystems/ibc-rs/issues/2110 (Relevant PR: informalsystems/hermes#2284) in order to delegate expensive crypto operations to native-optimized host functions in wasm environments. Which indirectly necessitates that we refactor its dependencies (tendermint-rs and confio/ics23) as well.

I can rename the trait to be CryptoProvider, but a similar pr already went into cosmos/ics23#90 where its called HostFunctions and @ethanfrey didn't seem to mind. I personally don't mind either.

Using a bool for signature verification is a dangerous API which has lead to cryptographic vulnerabilities in practice:

The signature verification host functions that substrate provides, doesn't use a result interface: https://github.com/paritytech/substrate/blob/9461b2de04210c6c193726a745c3ec6552b4ce9f/primitives/io/src/lib.rs#L616-L989

Seeing as we'd be delegating to these host functions, I don't see how this api can be misused.

@ethanfrey
Copy link

Comment on the API.

If parity returns bool, we can still require a HostFunctions trait that returns Result<(), Error>.

Just wrap the parity one with this. I agree for critical operations, this ensures the return value won't get silently ignored.

The point is not to mirror parity 1:1 but find a good api that we can easily make a transform to from various implementations

@tony-iqlusion
Copy link
Collaborator

tony-iqlusion commented Jun 21, 2022

I took a look at the [signature] crate and it doesn't seem that they can be used for the work that we're doing.

You didn't actually explain why?

These traits already have widespread usage for the purposes of abstracting over signature and verification providers. They should work just fine for this application, and are much more carefully thought out than the API you're proposing.

The signature verification host functions that substrate provides, doesn't use a result interface

...and that was a mistake which created a sharp edge which lead to a critical signature verification bypass in one of their other crates.

Let's not repeat it?

@seunlanlege
Copy link
Author

You didn't actually explain why?

the purpose of the interface is for the crate to describe to downstream users what host functions it needs.
The signature crate only defines interfaces that should be implemented by signature schemes, which is tangent to delegating the actual operations to native.

@tony-iqlusion
Copy link
Collaborator

That is not the case. As I explained earlier, we already use these traits to delegate signing operations to hardware devices including Ledger Nanos, YubiKeys, and YubiHSM2s, and the same thing can work just as well for verification.

In fact the whole purpose is to be able to plug in different signing or verification providers so the API is type safe and avoids confusion of supported signature algorithms.

@seunlanlege
Copy link
Author

Maybe you can spec out some pseudo-code as to how you see the verification interface being used in the context of wasm host functions?

@tony-iqlusion
Copy link
Collaborator

tony-iqlusion commented Jun 21, 2022

Leveraging existing traits, the CryptoProvider can contain associated types rather than a bag of unrelated methods:

pub trait CryptoProvider {
    type Sha256: Digest + FixedOutput<OutputSize = U32>;

    type EcdsaSecp256k1Signer: Signer<k256::ecdsa::Signature>;
    type EcdsaSecp256k1Verifier: Verifier<k256::ecdsa::Signature>;

    type Ed25519Signer: Signer<ed25519::Signature>;
    type Ed25519Verifier: Verifier<ed25519::Signature>;
}

This allows code to be written generically over traits. For example, when ECDSA/secp256r1 support is added, code can be written generically such that it can support both that and ECDSA/secp256k1 by leveraging the Signer and Verifier traits but keeping the signature type generic.

The ed25519 crate has a code example of what generic code written using these traits looks like:

https://docs.rs/ed25519/latest/ed25519/#using-ed25519-generically-over-algorithm-implementationsproviders

@siriustaikun
Copy link

This would be instrumental for my project.

I'm implementing tendermint light client validity predicates in CosmWasm as a workaround to trustlessly access validator voting powers from within a contract. At present, this is otherwise impossible, and it constricts the ways we are able to enforce network security measures via liquid staking protocols.

Furthermore, this would serve as a substantial catalyst toward the completion of ICS-8 Wasm Client.

@adizere
Copy link
Member

adizere commented Aug 3, 2022

It seems this feature is important for at least 2 use-cases (supporting IBC in Substrate that Composable Finance are doing, and CosmWasm validity predicates). I think at the moment Composable is maintaining their own long fork. That works temporarily but it fragments the ecosystem, and there are other orgs who seem to need this feature.

If we consider this feature an ecosystem requirement on the tendermint-rs crates, maybe someone from tendermint-rs team could shepherd the PR and align everyone to get Host* functions (adapted to use CryptoProvider) upstreamed into the light-client-verifier crate?

@blasrodri
Copy link
Contributor

blasrodri commented Oct 17, 2022

It seems this feature is important for at least 2 use-cases (supporting IBC in Substrate that Composable Finance are doing, and CosmWasm validity predicates). I think at the moment Composable is maintaining their own long fork. That works temporarily but it fragments the ecosystem, and there are other orgs who seem to need this feature.

If we consider this feature an ecosystem requirement on the tendermint-rs crates, maybe someone from tendermint-rs team could shepherd the PR and align everyone to get Host* functions (adapted to use CryptoProvider) upstreamed into the light-client-verifier crate?

I'm just wondering if we could re-use this implementation addressing https://github.com/informalsystems/tendermint-rs/pull/1138/files#r937928435

We're happy to work on a better API (following #1138 (comment)). I can try to summarize all comments into one, and then we can see how to draft it?

@tony-iqlusion
Copy link
Collaborator

@blasrodri I think it would be great to open a planning issue for this and sketch out the API

@blasrodri
Copy link
Contributor

@blasrodri I think it would be great to open a planning issue for this and sketch out the API

Will do sir. Thanks

@mzabaluev
Copy link
Contributor

#1214 (currently a draft) seems to be a more recent work along the same lines.

@blasrodri
Copy link
Contributor

#1214 (currently a draft) seems to be a more recent work along the same lines.

@mzabaluev it's an iteration over this PR based on the gathered feedback. @seunlanlege can we close this one?

@mzabaluev mzabaluev mentioned this pull request Nov 2, 2022
@seunlanlege seunlanlege closed this Nov 9, 2022
@seunlanlege seunlanlege deleted the master branch November 9, 2022 02:39
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.