diff --git a/src/kernel_sdk/CHANGES.md b/src/kernel_sdk/CHANGES.md index e75d30f0a736628a8e5f40cb064aacaa97f9f3a8..b59bc990de1b3a9f2e26b65bd79d5ea1dc0d577f 100644 --- a/src/kernel_sdk/CHANGES.md +++ b/src/kernel_sdk/CHANGES.md @@ -23,6 +23,7 @@ of `OutboxMessageTransaction` with potentially different parameter types. - Add `--keep-going` option to native cli, to control whether the kernel should exit once the inbox has been drained. - Bump `tezos_crypto_rs`/`tezos_data_encoding` to `0.6.0` release. +- Implement the generic `reveal` host function in the `MockHost`, this allows in particular to use the DAL host functions in the mockup. ### Installer client/kernel diff --git a/src/kernel_sdk/host/src/dal_parameters.rs b/src/kernel_sdk/host/src/dal_parameters.rs index 3f978ae38db051aa22573e585464c97402ad810a..1b1ab22160f1820dfe3b9bbb2d18cd597b7bab14 100644 --- a/src/kernel_sdk/host/src/dal_parameters.rs +++ b/src/kernel_sdk/host/src/dal_parameters.rs @@ -52,3 +52,14 @@ impl TryFrom<[u8; DAL_PARAMETERS_SIZE]> for RollupDalParameters { }) } } + +impl From<&RollupDalParameters> for [u8; DAL_PARAMETERS_SIZE] { + fn from(value: &RollupDalParameters) -> [u8; DAL_PARAMETERS_SIZE] { + let mut data = [0; 4]; + data[0] = (value.number_of_slots as i64).to_be(); + data[1] = (value.attestation_lag as i64).to_be(); + data[2] = (value.slot_size as i64).to_be(); + data[3] = (value.page_size as i64).to_be(); + unsafe { core::mem::transmute(data) } + } +} diff --git a/src/kernel_sdk/mock/src/host.rs b/src/kernel_sdk/mock/src/host.rs index 2c2d9c67ed86b43440c8d789d774a3d05653f123..6104c15f1ad265c7fadf82b3ce1a05f8a6264d57 100644 --- a/src/kernel_sdk/mock/src/host.rs +++ b/src/kernel_sdk/mock/src/host.rs @@ -12,11 +12,14 @@ use crate::state::{HostState, NextInput}; use crate::MockHost; use core::{ cell::RefCell, + cmp::min, + mem::size_of, ptr, slice::{from_raw_parts, from_raw_parts_mut}, }; use tezos_smart_rollup_core::smart_rollup_core::{ReadInputMessageInfo, SmartRollupCore}; use tezos_smart_rollup_core::PREIMAGE_HASH_SIZE; +use tezos_smart_rollup_host::dal_parameters::DAL_PARAMETERS_SIZE; use tezos_smart_rollup_host::metadata::METADATA_SIZE; use tezos_smart_rollup_host::Error; @@ -37,6 +40,40 @@ impl AsMut for MockHost { } } +unsafe fn reveal_dal_parameters( + host: &MockHost, + destination_addr: *mut u8, + max_bytes: usize, +) -> i32 { + let params: [u8; DAL_PARAMETERS_SIZE] = + host.state.borrow().get_dal_parameters().into(); + let len = min(max_bytes, params.len()); + let slice = from_raw_parts_mut(destination_addr, len); + slice.copy_from_slice(¶ms[..len]); + len as i32 +} + +unsafe fn reveal_dal_page( + host: &MockHost, + published_level: i32, + slot_index: u8, + page_index: i16, + destination_addr: *mut u8, + max_bytes: usize, +) -> i32 { + let state = host.state.borrow(); + let params = state.get_dal_parameters(); + let page_size = params.page_size as usize; + let len = min(max_bytes, page_size); + let start = ((page_index as u64) * params.page_size) as usize; + let Some(slot) = state.get_dal_slot(published_level, slot_index) else { + return 0; + }; + let slice = from_raw_parts_mut(destination_addr, len); + slice.copy_from_slice(&slot[start..start + len]); + len as i32 +} + unsafe impl SmartRollupCore for MockHost { unsafe fn read_input( &self, @@ -183,6 +220,8 @@ unsafe impl SmartRollupCore for MockHost { self.state.borrow().store.store_value_size(path, path_len) } + // TODO adapt reveal_metadata + // https://gitlab.com/tezos/tezos/-/issues/7378 unsafe fn reveal_metadata(&self, destination_addr: *mut u8, max_bytes: usize) -> i32 { assert!(METADATA_SIZE <= max_bytes); let metadata: [u8; METADATA_SIZE] = @@ -192,15 +231,60 @@ unsafe impl SmartRollupCore for MockHost { metadata.len().try_into().unwrap() } + // TODO turn payload.split_at into a read or error code helper function. + // https://gitlab.com/tezos/tezos/-/issues/7377 unsafe fn reveal( &self, - _payload_addr: *const u8, - _payload_len: usize, - _destination_addr: *mut u8, - _max_bytes: usize, + payload_addr: *const u8, + payload_len: usize, + destination_addr: *mut u8, + max_bytes: usize, ) -> i32 { - // TODO: https://gitlab.com/tezos/tezos/-/issues/6171 - unimplemented!("The `reveal` host function is not yet mocked.") + let payload: &[u8] = from_raw_parts(payload_addr, payload_len); + let (tag, payload) = payload.split_at(size_of::()); + match tag[0] { + 0 => { + // Reveal_raw_data + self.reveal_preimage( + payload_addr.add(1), + payload_len.saturating_sub(1), + destination_addr, + max_bytes, + ) + } + 1 => { + // Reveal_metadata + self.reveal_metadata(destination_addr, max_bytes) + } + 2 => { + // Reveal_dal_page + let (published_level, remaining) = payload.split_at(size_of::()); + let (slot_index, remaining) = remaining.split_at(size_of::()); + let (page_index, _) = remaining.split_at(size_of::()); + + let published_level = + i32::from_be_bytes(published_level.try_into().unwrap()); + let slot_index = slot_index[0]; + let page_index = i16::from_be_bytes(page_index.try_into().unwrap()); + + reveal_dal_page( + self, + published_level, + slot_index, + page_index, + destination_addr, + max_bytes, + ) + } + 3 => { + // Reveal_dal_parameters + reveal_dal_parameters(self, destination_addr, max_bytes) + } + tag => unimplemented!( + "The `reveal` host function is not yet mocked for tag {}.", + tag + ), + } } } diff --git a/src/kernel_sdk/mock/src/state/mod.rs b/src/kernel_sdk/mock/src/state/mod.rs index cc3aae2244fccb962f171901545cd542e3407f24..25b43e5e2991c06539d7a015c46289bf7e7b7933 100644 --- a/src/kernel_sdk/mock/src/state/mod.rs +++ b/src/kernel_sdk/mock/src/state/mod.rs @@ -10,7 +10,9 @@ use crypto::hash::SmartRollupHash; use tezos_smart_rollup_core::{ MAX_INPUT_MESSAGE_SIZE, MAX_OUTPUT_SIZE, PREIMAGE_HASH_SIZE, }; -use tezos_smart_rollup_host::{metadata::RollupMetadata, Error}; +use tezos_smart_rollup_host::{ + dal_parameters::RollupDalParameters, metadata::RollupMetadata, Error, +}; pub(crate) mod in_memory_store; pub(crate) mod store; @@ -32,6 +34,7 @@ pub(crate) struct HostState { /// Key-value store of runtime state. pub store: InMemoryStore, pub metadata: RollupMetadata, + pub dal_parameters: RollupDalParameters, // Inbox metadata pub(crate) curr_level: u32, pub(crate) curr_input_id: usize, @@ -52,9 +55,17 @@ impl Default for HostState { raw_rollup_address, origination_level: crate::NAIROBI_ACTIVATION_LEVEL, }; + + let dal_parameters = RollupDalParameters { + number_of_slots: 16, + attestation_lag: 8, + slot_size: 126944, + page_size: 3967, + }; Self { store, metadata, + dal_parameters, curr_level: crate::NAIROBI_ACTIVATION_LEVEL, curr_input_id: 0, input: vec![], @@ -133,6 +144,23 @@ impl HostState { pub(crate) fn get_metadata(&self) -> &RollupMetadata { &self.metadata } + + pub(crate) fn get_dal_parameters(&self) -> &RollupDalParameters { + &self.dal_parameters + } + + #[allow(dead_code)] + pub(crate) fn set_dal_parameters(&mut self, params: RollupDalParameters) { + self.dal_parameters = params + } + + pub(crate) fn get_dal_slot( + &self, + published_level: i32, + slot_index: u8, + ) -> Option<&Vec> { + self.store.0.retrieve_dal_slot(published_level, slot_index) + } } #[cfg(test)] diff --git a/src/kernel_sdk/mock/src/state/store.rs b/src/kernel_sdk/mock/src/state/store.rs index f6f083b0255f7c6cd90f5b0f13529ad1e18b7947..0235f481fbd700077c9deee642eb594c5e90cea6 100644 --- a/src/kernel_sdk/mock/src/state/store.rs +++ b/src/kernel_sdk/mock/src/state/store.rs @@ -13,6 +13,7 @@ use tezos_smart_rollup_core::PREIMAGE_HASH_SIZE; pub(crate) struct Store { pub(crate) durable: Rc, preimages: HashMap<[u8; PREIMAGE_HASH_SIZE], Vec>, + dal_slots: HashMap<(i32, u8), Vec>, outbox: HashMap>>, inbox: HashMap>>, } @@ -187,6 +188,14 @@ impl Store { .expect("Cannot retrieve preimage") .as_ref() } + + pub fn retrieve_dal_slot( + &self, + published_level: i32, + slot_index: u8, + ) -> Option<&Vec> { + self.dal_slots.get(&(published_level, slot_index)) + } } fn path_steps(path: &str) -> impl Iterator {