casper-node icon indicating copy to clipboard operation
casper-node copied to clipboard

Host function `generic_hash()` with blake2b/blake3 support.

Open koxu1996 opened this issue 2 years ago • 3 comments

In order to support Zero Knowledge software, cryptography related utils should be implemented as a host functions, otherwise execution cost would be too high. For example running Risc0 VM proof verification for simple sum of squares takes more than 6000 CSPR. The underlying hash used: sha256.

This PR adds host function called generic_hash(input, type) with support for the following types:

  • HashAlgoType::Blake2b - used existing blake2b implementation,
  • HashAlgoType::Blake3b - blake3 library was introduced.

We expect to add more algorithms, i.e. sha256, keccak, poseidon.

Example usage

Smart contract:

#![no_std]
#![no_main]

extern crate alloc;

use alloc::format;
use casper_contract::contract_api::{crypto, runtime};
use casper_types::HashAlgoType;

#[no_mangle]
pub extern "C" fn call() {
    let input = "casper".as_bytes();
    runtime::print(&format!("Input: {:?}", input));

    let blake2b = crypto::generic_hash(input, HashAlgoType::Blake2b);
    runtime::print(&format!("Blake2b hash: {:?}", blake2b));

    let blake3 = crypto::generic_hash(input, HashAlgoType::Blake3);
    runtime::print(&format!("Blake3 hash: {:?}", blake3));
}

Node output:

Input: [99, 97, 115, 112, 101, 114]
Blake2b hash: [163, 40, 63, 203, 149, 170, 125, 252, 231, 127, 90, 198, 44, 250, 234, 42, 1, 199, 20, 158, 150, 188, 25, 205, 21, 106, 255, 40, 204, 65, 45, 196]
Blake3 hash: [122, 158, 116, 51, 175, 213, 20, 50, 237, 63, 251, 230, 53, 2, 233, 86, 36, 159, 195, 109, 254, 108, 189, 210, 233, 1, 93, 219, 226, 1, 50, 217]

Considerations

~~1. AssemblyScript support~~

~~Is AssemblyScript binding required? I am pretty sure no one uses it.~~

Update: AssemblyScript is broken since a long time. I see no reason to include bindings for something that does not work.

~~2. Gas cost~~

~~For now, I used the same cost for generic_hash() as defined for blake2() - default fixed value 200. I can do benchmarks for WASM bytecode execution, but is there any conversion ratio between CPU time and execution cost?~~

Update: There will be new execution engine that will affect (lower) gas usage. It will be the better to make benchmarks then.

3. Place for core hashes implementation

Blake2b is implemented in types package, which does not seem to be reasonable. I added blake3 to new module crypto in execution engine, but I am open to discussing its location.

4. Single vs multiple host function

Do we want to introduce separate host functions for each hash algorithm?

5. Place for generic_hash() in contract API

I was thinking of using runtime, but finally decided to create new crypto module.

koxu1996 avatar Nov 13 '23 17:11 koxu1996

I just confirmed that host function is still working correctly after all changes and fixes.

koxu1996 avatar Nov 20 '23 15:11 koxu1996

Michal's approval is sufficient for you to move forward with this at the functional level. As far as inclusion into 1.6, @marc-casperlabs is the principal engineer on that rel; I've had no direct involvement with it.

If it can't go into 1.6 for timeline reasons, we can repoint it to 2.0 and then I'll review it.

You should repoint this to feat-2.0.

@mpapierski should this be repointed to feat-2.0 ?

@mpapierski should this be repointed to feat-2.0 ?

I talked to @asladeofgreen and @jonas089 and for now, there's no concrete use case for generic hash functions, but we can revisit this once we have use for this internally or externally from the community. My understanding is that this PR was done as part of research.

mpapierski avatar Sep 06 '24 09:09 mpapierski

Related issue (created to take this forward) #4892

devendran-m avatar Sep 19 '24 09:09 devendran-m