-
Notifications
You must be signed in to change notification settings - Fork 224
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
Conversation
…-host-functions Introduced `HostFunctionsProvider` trait to `tenderrmint-light-client-verifier`
@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. |
hi @thanethomson you can find the discussion thread here: informalsystems/ibc-rs#2110 cc: @adizere |
One thing to note is that |
Downgrade `k256` to `v0.10.4`
Why are you downgrading Also if this trait is supposed to be cryptography-related functionality, shouldn't it have something like |
yes for now it is related to crypto functionality, but its more semantically correct to call them |
@tony-iqlusion @thanethomson please approve CI steps so we can start to move this PR along 🙏🏿 |
/// 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; |
There was a problem hiding this comment.
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.
|
||
[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 } |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
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.
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. |
There was a problem hiding this 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.
sp-std = { version = "4.0.0", default-features = false } | ||
sp-core = { version = "6.0.0", features = ["full_crypto"], optional = true } |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
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. |
As a general design, I'd suggest using existing traits to express the required functionality (e.g. |
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
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. |
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 |
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.
...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? |
the purpose of the interface is for the crate to describe to downstream users what host functions it needs. |
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. |
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? |
Leveraging existing traits, the 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 The |
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. |
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 |
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? |
@blasrodri I think it would be great to open a planning issue for this and sketch out the API |
Will do sir. Thanks |
#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? |
This encapsulates all crypto (hasing, signature verifications) behind a trait, so downstream crates can delegate these functions to host functions