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

Cryptography documentation #26

Merged
merged 11 commits into from
Jun 5, 2024
21 changes: 21 additions & 0 deletions docs-test-gen/templates/core.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}

Expand Down
7 changes: 7 additions & 0 deletions src/pages/core/standard-library.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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).
77 changes: 76 additions & 1 deletion src/pages/core/standard-library/cryptography.mdx
Original file line number Diff line number Diff line change
@@ -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

<Callout>
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).
</Callout>

### 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.
6 changes: 6 additions & 0 deletions src/pages/core/standard-library/cryptography/_meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"ed25519": "Ed25519",
"p256": "P-256",
"k256": "K-256",
"bls12-381": "BLS12-381"
}
23 changes: 23 additions & 0 deletions src/pages/core/standard-library/cryptography/bls12-381.mdx
Original file line number Diff line number Diff line change
@@ -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.

<Callout>TODO: Add example as soon as BLS12-381 is properly released</Callout>
38 changes: 38 additions & 0 deletions src/pages/core/standard-library/cryptography/ed25519.mdx
Original file line number Diff line number Diff line change
@@ -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<QueryResponse> {
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()))
}
```
58 changes: 58 additions & 0 deletions src/pages/core/standard-library/cryptography/k256.mdx
Original file line number Diff line number Diff line change
@@ -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<QueryResponse> {
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<QueryResponse> {
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()))
}
```
17 changes: 17 additions & 0 deletions src/pages/core/standard-library/cryptography/p256.mdx
Original file line number Diff line number Diff line change
@@ -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

<Callout>TODO: Add example as soon as secp256r1 is properly released</Callout>