Introduction
Verifiable computation is the notion that two parties can jointly execute a program with assurances about the result1. Depending on the design goals of a specific system, verifiable computation may provide properties such as succinctness (verification is cheaper than re-execution), or privacy (certain inputs remain hidden from the other party).
A useful way to think about verifiable computation is to imagine a trusted third party that performs computation perfectly on behalf of two participants who don't trust each other. For a virtual machine -- and specifically the WebAssembly virtual machine -- this means a trusted party that receives inputs from both participants, faithfully executes a program, and relays the correct output back.
Of course, in practice we do not want to rely on a trusted third party. Instead, cryptographic protocols can be applied which allow the two parties to simulate such a system while providing very strong assurances that neither party can act dishonestly or cheat. This abstraction separates what the computation does from how it is securely implemented.
Here's what this could look like — an anonymous credential proof where a holder proves they meet an age requirement without revealing their birthdate:
#[vc::export]
fn assert_age(credential: &[u8], issuer_key: &[u8], min_age: u32, country: &[u8]) {
let id: Identity = parse_json(credential);
let is_valid_credential = id.verify_signature(issuer_key);
let is_min_age = id.age() >= min_age;
let is_in_country = id.country() == country;
assert!(is_valid_credential && is_min_age && is_in_country);
}
let instance = Instance::new(&module);
let result = instance.assert_age()
.credential(Private(my_credential)) // Credential is hidden.
.issuer_key(Public(ISSUER_KEY)) // Both parties agree on public inputs.
.min_age(Public(18))
.country(Public(b"US"))
.invoke()?;
assert!(result.success());
let instance = Instance::new(&module);
let result = instance.assert_age()
.credential(Blind)
.issuer_key(Public(ISSUER_KEY)) // Both parties agree on public inputs.
.min_age(Public(18))
.country(Public(b"US"))
.invoke()?;
assert!(result.success());
Different settings, such as zero-knowledge proofs or multi-party computation, utilize different cryptographic protocols and have varying capabilities and performance characteristics. This project aims to provide a unified abstraction which provides a number of benefits:
- Embedder independence - Developers can write applications which leverage verifiable computation without coupling business logic to a specific embedder.
- Standard toolchains - Programs are written in standard languages (C/C++, Rust, etc.) and compiled and tested using standard tools.
- Standard computation model - Built on top of an existing, formally specified computation model rather than defining a new one.
- Standard host interfaces - Common operations, such as hash functions, are exposed through standard host interfaces, enabling embedder-specific acceleration.