diff --git a/docs-test-gen/templates/core.tpl b/docs-test-gen/templates/core.tpl index e6703496..6ccd0771 100644 --- a/docs-test-gen/templates/core.tpl +++ b/docs-test-gen/templates/core.tpl @@ -12,6 +12,27 @@ struct InstantiateMsg {} #[cw_serde] struct QueryMsg {} +#[cw_serde] +struct EcdsaRecoverMsg { + message_hash: Binary, + signature: Binary, + recovery_id: u8, +} + +#[cw_serde] +struct EcdsaVerifyMsg { + message_hash: Binary, + signature: Binary, + public_key: Binary, +} + +#[cw_serde] +struct Ed25519VerifyMsg { + public_key: Binary, + message: Binary, + signature: Binary, +} + #[cw_serde] struct ExecuteMsg {} diff --git a/src/pages/core/standard-library.mdx b/src/pages/core/standard-library.mdx index c1ec4c04..7c34891c 100644 --- a/src/pages/core/standard-library.mdx +++ b/src/pages/core/standard-library.mdx @@ -5,3 +5,10 @@ tags: ["core"] import { Callout } from "nextra/components"; # Standard Library + +CosmWasm offers a standard library providing a bunch of different components to +write smart contracts. In this section we will go over some components and +functionality the standard library offers. + +A full list of all components along with documentation can be found +[on docs.rs](https://docs.rs/cosmwasm-std). diff --git a/src/pages/core/standard-library/cryptography.mdx b/src/pages/core/standard-library/cryptography.mdx index 188ef5af..32c22a6e 100644 --- a/src/pages/core/standard-library/cryptography.mdx +++ b/src/pages/core/standard-library/cryptography.mdx @@ -1,7 +1,82 @@ --- -tags: ["core"] +tags: ["core", "cryptography"] --- import { Callout } from "nextra/components"; # Cryptography + +CosmWasm offers cryptographic primitives that are implemented as VM intrinsics. +This means that they are more efficient than implementations in contract code +could be, saving you gas and code size. In some cases they are also _impossible_ +to implement in contract code, since some of them require a random intermediate +value and randomness is generally not exposed to contracts to ensure +deterministic execution. + +In the sidebar, you can find all the supported algorithms/curves along with +documentation about them. + +## Gas costs + + + Note that these values are in CosmWasm Gas (which is very much different from + Cosmos SDK Gas). For more info on gas, [check this + document](https://github.com/CosmWasm/cosmwasm/blob/main/docs/GAS.md). + + +### secp256k1 + +- Verify: 96_000_000 gas +- Recover public key: 194_000_000 gas + +### secp256r1 + +- Verify: 279_000_000 gas +- Recover public key: 592_000_000 gas + +### ed25519 + +- Verify: 35_000_000 gas +- Batch verify (multiple signatures; multiple keys): + - Base: 24_000_000 gas + - Per signature/key pair: 21_000_000 gas +- Batch verify (multiple signatures; one key): + - Base: 36_000_000 gas + - Per signature: 10_000_000 gas + +### BLS12-381 + +- Aggregate points to G1: + - Base: 68_000_000 gas + - Per point: 12_000_000 gas +- Aggregate points to G2: + - Base: 103_500_000 gas + - Per point: 24_500_000 gas +- Hash to G1: 563_000_000 gas +- Hash to G2: 871_000_000 gas +- Pairing equality: + - Base: 2_112_000_000 gas + - Per item: 163_000_000 gas + +You can also check these numbers in the +[source code](https://github.com/CosmWasm/cosmwasm/blob/main/packages/vm/src/environment.rs#L62-L101). + +## Note on hash functions + +You'll notice that CosmWasm does not implement any hash functions as native +functions, and we intend to keep it that way. The reasoning for that is: + +- Hash functions are pretty much always cheap in terms of execution cost _and_ + code size +- There are way too many hash functions out there, adding one would open the + floodgates where we would have to add more + - SHA-3 family, Keccak256, cSHAKE256, BLAKE2, BLAKE3, SHA-2 family, + KangarooTwelve, etc. (and this is just a small sample set to drive the point + home) +- Benchmarking and pricing functions (and keeping those up-to-date) correctly is + a lot of work +- We want to keep the API surface as small as possible for ease of maintainance + +Keep in mind that, thanks to Wasm being our execution environment, contract +execution is quite fast. In most cases the perceived need to move hashing into a +host function is premature optimization and not actually needed. diff --git a/src/pages/core/standard-library/cryptography/_meta.json b/src/pages/core/standard-library/cryptography/_meta.json new file mode 100644 index 00000000..d6c0be33 --- /dev/null +++ b/src/pages/core/standard-library/cryptography/_meta.json @@ -0,0 +1,6 @@ +{ + "ed25519": "Ed25519", + "p256": "P-256", + "k256": "K-256", + "bls12-381": "BLS12-381" +} diff --git a/src/pages/core/standard-library/cryptography/bls12-381.mdx b/src/pages/core/standard-library/cryptography/bls12-381.mdx new file mode 100644 index 00000000..b1eebc21 --- /dev/null +++ b/src/pages/core/standard-library/cryptography/bls12-381.mdx @@ -0,0 +1,23 @@ +--- +tags: ["core", "cryptography"] +--- + +import { Callout } from "nextra/components"; + +# BLS12-381 + +BLS12-381 is a bit of a special curve. It is a pairing-friendly curve, allowing +for fun things such as aggregated signatures. At the moment, CosmWasm only +supports signature verifications. In the future we might add support for +zero-knowledge proofs on this curve. + +Common examples where this curve is used are Ethereum block-headers and [drand](https://drand.love/) +randomness beacons. + +## Example + +CosmWasm offers a byte-oriented API for signature verification. This API also +doesn't care whether the public key is part of the G1 or G2 group (same for the +other components). They just have to somehow fit together. + +TODO: Add example as soon as BLS12-381 is properly released diff --git a/src/pages/core/standard-library/cryptography/ed25519.mdx b/src/pages/core/standard-library/cryptography/ed25519.mdx new file mode 100644 index 00000000..927762ad --- /dev/null +++ b/src/pages/core/standard-library/cryptography/ed25519.mdx @@ -0,0 +1,38 @@ +--- +tags: ["core", "cryptography"] +--- + +import { Callout } from "nextra/components"; + +# Ed25519 + +CosmWasm offers an API to verify and batch verify Ed25519 signatures. This is +powerful, especially since batch verifications require a random component which +is impossible to implement in contract code. + +Ed25519 is known to +[have issues with inconsistent validation criteria](https://hdevalence.ca/blog/2020-10-04-its-25519am), +the API we offer follows [ZIP215](https://zips.z.cash/zip-0215). This means you +will have no issues with signatures being valid in one place and invalid in +another. + +## Example + +```rust filename="contract.rs" template="core" +#[entry_point] +pub fn query( + deps: Deps, + _env: Env, + msg: Ed25519VerifyMsg, +) -> StdResult { + let public_key = msg.public_key; + let signature = msg.signature; + let message = msg.message; + + // Verify the signature. On chain! + let is_valid = deps.api.ed25519_verify(&message, &signature, &public_key)?; + let response = format!("{{ \"is_valid\": {is_valid} }}"); + + Ok(QueryResponse::new(response.into_bytes())) +} +``` diff --git a/src/pages/core/standard-library/cryptography/k256.mdx b/src/pages/core/standard-library/cryptography/k256.mdx new file mode 100644 index 00000000..eb363dbe --- /dev/null +++ b/src/pages/core/standard-library/cryptography/k256.mdx @@ -0,0 +1,58 @@ +--- +tags: ["core", "cryptography"] +--- + +import { Callout } from "nextra/components"; + +# K256 (secp256k1) + +K256 is a Koblitz curve that is widely used in the blockchain space (e.g. Bitcoin and Ethereum). CosmWasm +offers the following APIs: + +- Signature verification +- Public key recovery + +## Example + +### Signature verification + +```rust filename="contract.rs" template="core" +#[entry_point] +pub fn query( + deps: Deps, + _env: Env, + msg: EcdsaVerifyMsg, +) -> StdResult { + let public_key = msg.public_key; + let signature = msg.signature; + let message_hash = msg.message_hash; + + // Verify the signature. On chain! + let is_valid = deps.api.secp256k1_verify(&message_hash, &signature, &public_key)?; + let response = format!("{{ \"is_valid\": {is_valid} }}"); + + Ok(QueryResponse::new(response.into_bytes())) +} +``` + +### Public key recovery + +```rust filename="contract.rs" template="core" +#[entry_point] +pub fn query( + deps: Deps, + _env: Env, + msg: EcdsaRecoverMsg, +) -> StdResult { + let signature = msg.signature; + let message_hash = msg.message_hash; + let recovery_id = msg.recovery_id; + + // Recover the public key. On chain! + let public_key = deps.api.secp256k1_recover_pubkey(&message_hash, &signature, recovery_id)?; + let public_key = HexBinary::from(public_key).to_hex(); + let response = format!("{{ \"public_key\": \"{public_key}\" }}"); + + Ok(QueryResponse::new(response.into_bytes())) +} +``` diff --git a/src/pages/core/standard-library/cryptography/p256.mdx b/src/pages/core/standard-library/cryptography/p256.mdx new file mode 100644 index 00000000..21254c4d --- /dev/null +++ b/src/pages/core/standard-library/cryptography/p256.mdx @@ -0,0 +1,17 @@ +--- +tags: ["core", "cryptography"] +--- + +import { Callout } from "nextra/components"; + +# P256 (secp256r1) + +P256 is one of NIST's prime-order elliptic curves. You may need this curve to +implement protocols such as WebAuthn. This is the main reason this curve was +added to CosmWasm. + +## Example + +## Signature verification + +TODO: Add example as soon as secp256r1 is properly released