diff --git a/crates/cli/src/config.rs b/crates/cli/src/config.rs index 27fcaf4c4..0aa44b704 100644 --- a/crates/cli/src/config.rs +++ b/crates/cli/src/config.rs @@ -32,7 +32,6 @@ use specs::TraceBackend; use crate::args::HostMode; use crate::names::name_of_circuit_data; -use crate::names::name_of_etable_slice; use crate::names::name_of_frame_table_slice; use crate::names::name_of_instance; use crate::names::name_of_loadinfo; @@ -303,11 +302,7 @@ impl Config { style("[5/8]").bold().dim(), dir ); - tables.write( - &dir, - |slice| name_of_etable_slice(&self.name, slice), - |slice| name_of_frame_table_slice(&self.name, slice), - ); + tables.write(&dir, |slice| name_of_frame_table_slice(&self.name, slice)); } println!("{} Build circuit(s)...", style("[6/8]").bold().dim(),); diff --git a/crates/specs/src/etable.rs b/crates/specs/src/etable.rs index 6b2c14d11..a7d30159f 100644 --- a/crates/specs/src/etable.rs +++ b/crates/specs/src/etable.rs @@ -9,7 +9,7 @@ use crate::itable::InstructionTable; use crate::itable::InstructionTableEntry; use crate::step::StepInfo; -const JSON: bool = false; +const JSON: bool = true; #[derive(Clone, Debug, Serialize, Deserialize)] pub struct EventTableEntry { diff --git a/crates/specs/src/external_host_call_table/mod.rs b/crates/specs/src/external_host_call_table/mod.rs index 3e4b55d74..7b7fe6c70 100644 --- a/crates/specs/src/external_host_call_table/mod.rs +++ b/crates/specs/src/external_host_call_table/mod.rs @@ -54,7 +54,7 @@ impl Serialize for ExternalHostCallEntry { } } -#[derive(Serialize)] +#[derive(Default, Serialize)] pub struct ExternalHostCallTable(pub(crate) Vec); impl ExternalHostCallTable { @@ -65,4 +65,8 @@ impl ExternalHostCallTable { pub fn entries(&self) -> &Vec { &self.0 } + + pub fn push(&mut self, entry: ExternalHostCallEntry) { + self.0.push(entry); + } } diff --git a/crates/specs/src/external_host_call_table/table.rs b/crates/specs/src/external_host_call_table/table.rs index c1961eac5..dcb1d5980 100644 --- a/crates/specs/src/external_host_call_table/table.rs +++ b/crates/specs/src/external_host_call_table/table.rs @@ -1,26 +1,17 @@ use super::ExternalHostCallEntry; -use super::ExternalHostCallTable; -use crate::etable::EventTable; use crate::step::StepInfo; -impl EventTable { - pub fn filter_external_host_call_table(&self) -> ExternalHostCallTable { - let entries = self - .entries() - .iter() - .filter_map(|entry| { - if let StepInfo::ExternalHostCall { op, value, sig, .. } = &entry.step_info { - Some(ExternalHostCallEntry { - op: *op, - value: value.unwrap(), - sig: *sig, - }) - } else { - None - } - }) - .collect(); +impl TryFrom<&StepInfo> for ExternalHostCallEntry { + type Error = (); - ExternalHostCallTable(entries) + fn try_from(value: &StepInfo) -> Result { + match value { + StepInfo::ExternalHostCall { op, value, sig, .. } => Ok(ExternalHostCallEntry { + op: *op, + value: value.unwrap(), + sig: *sig, + }), + _ => Err(()), + } } } diff --git a/crates/specs/src/lib.rs b/crates/specs/src/lib.rs index 0314c4b5c..1755e4474 100644 --- a/crates/specs/src/lib.rs +++ b/crates/specs/src/lib.rs @@ -71,6 +71,9 @@ pub struct CompilationTable { pub struct ExecutionTable { pub etable: Vec>, pub frame_table: Vec>, + pub external_host_call_table: ExternalHostCallTable, + pub context_input_table: Vec, + pub context_output_table: Vec, } pub struct Tables { @@ -79,12 +82,7 @@ pub struct Tables { } impl Tables { - pub fn write( - &self, - dir: &Path, - name_of_etable_slice: impl Fn(usize) -> String, - name_of_frame_table_slice: impl Fn(usize) -> String, - ) { + pub fn write(&self, dir: &Path, name_of_frame_table_slice: impl Fn(usize) -> String) { fn write_file(folder: &Path, filename: &str, buf: &String) { let folder = folder.join(filename); let mut fd = File::create(folder.as_path()).unwrap(); @@ -92,26 +90,6 @@ impl Tables { fd.write_all(buf.as_bytes()).unwrap(); } - let mut external_host_call_table = vec![]; - self.execution_tables - .etable - .iter() - .enumerate() - .for_each(|(slice, e)| match e { - TableBackend::Memory(etable) => { - external_host_call_table.extend(etable.filter_external_host_call_table().0); - - let path = dir.join(name_of_etable_slice(slice)); - - etable.write(&path).unwrap(); - } - TableBackend::Json(path) => { - let etable = EventTable::read(path).unwrap(); - external_host_call_table.extend(etable.filter_external_host_call_table().0); - } - }); - let external_host_call_table = ExternalHostCallTable::new(external_host_call_table); - write_file( dir, "itable.json", @@ -133,7 +111,7 @@ impl Tables { write_file( dir, "external_host_table.json", - &serde_json::to_string_pretty(&external_host_call_table).unwrap(), + &serde_json::to_string_pretty(&self.execution_tables.external_host_call_table).unwrap(), ); } } diff --git a/crates/specs/src/slice.rs b/crates/specs/src/slice.rs index 704a4d37a..219560088 100644 --- a/crates/specs/src/slice.rs +++ b/crates/specs/src/slice.rs @@ -11,6 +11,7 @@ use crate::brtable::ElemTable; use crate::configure_table::ConfigureTable; use crate::etable::EventTable; use crate::etable::EventTableEntry; +use crate::external_host_call_table::ExternalHostCallTable; use crate::imtable::InitMemoryTable; use crate::itable::InstructionTable; use crate::jtable::CalledFrameTable; @@ -71,6 +72,10 @@ pub struct Slice { pub initialization_state: Arc>, pub post_initialization_state: Arc>, + pub external_host_call_table: Arc, + pub context_input_table: Arc>, + pub context_output_table: Arc>, + pub is_last_slice: bool, } @@ -99,6 +104,10 @@ impl Slice { initialization_state: compilation_table.initialization_state.clone(), post_initialization_state: compilation_table.initialization_state.clone(), + external_host_call_table: ExternalHostCallTable::default().into(), + context_input_table: Arc::new(Vec::new()), + context_output_table: Arc::new(Vec::new()), + is_last_slice, } } diff --git a/crates/zkwasm/src/circuits/zkwasm_circuit/mod.rs b/crates/zkwasm/src/circuits/zkwasm_circuit/mod.rs index 2fc96a627..ea9018989 100644 --- a/crates/zkwasm/src/circuits/zkwasm_circuit/mod.rs +++ b/crates/zkwasm/src/circuits/zkwasm_circuit/mod.rs @@ -16,6 +16,7 @@ use halo2_proofs::plonk::Fixed; use log::debug; use log::info; use specs::etable::EventTable; +use specs::external_host_call_table::ExternalHostCallTable; use specs::jtable::CalledFrameTable; use specs::jtable::INHERITED_FRAME_TABLE_ENTRIES; use specs::slice::FrameTableSlice; @@ -45,7 +46,6 @@ use crate::circuits::utils::table_entry::EventTableWithMemoryInfo; use crate::circuits::utils::table_entry::MemoryWritingTable; use crate::exec_with_profile; use crate::foreign::context::circuits::assign::ContextContHelperTableChip; -use crate::foreign::context::circuits::assign::ExtractContextFromTrace; use crate::foreign::context::circuits::ContextContHelperTableConfig; use crate::foreign::context::circuits::CONTEXT_FOREIGN_TABLE_KEY; use crate::foreign::foreign_table_enable_lines; @@ -135,6 +135,10 @@ macro_rules! impl_zkwasm_circuit { initialization_state: self.slice.initialization_state.clone(), post_initialization_state: self.slice.initialization_state.clone(), + external_host_call_table: ExternalHostCallTable::default().into(), + context_input_table: Arc::new(Vec::new()), + context_output_table: Arc::new(Vec::new()), + is_last_slice: self.slice.is_last_slice, }, ) @@ -392,10 +396,7 @@ macro_rules! impl_zkwasm_circuit { exec_with_profile!( || "Assign external host call table", external_host_call_chip - .assign( - _layouter, - &self.slice.etable.filter_external_host_call_table(), - ) + .assign(_layouter, &self.slice.external_host_call_table,) .unwrap() ); }); @@ -407,8 +408,8 @@ macro_rules! impl_zkwasm_circuit { context_chip .assign( _layouter, - &self.slice.etable.get_context_inputs(), - &self.slice.etable.get_context_outputs() + &self.slice.context_input_table, + &self.slice.context_output_table ) .unwrap() ); diff --git a/crates/zkwasm/src/foreign/context/mod.rs b/crates/zkwasm/src/foreign/context/mod.rs index 6c590b821..c3703e96e 100644 --- a/crates/zkwasm/src/foreign/context/mod.rs +++ b/crates/zkwasm/src/foreign/context/mod.rs @@ -2,6 +2,9 @@ use std::fs::File; use std::io; use std::io::Write; +use specs::host_function::HostPlugin; +use specs::step::StepInfo; + pub mod circuits; pub mod etable_op_configure; pub mod runtime; @@ -11,9 +14,48 @@ enum Op { WriteContext = 1, } -#[derive(Clone, Default)] +#[derive(Default)] +pub struct ContextInput(pub Vec); + +#[derive(Default)] pub struct ContextOutput(pub Vec); +pub fn try_get_context_input_from_step_info(step_info: &StepInfo) -> Option { + match step_info { + StepInfo::CallHost { + plugin: HostPlugin::Context, + op_index_in_plugin, + ret_val, + .. + } => { + if *op_index_in_plugin == Op::ReadContext as usize { + Some(ret_val.unwrap()) + } else { + None + } + } + _ => None, + } +} + +pub fn try_get_context_output_from_step_info(step_info: &StepInfo) -> Option { + match step_info { + StepInfo::CallHost { + plugin: HostPlugin::Context, + op_index_in_plugin, + args, + .. + } => { + if *op_index_in_plugin == Op::WriteContext as usize { + Some(args[0]) + } else { + None + } + } + _ => None, + } +} + impl ContextOutput { pub fn write(&self, fd: &mut File) -> io::Result<()> { fd.write_all("0x".as_bytes())?; diff --git a/crates/zkwasm/src/loader/slice.rs b/crates/zkwasm/src/loader/slice.rs index 027cfe77e..3105d26c7 100644 --- a/crates/zkwasm/src/loader/slice.rs +++ b/crates/zkwasm/src/loader/slice.rs @@ -3,6 +3,7 @@ use specs::brtable::BrTable; use specs::brtable::ElemTable; use specs::configure_table::ConfigureTable; use specs::etable::EventTable; +use specs::external_host_call_table::ExternalHostCallTable; use specs::imtable::InitMemoryTable; use specs::itable::InstructionTable; use specs::jtable::CalledFrameTable; @@ -38,6 +39,10 @@ pub struct Slices { initialization_state: Arc>, etables: VecDeque>, + external_host_call_table: Arc, + context_input_table: Arc>, + context_output_table: Arc>, + _marker: std::marker::PhantomData, } @@ -75,6 +80,9 @@ impl Slices { initialization_state: tables.compilation_tables.initialization_state, etables: tables.execution_tables.etable.into(), + external_host_call_table: tables.execution_tables.external_host_call_table.into(), + context_input_table: tables.execution_tables.context_input_table.into(), + context_output_table: tables.execution_tables.context_output_table.into(), _marker: std::marker::PhantomData, }) @@ -130,6 +138,10 @@ impl Slices { post_initialization_state: self.initialization_state.clone(), etable: Arc::new(EventTable::new(vec![])), + external_host_call_table: self.external_host_call_table.clone(), + context_input_table: self.context_input_table.clone(), + context_output_table: self.context_output_table.clone(), + is_last_slice: false, }; @@ -210,6 +222,10 @@ impl Iterator for Slices { post_initialization_state: post_initialization_state.clone(), etable: Arc::new(etable), + external_host_call_table: self.external_host_call_table.clone(), + context_input_table: self.context_input_table.clone(), + context_output_table: self.context_output_table.clone(), + is_last_slice: self.etables.is_empty(), }; diff --git a/crates/zkwasm/src/runtime/monitor/plugins/table/mod.rs b/crates/zkwasm/src/runtime/monitor/plugins/table/mod.rs index c374f79b8..d1e0bf0e6 100644 --- a/crates/zkwasm/src/runtime/monitor/plugins/table/mod.rs +++ b/crates/zkwasm/src/runtime/monitor/plugins/table/mod.rs @@ -6,6 +6,8 @@ use parity_wasm::elements::External; use specs::brtable::ElemEntry; use specs::brtable::ElemTable; use specs::configure_table::ConfigureTable; +use specs::external_host_call_table::ExternalHostCallEntry; +use specs::external_host_call_table::ExternalHostCallTable; use specs::host_function::HostFunctionDesc; use specs::host_function::HostPlugin; use specs::imtable::InitMemoryTable; @@ -41,6 +43,8 @@ use wasmi::Trap; use wasmi::DEFAULT_VALUE_STACK_LIMIT; use crate::circuits::compute_slice_capability; +use crate::foreign::context::try_get_context_input_from_step_info; +use crate::foreign::context::try_get_context_output_from_step_info; use self::etable::ETable; use self::frame_table::FrameTable; @@ -75,8 +79,11 @@ pub struct TablePlugin { etable: ETable, frame_table: FrameTable, - last_jump_eid: Vec, + external_host_call_table: ExternalHostCallTable, + context_input_table: Vec, + context_output_table: Vec, + last_jump_eid: Vec, module_ref: Option, unresolved_event: Option, } @@ -109,6 +116,9 @@ impl TablePlugin { last_jump_eid: vec![], etable: ETable::new(capacity, trace_backend.clone()), frame_table: FrameTable::new(trace_backend), + external_host_call_table: ExternalHostCallTable::default(), + context_input_table: vec![], + context_output_table: vec![], module_ref: None, unresolved_event: None, @@ -154,6 +164,9 @@ impl TablePlugin { execution_tables: ExecutionTable { etable: self.etable.finalized(), frame_table: self.frame_table.finalized(), + external_host_call_table: self.external_host_call_table, + context_input_table: self.context_input_table, + context_output_table: self.context_output_table, }, } } @@ -687,5 +700,13 @@ impl Monitor for TablePlugin { _ => unreachable!(), } } + + let fixed_step_info = &self.etable.entries().last().unwrap().step_info; + try_get_context_input_from_step_info(fixed_step_info) + .map(|v| self.context_input_table.push(v)); + try_get_context_output_from_step_info(fixed_step_info) + .map(|v| self.context_output_table.push(v)); + let _ = ExternalHostCallEntry::try_from(fixed_step_info) + .map(|e| self.external_host_call_table.push(e)); } }