From 349216441a95b5c183ea2e8a677eb4d9043f3f89 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Tue, 18 Jul 2023 14:00:12 -0600 Subject: [PATCH 01/20] split func merkle tree --- arbitrator/prover/src/machine.rs | 68 ++++++++++++++++++++++++-------- arbitrator/prover/src/merkle.rs | 6 ++- arbitrator/prover/src/wavm.rs | 21 ---------- 3 files changed, 56 insertions(+), 39 deletions(-) diff --git a/arbitrator/prover/src/machine.rs b/arbitrator/prover/src/machine.rs index d1f515f20..25572ac96 100644 --- a/arbitrator/prover/src/machine.rs +++ b/arbitrator/prover/src/machine.rs @@ -73,10 +73,40 @@ pub struct Function { code: Vec, ty: FunctionType, #[serde(skip)] - code_merkle: Merkle, + opcode_merkle: Merkle, + #[serde(skip)] + argument_data_merkle: Merkle, local_types: Vec, } +#[cfg(feature = "native")] +fn code_to_opcode_hashes(code: &Vec) -> Vec { + code.par_iter().map(|i| { + let mut b = [0u8; 32]; + b[30..].copy_from_slice(i.opcode.repr().to_be_bytes().as_slice()); + Bytes32(b) + }).collect() +} + +#[cfg(not(feature = "native"))] +fn code_to_opcode_hashes(code: &Vec) -> Merkle { + code.iter().map(|i| { + let mut b = [0u8; 32]; + b[30..].copy_from_slice(i.opcode.repr().to_be_bytes().as_slice()); + Bytes32(b) + }).collect() +} + +#[cfg(feature = "native")] +fn code_to_argdata_hashes(code: &Vec) -> Vec { + code.par_iter().map(|i| i.get_proving_argument_data()).collect() +} + +#[cfg(not(feature = "native"))] +fn code_to_argdata_hashes(code: &Vec) -> Vec { + code.iter().map(|i| i.get_proving_argument_data()).collect() +} + impl Function { pub fn new) -> Result<()>>( locals: &[Local], @@ -133,16 +163,14 @@ impl Function { "Function instruction count doesn't fit in a u32", ); - #[cfg(feature = "native")] - let code_hashes = code.par_iter().map(|i| i.hash()).collect(); - - #[cfg(not(feature = "native"))] - let code_hashes = code.iter().map(|i| i.hash()).collect(); + let argument_data_hashes = code_to_argdata_hashes(&code); + let opcode_hashes = code_to_opcode_hashes(&code); Function { code, ty, - code_merkle: Merkle::new(MerkleType::Instruction, code_hashes), + opcode_merkle:Merkle::new(MerkleType::Opcode, opcode_hashes), + argument_data_merkle: Merkle::new(MerkleType::ArgumentData, argument_data_hashes), local_types, } } @@ -150,7 +178,8 @@ impl Function { fn hash(&self) -> Bytes32 { let mut h = Keccak256::new(); h.update("Function:"); - h.update(self.code_merkle.root()); + h.update(self.opcode_merkle.root()); + h.update(self.argument_data_merkle.root()); h.finalize().into() } } @@ -1427,13 +1456,11 @@ impl Machine { let funcs = Arc::get_mut(&mut module.funcs).expect("Multiple copies of module functions"); for func in funcs.iter_mut() { - #[cfg(feature = "native")] - let code_hashes = func.code.par_iter().map(|i| i.hash()).collect(); + let opcode_hashes = code_to_opcode_hashes(&func.code); + let argdata_hashes = code_to_argdata_hashes(&func.code); - #[cfg(not(feature = "native"))] - let code_hashes = func.code.iter().map(|i| i.hash()).collect(); - - func.code_merkle = Merkle::new(MerkleType::Instruction, code_hashes); + func.opcode_merkle = Merkle::new(MerkleType::Opcode, opcode_hashes); + func.argument_data_merkle = Merkle::new(MerkleType::ArgumentData, argdata_hashes); } module.funcs_merkle = Arc::new(Merkle::new( MerkleType::Function, @@ -2640,11 +2667,20 @@ impl Machine { // Begin next instruction proof let func = &module.funcs[self.pc.func()]; - out!(func.code[self.pc.inst()].serialize_for_proof()); + let mut b = [0u8; 32]; + b[30..].copy_from_slice(func.code[self.pc.inst()].opcode.repr().to_be_bytes().as_slice()); + out!(b); + out!(func + .opcode_merkle + .prove(self.pc.inst()) + .expect("Failed to prove against code merkle")); + out!(func.code[self.pc.inst()].get_proving_argument_data()); out!(func - .code_merkle + .argument_data_merkle .prove(self.pc.inst()) .expect("Failed to prove against code merkle")); + println!("\nopcode {} argdata {}", func.code[self.pc.inst()].opcode.repr(), func.code[self.pc.inst()].get_proving_argument_data()); + println!("opcodeMerkle {} argdataMerkle {} funcMerkle {}", func.opcode_merkle.root(), func.argument_data_merkle.root(), module.funcs_merkle.root()); out!(module .funcs_merkle .prove(self.pc.func()) diff --git a/arbitrator/prover/src/merkle.rs b/arbitrator/prover/src/merkle.rs index c00712821..dc6f53168 100644 --- a/arbitrator/prover/src/merkle.rs +++ b/arbitrator/prover/src/merkle.rs @@ -14,7 +14,8 @@ pub enum MerkleType { Empty, Value, Function, - Instruction, + Opcode, + ArgumentData, Memory, Table, TableElement, @@ -33,7 +34,8 @@ impl MerkleType { MerkleType::Empty => panic!("Attempted to get prefix of empty merkle type"), MerkleType::Value => "Value merkle tree:", MerkleType::Function => "Function merkle tree:", - MerkleType::Instruction => "Instruction merkle tree:", + MerkleType::Opcode => "Opcode merkle tree:", + MerkleType::ArgumentData => "Argument data merkle tree:", MerkleType::Memory => "Memory merkle tree:", MerkleType::Table => "Table merkle tree:", MerkleType::TableElement => "Table element merkle tree:", diff --git a/arbitrator/prover/src/wavm.rs b/arbitrator/prover/src/wavm.rs index 54aa3d0a8..fd6d10f8d 100644 --- a/arbitrator/prover/src/wavm.rs +++ b/arbitrator/prover/src/wavm.rs @@ -7,13 +7,11 @@ use crate::{ value::{ArbValueType, FunctionType, IntegerValType}, }; use arbutil::Bytes32; -use digest::Digest; use eyre::{bail, ensure, Result}; use fnv::FnvHashMap as HashMap; use lazy_static::lazy_static; use parking_lot::Mutex; use serde::{Deserialize, Serialize}; -use sha3::Keccak256; use std::ops::{Add, AddAssign, Sub, SubAssign}; use wasmparser::{Operator, Type, TypeOrFuncType as BlockType}; @@ -368,25 +366,6 @@ impl Instruction { ret } - pub fn hash(&self) -> Bytes32 { - let dataless = self.proving_argument_data.is_none() && self.argument_data == 0; - if dataless { - if let Some(hash) = OP_HASHES.lock().get(&self.opcode) { - return *hash; - } - } - - let mut h = Keccak256::new(); - h.update(b"Instruction:"); - h.update(self.opcode.repr().to_be_bytes()); - h.update(self.get_proving_argument_data()); - let hash: Bytes32 = h.finalize().into(); - - if dataless { - OP_HASHES.lock().insert(self.opcode, hash); - } - hash - } } /// Note: An Unreachable stack state is equal to any other stack state. From ed07ddbedc76243978199cd9ad809eb0c91be0c9 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Tue, 18 Jul 2023 17:38:48 -0600 Subject: [PATCH 02/20] machine: 16 opcodes per opcode-merkle entry --- arbitrator/prover/src/machine.rs | 46 ++++++++++++++++---------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/arbitrator/prover/src/machine.rs b/arbitrator/prover/src/machine.rs index 25572ac96..ccc2d9139 100644 --- a/arbitrator/prover/src/machine.rs +++ b/arbitrator/prover/src/machine.rs @@ -39,6 +39,7 @@ use std::{ num::Wrapping, path::{Path, PathBuf}, sync::Arc, + cmp::min, }; use wasmer_types::FunctionIndex; use wasmparser::{DataKind, ElementItem, ElementKind, Operator, TableType}; @@ -79,22 +80,25 @@ pub struct Function { local_types: Vec, } -#[cfg(feature = "native")] -fn code_to_opcode_hashes(code: &Vec) -> Vec { - code.par_iter().map(|i| { - let mut b = [0u8; 32]; - b[30..].copy_from_slice(i.opcode.repr().to_be_bytes().as_slice()); - Bytes32(b) - }).collect() +fn code_to_opcode_hash(code: &Vec, opcode_idx:usize) -> Bytes32 { + let seg = opcode_idx/16; + let seg_start = seg*16; + let seg_end = min(seg_start + 16, code.len()); + let mut b = [0u8; 32]; + for i in 0..(seg_end-seg_start){ + b[i*2..i*2+2].copy_from_slice(code[seg_start + i].opcode.repr().to_be_bytes().as_slice()) + } + Bytes32(b) } -#[cfg(not(feature = "native"))] -fn code_to_opcode_hashes(code: &Vec) -> Merkle { - code.iter().map(|i| { - let mut b = [0u8; 32]; - b[30..].copy_from_slice(i.opcode.repr().to_be_bytes().as_slice()); - Bytes32(b) - }).collect() +fn code_to_opcode_hashes(code: &Vec) -> Vec { + #[cfg(feature = "native")] + let iter = (0..(code.len()+15)/16).into_par_iter(); + + #[cfg(not(feature = "native"))] + let iter = (0..(code.len()+15)/16).into_iter(); + + iter.map(|i|code_to_opcode_hash(code, i*16)).collect() } #[cfg(feature = "native")] @@ -1459,8 +1463,8 @@ impl Machine { let opcode_hashes = code_to_opcode_hashes(&func.code); let argdata_hashes = code_to_argdata_hashes(&func.code); - func.opcode_merkle = Merkle::new(MerkleType::Opcode, opcode_hashes); - func.argument_data_merkle = Merkle::new(MerkleType::ArgumentData, argdata_hashes); + func.opcode_merkle = Merkle::new_advanced(MerkleType::Opcode, opcode_hashes, Bytes32::default(), 2); + func.argument_data_merkle = Merkle::new_advanced(MerkleType::ArgumentData, argdata_hashes, Bytes32::default(), 2); } module.funcs_merkle = Arc::new(Merkle::new( MerkleType::Function, @@ -2667,20 +2671,16 @@ impl Machine { // Begin next instruction proof let func = &module.funcs[self.pc.func()]; - let mut b = [0u8; 32]; - b[30..].copy_from_slice(func.code[self.pc.inst()].opcode.repr().to_be_bytes().as_slice()); - out!(b); + out!(code_to_opcode_hash(&func.code, self.pc.inst())); out!(func .opcode_merkle - .prove(self.pc.inst()) + .prove(self.pc.inst()/16) .expect("Failed to prove against code merkle")); out!(func.code[self.pc.inst()].get_proving_argument_data()); out!(func .argument_data_merkle .prove(self.pc.inst()) - .expect("Failed to prove against code merkle")); - println!("\nopcode {} argdata {}", func.code[self.pc.inst()].opcode.repr(), func.code[self.pc.inst()].get_proving_argument_data()); - println!("opcodeMerkle {} argdataMerkle {} funcMerkle {}", func.opcode_merkle.root(), func.argument_data_merkle.root(), module.funcs_merkle.root()); + .expect("Failed to prove against argument data merkle")); out!(module .funcs_merkle .prove(self.pc.func()) From ed4ad2008c862bf0abc61120b7fd65b4ecbe6add Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Tue, 18 Jul 2023 18:24:58 -0600 Subject: [PATCH 03/20] optimize merkle of empty data --- arbitrator/prover/src/merkle.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/arbitrator/prover/src/merkle.rs b/arbitrator/prover/src/merkle.rs index dc6f53168..6db59250b 100644 --- a/arbitrator/prover/src/merkle.rs +++ b/arbitrator/prover/src/merkle.rs @@ -85,10 +85,18 @@ impl Merkle { #[cfg(not(feature = "native"))] let new_layer = layers.last().unwrap().chunks(2); + let new_empty_layer = hash_node(ty, empty_layer, empty_layer); let new_layer = new_layer - .map(|chunk| hash_node(ty, chunk[0], chunk.get(1).cloned().unwrap_or(empty_layer))) - .collect(); - empty_layers.push(hash_node(ty, empty_layer, empty_layer)); + .map(|chunk| { + let left = chunk[0]; + let right = chunk.get(1).cloned().unwrap_or(empty_layer); + if left == empty_layer && right == empty_layer { + new_empty_layer + } else { + hash_node(ty, left, right) + } + }).collect(); + empty_layers.push(new_empty_layer); layers.push(new_layer); } Merkle { From 7803babb15527810fd7f6be30b11a3a0e0b13a9a Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Tue, 18 Jul 2023 19:06:02 -0600 Subject: [PATCH 04/20] rustfmt fixes --- arbitrator/prover/src/machine.rs | 39 ++++++++++++++++++++------------ arbitrator/prover/src/merkle.rs | 3 ++- arbitrator/prover/src/wavm.rs | 1 - 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/arbitrator/prover/src/machine.rs b/arbitrator/prover/src/machine.rs index ccc2d9139..d996e7790 100644 --- a/arbitrator/prover/src/machine.rs +++ b/arbitrator/prover/src/machine.rs @@ -31,6 +31,7 @@ use sha3::Keccak256; use smallvec::SmallVec; use std::{ borrow::Cow, + cmp::min, convert::{TryFrom, TryInto}, fmt::{self, Display}, fs::File, @@ -39,7 +40,6 @@ use std::{ num::Wrapping, path::{Path, PathBuf}, sync::Arc, - cmp::min, }; use wasmer_types::FunctionIndex; use wasmparser::{DataKind, ElementItem, ElementKind, Operator, TableType}; @@ -80,30 +80,33 @@ pub struct Function { local_types: Vec, } -fn code_to_opcode_hash(code: &Vec, opcode_idx:usize) -> Bytes32 { - let seg = opcode_idx/16; - let seg_start = seg*16; +fn code_to_opcode_hash(code: &Vec, opcode_idx: usize) -> Bytes32 { + let seg = opcode_idx / 16; + let seg_start = seg * 16; let seg_end = min(seg_start + 16, code.len()); let mut b = [0u8; 32]; - for i in 0..(seg_end-seg_start){ - b[i*2..i*2+2].copy_from_slice(code[seg_start + i].opcode.repr().to_be_bytes().as_slice()) + for i in 0..(seg_end - seg_start) { + b[i * 2..i * 2 + 2] + .copy_from_slice(code[seg_start + i].opcode.repr().to_be_bytes().as_slice()) } Bytes32(b) } -fn code_to_opcode_hashes(code: &Vec) -> Vec { +fn code_to_opcode_hashes(code: &Vec) -> Vec { #[cfg(feature = "native")] - let iter = (0..(code.len()+15)/16).into_par_iter(); + let iter = (0..(code.len() + 15) / 16).into_par_iter(); #[cfg(not(feature = "native"))] - let iter = (0..(code.len()+15)/16).into_iter(); + let iter = (0..(code.len() + 15) / 16).into_iter(); - iter.map(|i|code_to_opcode_hash(code, i*16)).collect() + iter.map(|i| code_to_opcode_hash(code, i * 16)).collect() } #[cfg(feature = "native")] fn code_to_argdata_hashes(code: &Vec) -> Vec { - code.par_iter().map(|i| i.get_proving_argument_data()).collect() + code.par_iter() + .map(|i| i.get_proving_argument_data()) + .collect() } #[cfg(not(feature = "native"))] @@ -173,7 +176,7 @@ impl Function { Function { code, ty, - opcode_merkle:Merkle::new(MerkleType::Opcode, opcode_hashes), + opcode_merkle: Merkle::new(MerkleType::Opcode, opcode_hashes), argument_data_merkle: Merkle::new(MerkleType::ArgumentData, argument_data_hashes), local_types, } @@ -1463,8 +1466,14 @@ impl Machine { let opcode_hashes = code_to_opcode_hashes(&func.code); let argdata_hashes = code_to_argdata_hashes(&func.code); - func.opcode_merkle = Merkle::new_advanced(MerkleType::Opcode, opcode_hashes, Bytes32::default(), 2); - func.argument_data_merkle = Merkle::new_advanced(MerkleType::ArgumentData, argdata_hashes, Bytes32::default(), 2); + func.opcode_merkle = + Merkle::new_advanced(MerkleType::Opcode, opcode_hashes, Bytes32::default(), 2); + func.argument_data_merkle = Merkle::new_advanced( + MerkleType::ArgumentData, + argdata_hashes, + Bytes32::default(), + 2, + ); } module.funcs_merkle = Arc::new(Merkle::new( MerkleType::Function, @@ -2674,7 +2683,7 @@ impl Machine { out!(code_to_opcode_hash(&func.code, self.pc.inst())); out!(func .opcode_merkle - .prove(self.pc.inst()/16) + .prove(self.pc.inst() / 16) .expect("Failed to prove against code merkle")); out!(func.code[self.pc.inst()].get_proving_argument_data()); out!(func diff --git a/arbitrator/prover/src/merkle.rs b/arbitrator/prover/src/merkle.rs index 6db59250b..a5c5e9bd4 100644 --- a/arbitrator/prover/src/merkle.rs +++ b/arbitrator/prover/src/merkle.rs @@ -95,7 +95,8 @@ impl Merkle { } else { hash_node(ty, left, right) } - }).collect(); + }) + .collect(); empty_layers.push(new_empty_layer); layers.push(new_layer); } diff --git a/arbitrator/prover/src/wavm.rs b/arbitrator/prover/src/wavm.rs index fd6d10f8d..de0bf7c36 100644 --- a/arbitrator/prover/src/wavm.rs +++ b/arbitrator/prover/src/wavm.rs @@ -365,7 +365,6 @@ impl Instruction { ret[2..].copy_from_slice(&*self.get_proving_argument_data()); ret } - } /// Note: An Unreachable stack state is equal to any other stack state. From 46adb4bcbda70105ea4cfa4c26c60bbe296eecfb Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 19 Jul 2023 15:37:19 -0600 Subject: [PATCH 05/20] machine: remove now-unused code --- arbitrator/prover/src/wavm.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/arbitrator/prover/src/wavm.rs b/arbitrator/prover/src/wavm.rs index de0bf7c36..a2e1e1ae6 100644 --- a/arbitrator/prover/src/wavm.rs +++ b/arbitrator/prover/src/wavm.rs @@ -358,13 +358,6 @@ impl Instruction { Bytes32(b) } } - - pub fn serialize_for_proof(self) -> [u8; 34] { - let mut ret = [0u8; 34]; - ret[..2].copy_from_slice(&self.opcode.repr().to_be_bytes()); - ret[2..].copy_from_slice(&*self.get_proving_argument_data()); - ret - } } /// Note: An Unreachable stack state is equal to any other stack state. From 7ee2398d427240d943ea4b965274d85fa56877b9 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 19 Jul 2023 15:37:55 -0600 Subject: [PATCH 06/20] wasm test-cases: update linked module hashes --- arbitrator/prover/test-cases/dynamic.wat | 2 +- arbitrator/prover/test-cases/link.wat | 26 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/arbitrator/prover/test-cases/dynamic.wat b/arbitrator/prover/test-cases/dynamic.wat index 0505e074b..283c115c7 100644 --- a/arbitrator/prover/test-cases/dynamic.wat +++ b/arbitrator/prover/test-cases/dynamic.wat @@ -7,7 +7,7 @@ (import "hostio" "program_ink_status" (func $ink_status (param i32 i32) (result i32))) (import "hostio" "program_call_main" (func $user_func (param i32 i32 i32) (result i32))) (data (i32.const 0x0) - "\dd\13\30\ba\64\c6\e1\e9\e9\c3\b0\f9\63\c8\d9\69\c9\f0\13\70\42\17\f3\9e\60\c3\0d\13\5b\48\a5\88") ;; user + "\79\ab\25\ae\44\5f\37\d5\e4\4f\2f\b8\9f\43\c7\ba\4c\c0\66\3b\97\e9\ab\0c\88\a0\ba\01\02\3e\b7\a5") ;; user (func $start (local $user i32) (local $internals i32) ;; link in user.wat i32.const 0 diff --git a/arbitrator/prover/test-cases/link.wat b/arbitrator/prover/test-cases/link.wat index 69597f737..9ec47c8b2 100644 --- a/arbitrator/prover/test-cases/link.wat +++ b/arbitrator/prover/test-cases/link.wat @@ -5,31 +5,31 @@ (import "hostio" "wavm_link_module" (func $link (param i32) (result i32))) (import "hostio" "wavm_unlink_module" (func $unlink (param) (result))) (data (i32.const 0x000) - "\b8\ef\6c\9d\e3\a2\aa\9a\94\56\09\7b\13\ef\19\ab\82\ab\c6\d2\eb\76\ca\72\9a\dd\b8\20\84\7b\7a\f7") ;; block + "\2e\fa\1a\aa\e7\14\f2\63\bc\a1\c3\76\8a\46\e9\04\8a\a5\e7\c0\2d\fe\86\cc\30\0d\7e\de\18\1e\5a\46") (data (i32.const 0x020) - "\e0\7a\1c\2e\5f\26\ab\ff\5b\ef\d4\ae\b4\c1\7a\18\52\06\cd\be\9c\ea\fb\c3\b6\4a\03\4b\c0\c4\51\14") ;; call + "\1f\cd\e2\81\95\13\e0\4d\c5\c2\ce\f7\63\e7\18\10\db\f8\b2\eb\56\3f\37\b1\35\f6\61\67\02\91\7a\9d") (data (i32.const 0x040) - "\4c\85\59\6e\e9\89\38\42\7e\52\63\f5\98\c9\fe\23\4a\17\11\d8\37\e3\ed\d4\2a\93\e7\32\15\c2\d7\1c") ;; indirect + "\6f\5f\86\5e\fd\50\47\4a\71\22\bf\7f\e0\25\80\e1\2d\58\2c\3c\a5\f3\68\20\70\f4\c1\af\cd\c5\d5\1a") (data (i32.const 0x060) - "\f9\0f\a0\15\f7\e0\52\c2\c8\ec\ac\1c\b7\a3\58\8c\00\52\52\95\a1\ec\a0\55\90\74\aa\11\3f\4e\75\55") ;; const + "\7f\58\de\0d\bc\ed\d2\ef\5e\b0\f8\37\6c\0b\84\0f\52\86\4d\b6\08\87\be\be\44\b7\7a\e4\a4\24\e2\de") (data (i32.const 0x080) - "\2d\e2\b0\dd\15\63\31\27\e5\31\2d\2d\23\e4\13\67\a0\d5\4d\0e\66\d9\2d\79\37\5d\44\7c\d0\80\f8\b0") ;; div + "\4e\16\85\9c\b7\f3\ed\8d\e3\98\30\36\5a\ef\c9\aa\c6\31\fb\1e\39\54\a5\bd\09\9a\01\a5\6d\03\d6\17") (data (i32.const 0x0a0) - "\91\7a\9d\9d\03\77\07\f0\f7\84\b4\f1\01\e5\50\ff\5f\40\13\34\c1\af\c1\f2\f6\8f\f7\03\a3\ba\32\47") ;; globals + "\4d\88\c3\ad\5b\31\5e\96\1c\79\cb\44\ee\f4\b9\42\18\da\fc\25\c1\26\fd\a5\1e\d4\b5\30\6c\59\38\ab") (data (i32.const 0x0c0) - "\31\81\c9\76\80\55\57\40\6d\93\0d\46\3b\60\31\de\4b\0f\93\14\8e\78\58\63\8c\66\88\55\c3\d3\47\b2") ;; if-else + "\ac\23\98\89\12\fc\97\81\88\66\e8\19\dc\f6\f5\33\9d\75\bf\ae\6a\b2\0c\2a\5a\b4\12\87\29\1f\e2\d1") (data (i32.const 0x0e0) - "\8d\e8\a2\29\d8\22\25\97\3e\57\7f\17\2f\b0\24\94\3f\fe\73\6b\ef\34\18\10\4b\18\73\87\4c\3d\97\88") ;; locals + "\79\ab\25\ae\44\5f\37\d5\e4\4f\2f\b8\9f\43\c7\ba\4c\c0\66\3b\97\e9\ab\0c\88\a0\ba\01\02\3e\b7\a5") (data (i32.const 0x100) - "\6a\0b\f4\9a\9f\c4\68\18\a5\23\79\11\bf\3a\8d\02\72\ea\e1\21\db\b8\f3\a5\72\d3\66\9a\27\f1\01\74") ;; loop + "\dd\34\a3\48\d3\a0\b3\05\bc\c1\b7\de\fb\87\ec\00\d7\43\26\5e\6b\22\85\26\a2\77\35\e1\a2\ca\3c\79") (data (i32.const 0x120) - "\35\fb\41\8d\94\da\56\dc\3b\2e\8f\6c\7f\43\bf\dd\9a\30\7c\27\b9\b2\e0\dd\7d\15\29\36\53\ca\b7\77") ;; math + "\6f\d2\78\74\f4\a5\3b\84\1f\69\5c\80\5e\7c\12\52\ee\50\92\c2\f7\4f\ba\ab\35\51\84\53\fd\90\a8\11") (data (i32.const 0x140) - "\26\d0\56\ce\4a\fa\f1\ef\cd\d2\7a\4d\64\48\a3\86\5a\00\5f\6f\89\7e\a4\95\5c\b9\2d\b8\f1\04\eb\3e") ;; iops + "\cb\ff\fb\39\a0\f9\d4\3e\4a\46\a4\67\68\37\09\5e\d7\4e\3e\c9\76\da\60\fc\d9\44\93\5d\ef\8d\6d\0c") (data (i32.const 0x160) - "\dd\13\30\ba\64\c6\e1\e9\e9\c3\b0\f9\63\c8\d9\69\c9\f0\13\70\42\17\f3\9e\60\c3\0d\13\5b\48\a5\88") ;; user + "\c6\62\35\4e\f0\98\48\b7\af\03\5f\8d\09\92\8f\bf\cc\7d\71\1c\3e\88\19\11\77\6b\cd\c4\20\91\4c\3c") (data (i32.const 0x180) - "\07\33\43\e0\1d\b9\16\3e\99\1a\99\bd\cc\93\bf\26\15\f4\4c\11\c3\32\c0\2c\65\ba\76\11\76\eb\c1\7b") ;; return + "\c6\50\44\e7\ff\43\22\65\1c\19\65\48\57\0a\40\c7\20\62\2c\b2\0e\3a\71\cf\a7\05\2c\f2\6f\dc\5e\06") (func $start (local $counter i32) ;; add modules From 624962d44d2d9f722759eced90b4dcd37823af29 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Wed, 19 Jul 2023 16:03:37 -0600 Subject: [PATCH 07/20] update contract to new func-merkles --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index 623a8f017..601fa9692 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 623a8f017d0e1cb9e55fe8ee8c46e9ac326d07f6 +Subproject commit 601fa9692677df7ee1968d6bfae5941958cdfa3a From 88d729e6c7b1872312dfe004ab25a3ab2b16a895 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 20 Jul 2023 07:31:30 -0600 Subject: [PATCH 08/20] bugfix: loading machine from wavm used different hash --- arbitrator/prover/src/machine.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/arbitrator/prover/src/machine.rs b/arbitrator/prover/src/machine.rs index d996e7790..331d9a614 100644 --- a/arbitrator/prover/src/machine.rs +++ b/arbitrator/prover/src/machine.rs @@ -176,8 +176,18 @@ impl Function { Function { code, ty, - opcode_merkle: Merkle::new(MerkleType::Opcode, opcode_hashes), - argument_data_merkle: Merkle::new(MerkleType::ArgumentData, argument_data_hashes), + opcode_merkle: Merkle::new_advanced( + MerkleType::Opcode, + opcode_hashes, + Bytes32::default(), + 2, + ), + argument_data_merkle: Merkle::new_advanced( + MerkleType::ArgumentData, + argument_data_hashes, + Bytes32::default(), + 2, + ), local_types, } } From cae6719a513c912f36b9689ebc509784d16bcd14 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 20 Jul 2023 10:22:18 -0600 Subject: [PATCH 09/20] update merkle roots on wavm tests --- arbitrator/prover/test-cases/dynamic.wat | 3 +-- arbitrator/prover/test-cases/link.wat | 27 ++++++++++++------------ 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/arbitrator/prover/test-cases/dynamic.wat b/arbitrator/prover/test-cases/dynamic.wat index 283c115c7..4a943e7b2 100644 --- a/arbitrator/prover/test-cases/dynamic.wat +++ b/arbitrator/prover/test-cases/dynamic.wat @@ -7,8 +7,7 @@ (import "hostio" "program_ink_status" (func $ink_status (param i32 i32) (result i32))) (import "hostio" "program_call_main" (func $user_func (param i32 i32 i32) (result i32))) (data (i32.const 0x0) - "\79\ab\25\ae\44\5f\37\d5\e4\4f\2f\b8\9f\43\c7\ba\4c\c0\66\3b\97\e9\ab\0c\88\a0\ba\01\02\3e\b7\a5") ;; user - (func $start (local $user i32) (local $internals i32) + "\0a\3e\95\a0\01\bf\38\a7\f9\c0\4b\74\53\06\fc\a9\be\6b\4a\84\65\7e\04\b1\43\12\d9\e3\fd\5b\4d\ab") (func $start (local $user i32) (local $internals i32) ;; link in user.wat i32.const 0 call $link diff --git a/arbitrator/prover/test-cases/link.wat b/arbitrator/prover/test-cases/link.wat index 9ec47c8b2..74cb5e7c0 100644 --- a/arbitrator/prover/test-cases/link.wat +++ b/arbitrator/prover/test-cases/link.wat @@ -5,32 +5,31 @@ (import "hostio" "wavm_link_module" (func $link (param i32) (result i32))) (import "hostio" "wavm_unlink_module" (func $unlink (param) (result))) (data (i32.const 0x000) - "\2e\fa\1a\aa\e7\14\f2\63\bc\a1\c3\76\8a\46\e9\04\8a\a5\e7\c0\2d\fe\86\cc\30\0d\7e\de\18\1e\5a\46") + "\3e\2b\a8\7c\04\f9\c9\36\57\b8\a8\20\eb\b4\74\13\11\b2\36\48\8e\01\36\50\b3\59\d4\50\b7\15\86\a1") (data (i32.const 0x020) - "\1f\cd\e2\81\95\13\e0\4d\c5\c2\ce\f7\63\e7\18\10\db\f8\b2\eb\56\3f\37\b1\35\f6\61\67\02\91\7a\9d") + "\cd\ef\2c\33\e2\88\88\0f\95\e5\56\f6\f2\09\eb\c1\12\6c\5e\d3\3e\f1\3a\ee\b1\de\6a\6b\1d\72\55\0a") (data (i32.const 0x040) - "\6f\5f\86\5e\fd\50\47\4a\71\22\bf\7f\e0\25\80\e1\2d\58\2c\3c\a5\f3\68\20\70\f4\c1\af\cd\c5\d5\1a") + "\e9\a4\72\b9\ac\2c\39\c3\bd\07\ba\2a\07\27\01\37\1f\0d\4a\4f\32\37\b4\9b\76\b2\2f\82\75\c5\e5\db") (data (i32.const 0x060) - "\7f\58\de\0d\bc\ed\d2\ef\5e\b0\f8\37\6c\0b\84\0f\52\86\4d\b6\08\87\be\be\44\b7\7a\e4\a4\24\e2\de") + "\0a\3e\95\a0\01\bf\38\a7\f9\c0\4b\74\53\06\fc\a9\be\6b\4a\84\65\7e\04\b1\43\12\d9\e3\fd\5b\4d\ab") (data (i32.const 0x080) - "\4e\16\85\9c\b7\f3\ed\8d\e3\98\30\36\5a\ef\c9\aa\c6\31\fb\1e\39\54\a5\bd\09\9a\01\a5\6d\03\d6\17") + "\17\38\60\10\80\4d\6b\4e\04\51\1f\af\b8\5f\73\a3\97\70\6f\e4\ce\0e\a4\c2\1a\e0\b5\96\32\d2\e7\0b") (data (i32.const 0x0a0) - "\4d\88\c3\ad\5b\31\5e\96\1c\79\cb\44\ee\f4\b9\42\18\da\fc\25\c1\26\fd\a5\1e\d4\b5\30\6c\59\38\ab") + "\04\b3\01\ae\24\d9\10\12\fe\be\a3\2a\0f\ee\8c\20\6a\bc\af\d4\40\c0\70\62\d9\7f\40\ae\fb\f1\41\cd") (data (i32.const 0x0c0) - "\ac\23\98\89\12\fc\97\81\88\66\e8\19\dc\f6\f5\33\9d\75\bf\ae\6a\b2\0c\2a\5a\b4\12\87\29\1f\e2\d1") + "\8f\0a\38\39\b9\f2\d7\ba\3f\24\53\59\02\c6\f6\4e\c5\f1\5c\5d\cf\16\8f\9b\6d\7e\2b\ec\cc\c8\90\c2") (data (i32.const 0x0e0) - "\79\ab\25\ae\44\5f\37\d5\e4\4f\2f\b8\9f\43\c7\ba\4c\c0\66\3b\97\e9\ab\0c\88\a0\ba\01\02\3e\b7\a5") + "\7f\73\86\67\a0\b5\c3\85\43\a4\4d\05\ab\9e\1d\9b\68\c5\c8\cc\03\f4\fa\5b\98\64\27\6e\e6\26\5e\c0") (data (i32.const 0x100) - "\dd\34\a3\48\d3\a0\b3\05\bc\c1\b7\de\fb\87\ec\00\d7\43\26\5e\6b\22\85\26\a2\77\35\e1\a2\ca\3c\79") + "\4b\c3\5f\e7\d7\63\0e\13\29\e4\a7\c0\7b\cb\5c\b4\44\d8\d7\b0\53\52\d4\d3\64\90\7f\35\d3\a8\25\53") (data (i32.const 0x120) - "\6f\d2\78\74\f4\a5\3b\84\1f\69\5c\80\5e\7c\12\52\ee\50\92\c2\f7\4f\ba\ab\35\51\84\53\fd\90\a8\11") + "\6c\bc\c4\8f\38\8c\9f\f3\e5\74\67\35\b4\9f\63\c9\f2\8f\71\b1\12\d7\60\3d\d9\4d\5f\0c\ce\ca\3f\e3") (data (i32.const 0x140) - "\cb\ff\fb\39\a0\f9\d4\3e\4a\46\a4\67\68\37\09\5e\d7\4e\3e\c9\76\da\60\fc\d9\44\93\5d\ef\8d\6d\0c") + "\dd\86\00\e8\70\cb\a5\57\92\7f\00\d3\ab\57\8a\a3\43\c6\f1\d2\f3\47\0a\12\33\96\69\0b\44\4d\87\8d") (data (i32.const 0x160) - "\c6\62\35\4e\f0\98\48\b7\af\03\5f\8d\09\92\8f\bf\cc\7d\71\1c\3e\88\19\11\77\6b\cd\c4\20\91\4c\3c") + "\a8\65\a9\40\f3\d1\3d\dc\a4\25\e8\ce\d2\e6\44\5e\53\c3\47\3c\d0\c5\2d\8d\f8\71\0b\39\d6\b8\fb\ae") (data (i32.const 0x180) - "\c6\50\44\e7\ff\43\22\65\1c\19\65\48\57\0a\40\c7\20\62\2c\b2\0e\3a\71\cf\a7\05\2c\f2\6f\dc\5e\06") - (func $start (local $counter i32) + "\bf\3c\c7\d8\b7\5e\dc\e0\93\3d\d5\fb\b6\3e\ec\39\c0\88\1e\fd\91\d1\ea\45\da\e4\c0\78\af\74\4b\cc") (func $start (local $counter i32) ;; add modules (loop $top From aaa0b60a7cb4ca6ff200e67051e1af48ddd20655 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Thu, 20 Jul 2023 11:56:59 -0600 Subject: [PATCH 10/20] cache and reuse empty merkle layers --- arbitrator/prover/src/machine.rs | 24 ++------- arbitrator/prover/src/memory.rs | 16 +++--- arbitrator/prover/src/merkle.rs | 83 +++++++++++++++++++++++--------- arbitrator/prover/src/wavm.rs | 6 --- 4 files changed, 71 insertions(+), 58 deletions(-) diff --git a/arbitrator/prover/src/machine.rs b/arbitrator/prover/src/machine.rs index 331d9a614..8a31a15bd 100644 --- a/arbitrator/prover/src/machine.rs +++ b/arbitrator/prover/src/machine.rs @@ -176,18 +176,8 @@ impl Function { Function { code, ty, - opcode_merkle: Merkle::new_advanced( - MerkleType::Opcode, - opcode_hashes, - Bytes32::default(), - 2, - ), - argument_data_merkle: Merkle::new_advanced( - MerkleType::ArgumentData, - argument_data_hashes, - Bytes32::default(), - 2, - ), + opcode_merkle: Merkle::new(MerkleType::Opcode, opcode_hashes), + argument_data_merkle: Merkle::new(MerkleType::ArgumentData, argument_data_hashes), local_types, } } @@ -1476,14 +1466,8 @@ impl Machine { let opcode_hashes = code_to_opcode_hashes(&func.code); let argdata_hashes = code_to_argdata_hashes(&func.code); - func.opcode_merkle = - Merkle::new_advanced(MerkleType::Opcode, opcode_hashes, Bytes32::default(), 2); - func.argument_data_merkle = Merkle::new_advanced( - MerkleType::ArgumentData, - argdata_hashes, - Bytes32::default(), - 2, - ); + func.opcode_merkle = Merkle::new(MerkleType::Opcode, opcode_hashes); + func.argument_data_merkle = Merkle::new(MerkleType::ArgumentData, argdata_hashes); } module.funcs_merkle = Arc::new(Merkle::new( MerkleType::Function, diff --git a/arbitrator/prover/src/memory.rs b/arbitrator/prover/src/memory.rs index 60fe15bad..7d97c9693 100644 --- a/arbitrator/prover/src/memory.rs +++ b/arbitrator/prover/src/memory.rs @@ -8,6 +8,7 @@ use crate::{ use arbutil::Bytes32; use digest::Digest; use eyre::{bail, ErrReport, Result}; +use lazy_static::lazy_static; use serde::{Deserialize, Serialize}; use sha3::Keccak256; use std::{borrow::Cow, convert::TryFrom}; @@ -59,6 +60,10 @@ fn hash_leaf(bytes: [u8; Memory::LEAF_SIZE]) -> Bytes32 { h.finalize().into() } +lazy_static! { + pub static ref EMPTY_MEM_HASH: Bytes32 = hash_leaf([0u8; 32]); +} + fn round_up_to_power_of_two(mut input: usize) -> usize { if input == 0 { return 1; @@ -84,7 +89,7 @@ impl Memory { pub const PAGE_SIZE: u64 = 65536; /// The number of layers in the memory merkle tree /// 1 + log2(2^32 / LEAF_SIZE) = 1 + log2(2^(32 - log2(LEAF_SIZE))) = 1 + 32 - 5 - const MEMORY_LAYERS: usize = 1 + 32 - 5; + pub const MEMORY_LAYERS: usize = 1 + 32 - 5; pub fn new(size: usize, max_size: u64) -> Memory { Memory { @@ -119,15 +124,10 @@ impl Memory { }) .collect(); if leaf_hashes.len() < leaves { - let empty_hash = hash_leaf([0u8; 32]); + let empty_hash = *EMPTY_MEM_HASH; leaf_hashes.resize(leaves, empty_hash); } - Cow::Owned(Merkle::new_advanced( - MerkleType::Memory, - leaf_hashes, - hash_leaf([0u8; 32]), - Self::MEMORY_LAYERS, - )) + Cow::Owned(Merkle::new(MerkleType::Memory, leaf_hashes)) } pub fn get_leaf_data(&self, leaf_idx: usize) -> [u8; Self::LEAF_SIZE] { diff --git a/arbitrator/prover/src/merkle.rs b/arbitrator/prover/src/merkle.rs index a5c5e9bd4..cf868d88f 100644 --- a/arbitrator/prover/src/merkle.rs +++ b/arbitrator/prover/src/merkle.rs @@ -1,15 +1,18 @@ // Copyright 2021-2023, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE +use crate::memory::{Memory, EMPTY_MEM_HASH}; use arbutil::Bytes32; use digest::Digest; +use lazy_static::lazy_static; use sha3::Keccak256; -use std::convert::TryFrom; +use std::collections::HashMap; +use std::sync::RwLock; #[cfg(feature = "native")] use rayon::prelude::*; -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] pub enum MerkleType { Empty, Value, @@ -48,7 +51,6 @@ impl MerkleType { pub struct Merkle { ty: MerkleType, layers: Vec>, - empty_layers: Vec, min_depth: usize, } @@ -60,24 +62,63 @@ fn hash_node(ty: MerkleType, a: Bytes32, b: Bytes32) -> Bytes32 { h.finalize().into() } +lazy_static! { + static ref EMPTY_LAYERS: RwLock>>> = Default::default(); +} + impl Merkle { - pub fn new(ty: MerkleType, hashes: Vec) -> Merkle { - Self::new_advanced(ty, hashes, Bytes32::default(), 0) + fn get_empty_readonly(ty: MerkleType, layer: usize) -> Option { + match EMPTY_LAYERS.read().unwrap().get(&ty) { + None => None, + Some(rwvec) => rwvec.read().unwrap().get(layer).copied(), + } } - pub fn new_advanced( - ty: MerkleType, - hashes: Vec, - empty_hash: Bytes32, - min_depth: usize, - ) -> Merkle { + pub fn get_empty(ty: MerkleType, layer: usize) -> Bytes32 { + let exists = Self::get_empty_readonly(ty, layer); + if let Some(val_exists) = exists { + return val_exists; + } + let new_val: Bytes32; + if layer == 0 { + new_val = match ty { + MerkleType::Empty => { + panic!("attempted to fetch empty-layer value from empty merkle") + } + MerkleType::Memory => *EMPTY_MEM_HASH, + _ => Bytes32::default(), + } + } else { + let prev_val = Self::get_empty(ty, layer - 1); + new_val = hash_node(ty, prev_val, prev_val); + } + let mut layers = EMPTY_LAYERS.write().unwrap(); + let mut typed = layers.entry(ty).or_default().write().unwrap(); + if typed.len() > layer { + assert_eq!(typed[layer], new_val); + } else if typed.len() == layer { + typed.push(new_val); + } else { + panic!("trying to compute empty merkle entries out of order") + } + return typed[layer]; + } + + pub fn new(ty: MerkleType, hashes: Vec) -> Merkle { if hashes.is_empty() { return Merkle::default(); } + let min_depth = match ty { + MerkleType::Empty => panic!("attempted to fetch empty-layer value from empty merkle"), + MerkleType::Memory => Memory::MEMORY_LAYERS, + MerkleType::Opcode => 2, + MerkleType::ArgumentData => 2, + _ => 0, + }; let mut layers = vec![hashes]; - let mut empty_layers = vec![empty_hash]; while layers.last().unwrap().len() > 1 || layers.len() < min_depth { - let empty_layer = *empty_layers.last().unwrap(); + let empty_layer = Self::get_empty(ty, layers.len() - 1); + let next_empty_layer = Self::get_empty(ty, layers.len()); #[cfg(feature = "native")] let new_layer = layers.last().unwrap().par_chunks(2); @@ -85,25 +126,22 @@ impl Merkle { #[cfg(not(feature = "native"))] let new_layer = layers.last().unwrap().chunks(2); - let new_empty_layer = hash_node(ty, empty_layer, empty_layer); let new_layer = new_layer .map(|chunk| { let left = chunk[0]; let right = chunk.get(1).cloned().unwrap_or(empty_layer); if left == empty_layer && right == empty_layer { - new_empty_layer + next_empty_layer } else { hash_node(ty, left, right) } }) .collect(); - empty_layers.push(new_empty_layer); layers.push(new_layer); } Merkle { ty, layers, - empty_layers, min_depth, } } @@ -146,7 +184,7 @@ impl Merkle { layer .get(counterpart) .cloned() - .unwrap_or_else(|| self.empty_layers[layer_i]), + .unwrap_or_else(|| Self::get_empty(self.ty, layer_i)), ); idx >>= 1; } @@ -158,8 +196,7 @@ impl Merkle { pub fn push_leaf(&mut self, leaf: Bytes32) { let mut leaves = self.layers.swap_remove(0); leaves.push(leaf); - let empty = self.empty_layers[0]; - *self = Self::new_advanced(self.ty, leaves, empty, self.min_depth); + *self = Self::new(self.ty, leaves); } /// Removes the rightmost leaf from the merkle @@ -167,8 +204,7 @@ impl Merkle { pub fn pop_leaf(&mut self) { let mut leaves = self.layers.swap_remove(0); leaves.pop(); - let empty = self.empty_layers[0]; - *self = Self::new_advanced(self.ty, leaves, empty, self.min_depth); + *self = Self::new(self.ty, leaves); } pub fn set(&mut self, mut idx: usize, hash: Bytes32) { @@ -176,7 +212,6 @@ impl Merkle { return; } let mut next_hash = hash; - let empty_layers = &self.empty_layers; let layers_len = self.layers.len(); for (layer_i, layer) in self.layers.iter_mut().enumerate() { layer[idx] = next_hash; @@ -187,7 +222,7 @@ impl Merkle { let counterpart = layer .get(idx ^ 1) .cloned() - .unwrap_or_else(|| empty_layers[layer_i]); + .unwrap_or_else(|| Self::get_empty(self.ty, layer_i)); if idx % 2 == 0 { next_hash = hash_node(self.ty, next_hash, counterpart); } else { diff --git a/arbitrator/prover/src/wavm.rs b/arbitrator/prover/src/wavm.rs index a2e1e1ae6..e949139a2 100644 --- a/arbitrator/prover/src/wavm.rs +++ b/arbitrator/prover/src/wavm.rs @@ -9,8 +9,6 @@ use crate::{ use arbutil::Bytes32; use eyre::{bail, ensure, Result}; use fnv::FnvHashMap as HashMap; -use lazy_static::lazy_static; -use parking_lot::Mutex; use serde::{Deserialize, Serialize}; use std::ops::{Add, AddAssign, Sub, SubAssign}; use wasmparser::{Operator, Type, TypeOrFuncType as BlockType}; @@ -326,10 +324,6 @@ pub fn unpack_cross_module_call(data: u64) -> (u32, u32) { ((data >> 32) as u32, data as u32) } -lazy_static! { - static ref OP_HASHES: Mutex> = Mutex::new(HashMap::default()); -} - impl Instruction { #[must_use] pub fn simple(opcode: Opcode) -> Instruction { From 807622c695585b3b9e1d6612b5bb5adf62f5cf46 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Mon, 24 Jul 2023 14:52:12 -0600 Subject: [PATCH 11/20] prover: add per-module types merkle and use for call-indirect --- arbitrator/prover/src/host.rs | 3 +-- arbitrator/prover/src/machine.rs | 45 ++++++++++++++++---------------- arbitrator/prover/src/merkle.rs | 2 ++ 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/arbitrator/prover/src/host.rs b/arbitrator/prover/src/host.rs index 1802ea609..8296eba96 100644 --- a/arbitrator/prover/src/host.rs +++ b/arbitrator/prover/src/host.rs @@ -358,7 +358,7 @@ pub fn get_impl(module: &str, name: &str) -> Result<(Function, bool)> { }; let debug = module == "console"; - Function::new(&[], append, hostio.ty(), &[]).map(|x| (x, debug)) + Function::new(&[], append, hostio.ty()).map(|x| (x, debug)) } /// Adds internal functions to a module. @@ -458,7 +458,6 @@ lazy_static! { 0, // impls don't use other internals ), ty.clone(), - &[] // impls don't make calls ); func.expect("failed to create bulk memory func") }) diff --git a/arbitrator/prover/src/machine.rs b/arbitrator/prover/src/machine.rs index 8a31a15bd..dde86f23f 100644 --- a/arbitrator/prover/src/machine.rs +++ b/arbitrator/prover/src/machine.rs @@ -47,14 +47,6 @@ use wasmparser::{DataKind, ElementItem, ElementKind, Operator, TableType}; #[cfg(feature = "native")] use rayon::prelude::*; -fn hash_call_indirect_data(table: u32, ty: &FunctionType) -> Bytes32 { - let mut h = Keccak256::new(); - h.update("Call indirect:"); - h.update((table as u64).to_be_bytes()); - h.update(ty.hash()); - h.finalize().into() -} - #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum InboxIdentifier { Sequencer = 0, @@ -119,7 +111,6 @@ impl Function { locals: &[Local], add_body: F, func_ty: FunctionType, - module_types: &[FunctionType], ) -> Result { let mut locals_with_params = func_ty.inputs.clone(); locals_with_params.extend(locals.iter().map(|x| x.value)); @@ -148,15 +139,6 @@ impl Function { add_body(&mut insts)?; insts.push(Instruction::simple(Opcode::Return)); - // Insert missing proving argument data - for inst in insts.iter_mut() { - if inst.opcode == Opcode::CallIndirect { - let (table, ty) = crate::wavm::unpack_call_indirect(inst.argument_data); - let ty = &module_types[usize::try_from(ty).unwrap()]; - inst.proving_argument_data = Some(hash_call_indirect_data(table, ty)); - } - } - Ok(Function::new_from_wavm(insts, func_ty, locals_with_params)) } @@ -309,6 +291,8 @@ struct Module { #[serde(skip)] funcs_merkle: Arc, types: Arc>, + #[serde(skip)] + types_merkle: Arc, internals_offset: u32, names: Arc, host_call_hooks: Arc>>, @@ -423,7 +407,6 @@ impl Module { ) }, func_ty.clone(), - &types, )?); } code.extend(internals); @@ -567,6 +550,10 @@ impl Module { code.iter().map(|f| f.hash()).collect(), )), funcs: Arc::new(code), + types_merkle: Arc::new(Merkle::new( + MerkleType::FunctionType, + types.iter().map(FunctionType::hash).collect(), + )), types: Arc::new(types.to_owned()), internals_offset, names: Arc::new(bin.names.to_owned()), @@ -602,6 +589,7 @@ impl Module { h.update(self.memory.hash()); h.update(self.tables_merkle.root()); h.update(self.funcs_merkle.root()); + h.update(self.types_merkle.root()); h.update(self.internals_offset.to_be_bytes()); h.finalize().into() } @@ -623,6 +611,7 @@ impl Module { data.extend(self.tables_merkle.root()); data.extend(self.funcs_merkle.root()); + data.extend(self.types_merkle.root()); data.extend(self.internals_offset.to_be_bytes()); @@ -1361,7 +1350,6 @@ impl Machine { Ok(()) }, FunctionType::default(), - &entrypoint_types, )?]; let entrypoint = Module { globals: Vec::new(), @@ -1373,6 +1361,10 @@ impl Machine { entrypoint_funcs.iter().map(Function::hash).collect(), )), funcs: Arc::new(entrypoint_funcs), + types_merkle: Arc::new( Merkle::new( + MerkleType::FunctionType, + entrypoint_types.iter().map(FunctionType::hash).collect() + )), types: Arc::new(entrypoint_types), names: Arc::new(entrypoint_names), internals_offset: 0, @@ -1473,6 +1465,10 @@ impl Machine { MerkleType::Function, module.funcs.iter().map(Function::hash).collect(), )); + module.types_merkle = Arc::new(Merkle::new( + MerkleType::FunctionType, + module.types.iter().map(FunctionType::hash).collect() + )) } let mut mach = Machine { status: MachineStatus::Running, @@ -2768,11 +2764,14 @@ impl Machine { Some(Value::I32(i)) => *i, x => fail!("top of stack before call_indirect is {x:?}"), }; - let ty = &module.types[usize::try_from(ty).unwrap()]; - out!((table as u64).to_be_bytes()); - out!(ty.hash()); let table_usize = usize::try_from(table).unwrap(); + let type_usize = usize::try_from(ty).unwrap(); let table = &module.tables[table_usize]; + out!(module.types[type_usize].hash()); + out!(module + .types_merkle + .prove(type_usize) + .expect("failed to prove types merkle")); out!(table .serialize_for_proof() .expect("failed to serialize table")); diff --git a/arbitrator/prover/src/merkle.rs b/arbitrator/prover/src/merkle.rs index cf868d88f..b3597a9ae 100644 --- a/arbitrator/prover/src/merkle.rs +++ b/arbitrator/prover/src/merkle.rs @@ -17,6 +17,7 @@ pub enum MerkleType { Empty, Value, Function, + FunctionType, Opcode, ArgumentData, Memory, @@ -37,6 +38,7 @@ impl MerkleType { MerkleType::Empty => panic!("Attempted to get prefix of empty merkle type"), MerkleType::Value => "Value merkle tree:", MerkleType::Function => "Function merkle tree:", + MerkleType::FunctionType => "Function type merkle tree:", MerkleType::Opcode => "Opcode merkle tree:", MerkleType::ArgumentData => "Argument data merkle tree:", MerkleType::Memory => "Memory merkle tree:", From 45c5c8f54f1a789a9916611e12dc7be4fb427a2b Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Mon, 24 Jul 2023 15:43:26 -0600 Subject: [PATCH 12/20] prover: empty_locals moves to function hash --- arbitrator/prover/src/machine.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/arbitrator/prover/src/machine.rs b/arbitrator/prover/src/machine.rs index dde86f23f..f68f2935c 100644 --- a/arbitrator/prover/src/machine.rs +++ b/arbitrator/prover/src/machine.rs @@ -116,16 +116,10 @@ impl Function { locals_with_params.extend(locals.iter().map(|x| x.value)); let mut insts = Vec::new(); - let empty_local_hashes = locals_with_params - .iter() - .cloned() - .map(Value::default_of_type) - .map(Value::hash) - .collect::>(); insts.push(Instruction { opcode: Opcode::InitFrame, argument_data: 0, - proving_argument_data: Some(Merkle::new(MerkleType::Value, empty_local_hashes).root()), + proving_argument_data: None, }); // Fill in parameters for i in (0..func_ty.inputs.len()).rev() { @@ -165,10 +159,17 @@ impl Function { } fn hash(&self) -> Bytes32 { + let empty_local_hashes = self.ty.inputs + .iter() + .cloned() + .map(Value::default_of_type) + .map(Value::hash) + .collect::>(); let mut h = Keccak256::new(); h.update("Function:"); h.update(self.opcode_merkle.root()); h.update(self.argument_data_merkle.root()); + h.update(Merkle::new(MerkleType::Value, empty_local_hashes).root()); h.finalize().into() } } From 47a3ebc3009c090b6a803a0ac65b5b783d2137db Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Mon, 24 Jul 2023 17:29:58 -0600 Subject: [PATCH 13/20] prover: move funcs emptylocalhash to function --- arbitrator/prover/src/machine.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arbitrator/prover/src/machine.rs b/arbitrator/prover/src/machine.rs index f68f2935c..b5dd1d1df 100644 --- a/arbitrator/prover/src/machine.rs +++ b/arbitrator/prover/src/machine.rs @@ -158,18 +158,22 @@ impl Function { } } - fn hash(&self) -> Bytes32 { + fn empty_locals_hash(&self) -> Bytes32 { let empty_local_hashes = self.ty.inputs .iter() .cloned() .map(Value::default_of_type) .map(Value::hash) .collect::>(); + Merkle::new(MerkleType::Value, empty_local_hashes).root() + } + + fn hash(&self) -> Bytes32 { let mut h = Keccak256::new(); h.update("Function:"); h.update(self.opcode_merkle.root()); h.update(self.argument_data_merkle.root()); - h.update(Merkle::new(MerkleType::Value, empty_local_hashes).root()); + h.update(self.empty_locals_hash()); h.finalize().into() } } @@ -2681,6 +2685,7 @@ impl Machine { .argument_data_merkle .prove(self.pc.inst()) .expect("Failed to prove against argument data merkle")); + out!(func.empty_locals_hash()); out!(module .funcs_merkle .prove(self.pc.func()) From 5d3b76e70505187ae5ead25d352224762ffce556 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Mon, 24 Jul 2023 18:02:55 -0600 Subject: [PATCH 14/20] prover: remove instruction_proving_data --- arbitrator/prover/src/machine.rs | 32 ++++++++++++++++++-------------- arbitrator/prover/src/wavm.rs | 13 ------------- 2 files changed, 18 insertions(+), 27 deletions(-) diff --git a/arbitrator/prover/src/machine.rs b/arbitrator/prover/src/machine.rs index b5dd1d1df..8beb615f4 100644 --- a/arbitrator/prover/src/machine.rs +++ b/arbitrator/prover/src/machine.rs @@ -94,16 +94,20 @@ fn code_to_opcode_hashes(code: &Vec) -> Vec { iter.map(|i| code_to_opcode_hash(code, i * 16)).collect() } -#[cfg(feature = "native")] -fn code_to_argdata_hashes(code: &Vec) -> Vec { - code.par_iter() - .map(|i| i.get_proving_argument_data()) - .collect() +fn code_to_argdata_hash(code: &Vec, opcode_idx: usize) -> Bytes32 { + let mut b = [0u8; 32]; + b[24..].copy_from_slice(code[opcode_idx].argument_data.to_be_bytes().as_slice()); + Bytes32(b) } -#[cfg(not(feature = "native"))] fn code_to_argdata_hashes(code: &Vec) -> Vec { - code.iter().map(|i| i.get_proving_argument_data()).collect() + #[cfg(feature = "native")] + let iter = (0..(code.len())).into_par_iter(); + + #[cfg(not(feature = "native"))] + let iter = (0..(code.len())).into_iter(); + + iter.map(|i| code_to_argdata_hash(code, i)).collect() } impl Function { @@ -119,14 +123,12 @@ impl Function { insts.push(Instruction { opcode: Opcode::InitFrame, argument_data: 0, - proving_argument_data: None, }); // Fill in parameters for i in (0..func_ty.inputs.len()).rev() { insts.push(Instruction { opcode: Opcode::LocalSet, argument_data: i as u64, - proving_argument_data: None, }); } @@ -159,7 +161,9 @@ impl Function { } fn empty_locals_hash(&self) -> Bytes32 { - let empty_local_hashes = self.ty.inputs + let empty_local_hashes = self + .ty + .inputs .iter() .cloned() .map(Value::default_of_type) @@ -1366,9 +1370,9 @@ impl Machine { entrypoint_funcs.iter().map(Function::hash).collect(), )), funcs: Arc::new(entrypoint_funcs), - types_merkle: Arc::new( Merkle::new( + types_merkle: Arc::new(Merkle::new( MerkleType::FunctionType, - entrypoint_types.iter().map(FunctionType::hash).collect() + entrypoint_types.iter().map(FunctionType::hash).collect(), )), types: Arc::new(entrypoint_types), names: Arc::new(entrypoint_names), @@ -1472,7 +1476,7 @@ impl Machine { )); module.types_merkle = Arc::new(Merkle::new( MerkleType::FunctionType, - module.types.iter().map(FunctionType::hash).collect() + module.types.iter().map(FunctionType::hash).collect(), )) } let mut mach = Machine { @@ -2680,7 +2684,7 @@ impl Machine { .opcode_merkle .prove(self.pc.inst() / 16) .expect("Failed to prove against code merkle")); - out!(func.code[self.pc.inst()].get_proving_argument_data()); + out!(code_to_argdata_hash(&func.code, self.pc.inst())); out!(func .argument_data_merkle .prove(self.pc.inst()) diff --git a/arbitrator/prover/src/wavm.rs b/arbitrator/prover/src/wavm.rs index e949139a2..ade3a011e 100644 --- a/arbitrator/prover/src/wavm.rs +++ b/arbitrator/prover/src/wavm.rs @@ -305,7 +305,6 @@ pub type FloatingPointImpls = HashMap; pub struct Instruction { pub opcode: Opcode, pub argument_data: u64, - pub proving_argument_data: Option, } fn pack_call_indirect(table: u32, ty: u32) -> u64 { @@ -330,7 +329,6 @@ impl Instruction { Instruction { opcode, argument_data: 0, - proving_argument_data: None, } } @@ -339,17 +337,6 @@ impl Instruction { Instruction { opcode, argument_data, - proving_argument_data: None, - } - } - - pub fn get_proving_argument_data(self) -> Bytes32 { - if let Some(data) = self.proving_argument_data { - data - } else { - let mut b = [0u8; 32]; - b[24..].copy_from_slice(&self.argument_data.to_be_bytes()); - Bytes32(b) } } } From 6117a20cacfe4116cacb143d5dd6852f3783aa8d Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Mon, 24 Jul 2023 19:14:27 -0600 Subject: [PATCH 15/20] prover: 4 argdata hashes per merkle leaf --- arbitrator/prover/src/machine.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/arbitrator/prover/src/machine.rs b/arbitrator/prover/src/machine.rs index 8beb615f4..251722918 100644 --- a/arbitrator/prover/src/machine.rs +++ b/arbitrator/prover/src/machine.rs @@ -95,19 +95,25 @@ fn code_to_opcode_hashes(code: &Vec) -> Vec { } fn code_to_argdata_hash(code: &Vec, opcode_idx: usize) -> Bytes32 { + let seg = opcode_idx / 4; + let seg_start = seg * 4; + let seg_end = min(seg_start + 4, code.len()); let mut b = [0u8; 32]; - b[24..].copy_from_slice(code[opcode_idx].argument_data.to_be_bytes().as_slice()); + for i in 0..(seg_end - seg_start) { + b[i * 8..i * 8 + 8] + .copy_from_slice(code[seg_start + i].argument_data.to_be_bytes().as_slice()) + } Bytes32(b) } fn code_to_argdata_hashes(code: &Vec) -> Vec { #[cfg(feature = "native")] - let iter = (0..(code.len())).into_par_iter(); + let iter = (0..(code.len() + 3) / 4).into_par_iter(); #[cfg(not(feature = "native"))] - let iter = (0..(code.len())).into_iter(); + let iter = (0..(code.len() + 3) / 4).into_iter(); - iter.map(|i| code_to_argdata_hash(code, i)).collect() + iter.map(|i| code_to_argdata_hash(code, i * 4)).collect() } impl Function { @@ -2687,7 +2693,7 @@ impl Machine { out!(code_to_argdata_hash(&func.code, self.pc.inst())); out!(func .argument_data_merkle - .prove(self.pc.inst()) + .prove(self.pc.inst() / 4) .expect("Failed to prove against argument data merkle")); out!(func.empty_locals_hash()); out!(module From a0cd23691b602af8fe917c09a6e1040ac05fe3d7 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Mon, 24 Jul 2023 19:15:05 -0600 Subject: [PATCH 16/20] prover test: update link hashes --- arbitrator/prover/test-cases/dynamic.wat | 4 +++- arbitrator/prover/test-cases/link.wat | 28 +++++++++++++----------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/arbitrator/prover/test-cases/dynamic.wat b/arbitrator/prover/test-cases/dynamic.wat index 4a943e7b2..4e6342c8e 100644 --- a/arbitrator/prover/test-cases/dynamic.wat +++ b/arbitrator/prover/test-cases/dynamic.wat @@ -7,7 +7,9 @@ (import "hostio" "program_ink_status" (func $ink_status (param i32 i32) (result i32))) (import "hostio" "program_call_main" (func $user_func (param i32 i32 i32) (result i32))) (data (i32.const 0x0) - "\0a\3e\95\a0\01\bf\38\a7\f9\c0\4b\74\53\06\fc\a9\be\6b\4a\84\65\7e\04\b1\43\12\d9\e3\fd\5b\4d\ab") (func $start (local $user i32) (local $internals i32) + "\ae\01\43\c4\fa\31\c1\30\eb\d6\16\53\7b\a9\e4\0d\0c\52\ab\4b\2a\4c\fe\62\06\5e\e8\33\c8\f4\d4\d4") + + (func $start (local $user i32) (local $internals i32) ;; link in user.wat i32.const 0 call $link diff --git a/arbitrator/prover/test-cases/link.wat b/arbitrator/prover/test-cases/link.wat index 74cb5e7c0..d0d662139 100644 --- a/arbitrator/prover/test-cases/link.wat +++ b/arbitrator/prover/test-cases/link.wat @@ -5,31 +5,33 @@ (import "hostio" "wavm_link_module" (func $link (param i32) (result i32))) (import "hostio" "wavm_unlink_module" (func $unlink (param) (result))) (data (i32.const 0x000) - "\3e\2b\a8\7c\04\f9\c9\36\57\b8\a8\20\eb\b4\74\13\11\b2\36\48\8e\01\36\50\b3\59\d4\50\b7\15\86\a1") + "\2a\94\85\60\92\8c\fb\08\cf\0e\e0\c4\9c\02\5b\0f\03\b1\3d\b9\ac\83\f7\f8\3d\9a\8c\9b\c3\01\ec\24") (data (i32.const 0x020) - "\cd\ef\2c\33\e2\88\88\0f\95\e5\56\f6\f2\09\eb\c1\12\6c\5e\d3\3e\f1\3a\ee\b1\de\6a\6b\1d\72\55\0a") + "\40\49\8b\d3\0d\81\e6\61\ef\f7\99\1e\6f\87\33\24\d5\48\4f\8e\c4\28\9b\ff\44\34\3a\62\15\5f\65\f3") (data (i32.const 0x040) - "\e9\a4\72\b9\ac\2c\39\c3\bd\07\ba\2a\07\27\01\37\1f\0d\4a\4f\32\37\b4\9b\76\b2\2f\82\75\c5\e5\db") + "\ba\f4\d6\92\3a\dc\6d\01\b7\a7\f7\8b\bc\26\4e\b6\73\e7\1c\0b\6a\1b\e9\43\cf\aa\78\51\7d\f0\6e\e2") (data (i32.const 0x060) - "\0a\3e\95\a0\01\bf\38\a7\f9\c0\4b\74\53\06\fc\a9\be\6b\4a\84\65\7e\04\b1\43\12\d9\e3\fd\5b\4d\ab") + "\8c\bd\e0\cc\72\d6\c7\16\9b\4a\a0\16\dc\10\62\b9\01\20\6f\57\ea\f9\d2\e9\65\41\ab\f6\99\9c\fe\ab") (data (i32.const 0x080) - "\17\38\60\10\80\4d\6b\4e\04\51\1f\af\b8\5f\73\a3\97\70\6f\e4\ce\0e\a4\c2\1a\e0\b5\96\32\d2\e7\0b") + "\8e\ef\66\f7\31\69\77\15\a5\d1\37\e8\5f\1b\40\b2\d9\cc\87\12\bf\cd\33\e9\17\0e\29\16\3b\ae\5a\89") (data (i32.const 0x0a0) - "\04\b3\01\ae\24\d9\10\12\fe\be\a3\2a\0f\ee\8c\20\6a\bc\af\d4\40\c0\70\62\d9\7f\40\ae\fb\f1\41\cd") + "\29\87\e2\17\e8\2c\fb\3a\02\a1\92\ce\e9\43\a5\da\91\93\af\80\80\7b\5f\d3\cf\e8\cb\ee\64\bf\84\1d") (data (i32.const 0x0c0) - "\8f\0a\38\39\b9\f2\d7\ba\3f\24\53\59\02\c6\f6\4e\c5\f1\5c\5d\cf\16\8f\9b\6d\7e\2b\ec\cc\c8\90\c2") + "\3e\58\e3\ac\66\62\b8\93\eb\6e\da\57\3a\44\bf\c7\05\4e\7b\0d\32\90\3e\38\c5\88\d2\58\0c\ad\fe\34") (data (i32.const 0x0e0) - "\7f\73\86\67\a0\b5\c3\85\43\a4\4d\05\ab\9e\1d\9b\68\c5\c8\cc\03\f4\fa\5b\98\64\27\6e\e6\26\5e\c0") + "\2d\a1\42\a0\b6\8c\4b\f4\55\61\82\27\15\15\d5\16\20\b3\37\10\f2\33\c3\01\1f\36\ea\56\0f\b5\f4\ce") (data (i32.const 0x100) - "\4b\c3\5f\e7\d7\63\0e\13\29\e4\a7\c0\7b\cb\5c\b4\44\d8\d7\b0\53\52\d4\d3\64\90\7f\35\d3\a8\25\53") + "\a2\2b\96\13\c4\76\97\af\01\19\a6\a3\3c\75\6a\52\bb\74\99\e9\55\7a\dc\2c\d6\66\e5\f0\ac\a2\c1\84") (data (i32.const 0x120) - "\6c\bc\c4\8f\38\8c\9f\f3\e5\74\67\35\b4\9f\63\c9\f2\8f\71\b1\12\d7\60\3d\d9\4d\5f\0c\ce\ca\3f\e3") + "\39\34\5a\b8\c7\cd\6a\cc\d3\45\00\a5\72\67\02\e2\8d\7f\22\f8\81\8f\50\60\d0\32\40\70\74\31\6a\72") (data (i32.const 0x140) - "\dd\86\00\e8\70\cb\a5\57\92\7f\00\d3\ab\57\8a\a3\43\c6\f1\d2\f3\47\0a\12\33\96\69\0b\44\4d\87\8d") + "\a4\11\ca\e6\37\2b\70\48\db\70\7f\d2\0e\f1\c6\73\dd\21\f3\8d\91\14\f7\44\29\93\38\d1\43\b5\8b\e7") (data (i32.const 0x160) - "\a8\65\a9\40\f3\d1\3d\dc\a4\25\e8\ce\d2\e6\44\5e\53\c3\47\3c\d0\c5\2d\8d\f8\71\0b\39\d6\b8\fb\ae") + "\ae\01\43\c4\fa\31\c1\30\eb\d6\16\53\7b\a9\e4\0d\0c\52\ab\4b\2a\4c\fe\62\06\5e\e8\33\c8\f4\d4\d4") (data (i32.const 0x180) - "\bf\3c\c7\d8\b7\5e\dc\e0\93\3d\d5\fb\b6\3e\ec\39\c0\88\1e\fd\91\d1\ea\45\da\e4\c0\78\af\74\4b\cc") (func $start (local $counter i32) + "\b0\11\13\06\77\24\48\82\59\c7\12\ba\43\bf\43\02\89\c5\cd\c9\3a\c5\ba\7a\92\c8\88\a0\5a\49\4e\9e") + + (func $start (local $counter i32) ;; add modules (loop $top From dc3fbafa2c49856acf9912272012dcfbfc7a5272 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Mon, 24 Jul 2023 19:16:49 -0600 Subject: [PATCH 17/20] contracts: upgrade OSP to support 4 argdata per merkle leaf --- contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts b/contracts index 601fa9692..79cafd280 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 601fa9692677df7ee1968d6bfae5941958cdfa3a +Subproject commit 79cafd28024389653692ab29f7b1f231a07623c4 From 0921586ef629caa6bd61cf34684f953f2928ea73 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Mon, 24 Jul 2023 19:32:54 -0600 Subject: [PATCH 18/20] prover: remove unused import --- arbitrator/prover/src/wavm.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/arbitrator/prover/src/wavm.rs b/arbitrator/prover/src/wavm.rs index ade3a011e..c12f9d171 100644 --- a/arbitrator/prover/src/wavm.rs +++ b/arbitrator/prover/src/wavm.rs @@ -6,7 +6,6 @@ use crate::{ host::InternalFunc, value::{ArbValueType, FunctionType, IntegerValType}, }; -use arbutil::Bytes32; use eyre::{bail, ensure, Result}; use fnv::FnvHashMap as HashMap; use serde::{Deserialize, Serialize}; From 9272577392a9bcf6dba8112dae55921c34f5f5de Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Tue, 25 Jul 2023 09:41:34 -0600 Subject: [PATCH 19/20] prover: store and fix empty_locals_hash --- arbitrator/prover/src/machine.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/arbitrator/prover/src/machine.rs b/arbitrator/prover/src/machine.rs index 251722918..5f9f87a45 100644 --- a/arbitrator/prover/src/machine.rs +++ b/arbitrator/prover/src/machine.rs @@ -70,6 +70,8 @@ pub struct Function { #[serde(skip)] argument_data_merkle: Merkle, local_types: Vec, + #[serde(skip)] + empty_locals_hash: Bytes32, } fn code_to_opcode_hash(code: &Vec, opcode_idx: usize) -> Bytes32 { @@ -159,6 +161,7 @@ impl Function { Function { code, + empty_locals_hash: Self::calc_empty_locals_hash(&local_types), ty, opcode_merkle: Merkle::new(MerkleType::Opcode, opcode_hashes), argument_data_merkle: Merkle::new(MerkleType::ArgumentData, argument_data_hashes), @@ -166,10 +169,8 @@ impl Function { } } - fn empty_locals_hash(&self) -> Bytes32 { - let empty_local_hashes = self - .ty - .inputs + fn calc_empty_locals_hash(locals_with_params: &Vec) -> Bytes32 { + let empty_local_hashes = locals_with_params .iter() .cloned() .map(Value::default_of_type) @@ -183,7 +184,7 @@ impl Function { h.update("Function:"); h.update(self.opcode_merkle.root()); h.update(self.argument_data_merkle.root()); - h.update(self.empty_locals_hash()); + h.update(self.empty_locals_hash); h.finalize().into() } } @@ -1475,6 +1476,7 @@ impl Machine { func.opcode_merkle = Merkle::new(MerkleType::Opcode, opcode_hashes); func.argument_data_merkle = Merkle::new(MerkleType::ArgumentData, argdata_hashes); + func.empty_locals_hash = Function::calc_empty_locals_hash(&func.local_types) } module.funcs_merkle = Arc::new(Merkle::new( MerkleType::Function, @@ -2695,7 +2697,7 @@ impl Machine { .argument_data_merkle .prove(self.pc.inst() / 4) .expect("Failed to prove against argument data merkle")); - out!(func.empty_locals_hash()); + out!(func.empty_locals_hash); out!(module .funcs_merkle .prove(self.pc.func()) From a8ae255dd7207d49a3b95dce51baac6d3b47a9d8 Mon Sep 17 00:00:00 2001 From: Tsahi Zidenberg Date: Tue, 25 Jul 2023 09:42:22 -0600 Subject: [PATCH 20/20] prover: update linked hashes in testcases --- arbitrator/prover/test-cases/dynamic.wat | 2 +- arbitrator/prover/test-cases/link.wat | 26 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/arbitrator/prover/test-cases/dynamic.wat b/arbitrator/prover/test-cases/dynamic.wat index 4e6342c8e..0cdcc2b27 100644 --- a/arbitrator/prover/test-cases/dynamic.wat +++ b/arbitrator/prover/test-cases/dynamic.wat @@ -7,7 +7,7 @@ (import "hostio" "program_ink_status" (func $ink_status (param i32 i32) (result i32))) (import "hostio" "program_call_main" (func $user_func (param i32 i32 i32) (result i32))) (data (i32.const 0x0) - "\ae\01\43\c4\fa\31\c1\30\eb\d6\16\53\7b\a9\e4\0d\0c\52\ab\4b\2a\4c\fe\62\06\5e\e8\33\c8\f4\d4\d4") + "\ef\75\83\c3\de\bf\e1\41\0a\3d\24\81\1c\a3\b7\4d\a5\18\3b\46\63\f2\5d\c9\14\d3\70\aa\b8\b3\21\56") (func $start (local $user i32) (local $internals i32) ;; link in user.wat diff --git a/arbitrator/prover/test-cases/link.wat b/arbitrator/prover/test-cases/link.wat index d0d662139..d9a60f97f 100644 --- a/arbitrator/prover/test-cases/link.wat +++ b/arbitrator/prover/test-cases/link.wat @@ -5,31 +5,31 @@ (import "hostio" "wavm_link_module" (func $link (param i32) (result i32))) (import "hostio" "wavm_unlink_module" (func $unlink (param) (result))) (data (i32.const 0x000) - "\2a\94\85\60\92\8c\fb\08\cf\0e\e0\c4\9c\02\5b\0f\03\b1\3d\b9\ac\83\f7\f8\3d\9a\8c\9b\c3\01\ec\24") + "\7a\cd\ed\ed\a3\18\fa\b7\4b\21\35\f5\08\8f\37\02\f3\96\fa\70\79\5d\c0\c9\55\92\8b\42\77\58\09\95") (data (i32.const 0x020) - "\40\49\8b\d3\0d\81\e6\61\ef\f7\99\1e\6f\87\33\24\d5\48\4f\8e\c4\28\9b\ff\44\34\3a\62\15\5f\65\f3") + "\91\3a\58\fe\e6\8f\2f\3f\a4\d7\a6\60\7e\f8\06\8a\db\de\37\31\e8\66\99\9a\f5\2b\00\39\b0\df\f0\29") (data (i32.const 0x040) - "\ba\f4\d6\92\3a\dc\6d\01\b7\a7\f7\8b\bc\26\4e\b6\73\e7\1c\0b\6a\1b\e9\43\cf\aa\78\51\7d\f0\6e\e2") + "\94\63\42\17\b2\0a\c3\94\ce\e1\0c\50\74\7b\fb\2c\22\3f\ca\97\3e\18\30\90\df\9b\36\37\40\fa\57\df") (data (i32.const 0x060) - "\8c\bd\e0\cc\72\d6\c7\16\9b\4a\a0\16\dc\10\62\b9\01\20\6f\57\ea\f9\d2\e9\65\41\ab\f6\99\9c\fe\ab") + "\f1\37\72\b3\30\37\09\8e\b2\d5\e5\49\20\57\ea\17\1d\a6\1c\85\58\82\e1\96\c7\80\a2\e9\26\e7\fe\23") (data (i32.const 0x080) - "\8e\ef\66\f7\31\69\77\15\a5\d1\37\e8\5f\1b\40\b2\d9\cc\87\12\bf\cd\33\e9\17\0e\29\16\3b\ae\5a\89") + "\03\a1\b5\e0\fa\39\f0\89\12\a4\f7\af\fe\af\5b\21\e1\61\1f\4b\f7\fb\51\c5\e7\07\6b\12\cd\b6\fd\ad") (data (i32.const 0x0a0) - "\29\87\e2\17\e8\2c\fb\3a\02\a1\92\ce\e9\43\a5\da\91\93\af\80\80\7b\5f\d3\cf\e8\cb\ee\64\bf\84\1d") + "\b0\53\f4\29\a3\9d\e0\2d\d4\7f\c9\d4\fa\0d\e8\ed\ff\90\c2\c2\e8\f4\9d\41\3d\04\67\2a\75\2d\ff\d2") (data (i32.const 0x0c0) - "\3e\58\e3\ac\66\62\b8\93\eb\6e\da\57\3a\44\bf\c7\05\4e\7b\0d\32\90\3e\38\c5\88\d2\58\0c\ad\fe\34") + "\c3\4c\a0\04\4e\cb\62\af\fb\15\f9\da\08\22\91\28\be\97\fa\04\f4\da\a9\1b\07\de\6d\79\f1\af\27\30") (data (i32.const 0x0e0) - "\2d\a1\42\a0\b6\8c\4b\f4\55\61\82\27\15\15\d5\16\20\b3\37\10\f2\33\c3\01\1f\36\ea\56\0f\b5\f4\ce") + "\e0\44\10\9b\5d\95\19\8b\e0\5c\20\fe\31\ce\f0\cf\b7\c7\6a\9d\a9\88\dd\4d\a9\fd\78\ff\5f\69\dd\82") (data (i32.const 0x100) - "\a2\2b\96\13\c4\76\97\af\01\19\a6\a3\3c\75\6a\52\bb\74\99\e9\55\7a\dc\2c\d6\66\e5\f0\ac\a2\c1\84") + "\ef\75\83\c3\de\bf\e1\41\0a\3d\24\81\1c\a3\b7\4d\a5\18\3b\46\63\f2\5d\c9\14\d3\70\aa\b8\b3\21\56") (data (i32.const 0x120) - "\39\34\5a\b8\c7\cd\6a\cc\d3\45\00\a5\72\67\02\e2\8d\7f\22\f8\81\8f\50\60\d0\32\40\70\74\31\6a\72") + "\c9\a6\64\85\89\33\76\a1\8f\17\51\9a\2d\74\b1\9b\89\16\0d\ea\87\3b\ed\f4\62\b7\e5\1b\aa\13\02\8f") (data (i32.const 0x140) - "\a4\11\ca\e6\37\2b\70\48\db\70\7f\d2\0e\f1\c6\73\dd\21\f3\8d\91\14\f7\44\29\93\38\d1\43\b5\8b\e7") + "\e2\b4\0f\72\1d\71\60\c7\5b\37\ce\89\7e\de\e1\ab\08\ed\27\d0\06\0e\55\a3\9c\44\e3\4b\3c\b9\54\86") (data (i32.const 0x160) - "\ae\01\43\c4\fa\31\c1\30\eb\d6\16\53\7b\a9\e4\0d\0c\52\ab\4b\2a\4c\fe\62\06\5e\e8\33\c8\f4\d4\d4") + "\fc\39\b7\9f\6a\2b\66\33\8f\2c\a5\9b\33\67\a7\f4\45\5e\0b\34\49\6d\1a\6c\a6\c1\7e\9a\7e\91\27\d7") (data (i32.const 0x180) - "\b0\11\13\06\77\24\48\82\59\c7\12\ba\43\bf\43\02\89\c5\cd\c9\3a\c5\ba\7a\92\c8\88\a0\5a\49\4e\9e") + "\16\c7\a1\3d\ad\27\8f\a9\11\7c\6e\0c\a1\4c\68\ce\46\c6\c0\e2\cf\97\45\88\53\08\22\17\33\0b\8c\fb") (func $start (local $counter i32)