diff --git a/Cargo.toml b/Cargo.toml index f227f28..3317c7a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ name = 'ever_vm' version = '2.1.2' [dependencies] +crusty3_zk = { git = 'https://github.com/nilfoundation/crusty3-zk.git', branch = '6-extended-vk-encrypted-input-verification' } diffy = { optional = true, version = '0.2.2' } ed25519 = '1.2' ed25519-dalek = '1.0' diff --git a/src/executor/crypto.rs b/src/executor/crypto.rs index 58ba913..de0e2b5 100644 --- a/src/executor/crypto.rs +++ b/src/executor/crypto.rs @@ -25,10 +25,17 @@ use crate::{ }, types::{Exception, Status} }; + +use crusty3_zk::{ + groth16::{ + verify_groth16_proof_from_byteblob, + verify_encrypted_input_groth16_proof_from_byteblob, + }, + bls::{Bls12}, +}; use ed25519::signature::Verifier; +use ever_block::{error, BuilderData, Cell, ExceptionCode, GasConsumer, GlobalCapabilities, Result, UInt256}; use std::borrow::Cow; -use ever_block::GlobalCapabilities; -use ever_block::{BuilderData, error, GasConsumer, ExceptionCode, UInt256}; const PUBLIC_KEY_BITS: usize = PUBLIC_KEY_BYTES * 8; const SIGNATURE_BITS: usize = SIGNATURE_BYTES * 8; @@ -80,6 +87,43 @@ pub(super) fn execute_sha256u(engine: &mut Engine) -> Status { } } +pub fn obtain_cells_data(cl: Cell) -> Result> { + let mut byte_blob = Vec::new(); + let mut queue = vec!(cl.clone()); + while let Some(cell) = queue.pop() { + let this_reference_data = cell.data(); + + byte_blob.extend(this_reference_data[0..this_reference_data.len()-1].iter().copied()); + + let count = cell.references_count(); + for i in 0..count { + queue.push(cell.reference(i)?); + } + } + + Ok(byte_blob) +} + +pub(super) fn execute_vergrth16(engine: &mut Engine) -> Status { + engine.load_instruction(Instruction::new("VERGRTH16"))?; + fetch_stack(engine, 1)?; + let builder = engine.cmd.var(0).clone().as_builder_mut()?; + let cell_proof_data_length = builder.length_in_bits(); + let cell_proof = engine.finalize_cell(builder.into())?; + let cell_proof_data = obtain_cells_data(cell_proof).unwrap(); + if cell_proof_data_length % 8 == 0 { + let result = if cell_proof_data[0] == 0 { + verify_groth16_proof_from_byteblob::(&cell_proof_data[1..]).unwrap() + } else { + verify_encrypted_input_groth16_proof_from_byteblob::(&cell_proof_data[1..]).unwrap() + }; + engine.cc.stack.push(boolean!(result)); + return Ok(()) + } else { + err!(ExceptionCode::CellUnderflow) + } +} + enum DataForSignature { Hash(BuilderData), Slice(Vec) diff --git a/src/executor/engine/handlers.rs b/src/executor/engine/handlers.rs index 6fd3abe..1b63c67 100644 --- a/src/executor/engine/handlers.rs +++ b/src/executor/engine/handlers.rs @@ -894,6 +894,7 @@ impl Handlers { .set(0x02, execute_sha256u) .set(0x10, execute_chksignu) .set(0x11, execute_chksigns) + .set(0x12, execute_vergrth16) .set(0x40, execute_cdatasizeq) .set(0x41, execute_cdatasize) .set(0x42, execute_sdatasizeq)