|
143 | 143 | //! ## Example
|
144 | 144 | //!
|
145 | 145 | //! ```
|
146 |
| -//! use smoldot::executor::host::{Config, HeapPages, HostVm, HostVmPrototype}; |
| 146 | +//! use smoldot::executor::host::{ |
| 147 | +//! Config, HeapPages, HostVm, HostVmPrototype, StorageProofSizeBehavior |
| 148 | +//! }; |
147 | 149 | //!
|
148 | 150 | //! # let wasm_binary_code: &[u8] = return;
|
149 | 151 | //!
|
|
155 | 157 | //! exec_hint: smoldot::executor::vm::ExecHint::ValidateAndExecuteOnce,
|
156 | 158 | //! allow_unresolved_imports: false
|
157 | 159 | //! }).unwrap();
|
158 |
| -//! prototype.run_no_param("Core_version").unwrap().into() |
| 160 | +//! prototype.run_no_param( |
| 161 | +//! "Core_version", |
| 162 | +//! StorageProofSizeBehavior::proof_recording_disabled() |
| 163 | +//! ).unwrap().into() |
159 | 164 | //! };
|
160 | 165 | //!
|
161 | 166 | //! // We need to answer the calls that the runtime might perform.
|
@@ -234,6 +239,33 @@ pub struct Config<TModule> {
|
234 | 239 | pub allow_unresolved_imports: bool,
|
235 | 240 | }
|
236 | 241 |
|
| 242 | +/// Behavior if the `ext_storage_proof_size_storage_proof_size_version_1` host function is called. |
| 243 | +/// |
| 244 | +/// When authoring a block or executing a block, this host function is expected to return the |
| 245 | +/// current size of the proof. Smoldot unfortunately can't implement this due to the fact that |
| 246 | +/// the proof generation algorithm is completely unspecified. For this reason, you should |
| 247 | +/// use [`StorageProofSizeBehavior::Unimplemented`]. However, for testing purposes, using |
| 248 | +/// `StorageProofSizeBehavior::ConstantReturnValue(0)` is acceptable. |
| 249 | +/// |
| 250 | +/// In situations other than authoring or executing a block, use the value returned by |
| 251 | +/// [`StorageProofSizeBehavior::proof_recording_disabled`]. |
| 252 | +/// |
| 253 | +#[derive(Debug, Clone, PartialEq, Eq)] |
| 254 | +pub enum StorageProofSizeBehavior { |
| 255 | + /// The host function is unimplemented. An error is returned if it is called. |
| 256 | + Unimplemented, |
| 257 | + /// The host function returns the given value. |
| 258 | + ConstantReturnValue(u64), |
| 259 | +} |
| 260 | + |
| 261 | +impl StorageProofSizeBehavior { |
| 262 | + /// Returns the behavior to employ when proof recording is disabled, as defined in the |
| 263 | + /// specification. |
| 264 | + pub fn proof_recording_disabled() -> Self { |
| 265 | + StorageProofSizeBehavior::ConstantReturnValue(u64::MAX) |
| 266 | + } |
| 267 | +} |
| 268 | + |
237 | 269 | /// Prototype for an [`HostVm`].
|
238 | 270 | ///
|
239 | 271 | /// > **Note**: This struct implements `Clone`. Cloning a [`HostVmPrototype`] allocates memory
|
@@ -380,7 +412,10 @@ impl HostVmPrototype {
|
380 | 412 |
|
381 | 413 | // Call `Core_version` if no runtime version is known yet.
|
382 | 414 | if host_vm_prototype.common.runtime_version.is_none() {
|
383 |
| - let mut vm: HostVm = match host_vm_prototype.run_no_param("Core_version") { |
| 415 | + let mut vm: HostVm = match host_vm_prototype.run_no_param( |
| 416 | + "Core_version", |
| 417 | + StorageProofSizeBehavior::proof_recording_disabled(), |
| 418 | + ) { |
384 | 419 | Ok(vm) => vm.into(),
|
385 | 420 | Err((err, _)) => return Err(NewErr::CoreVersion(CoreVersionError::Start(err))),
|
386 | 421 | };
|
@@ -438,20 +473,47 @@ impl HostVmPrototype {
|
438 | 473 | }
|
439 | 474 |
|
440 | 475 | /// Starts the VM, calling the function passed as parameter.
|
441 |
| - pub fn run(self, function_to_call: &str, data: &[u8]) -> Result<ReadyToRun, (StartErr, Self)> { |
442 |
| - self.run_vectored(function_to_call, iter::once(data)) |
| 476 | + /// |
| 477 | + /// See the documentation of [`StorageProofSizeBehavior`] for an explanation of |
| 478 | + /// the `storage_proof_size_behavior` parameter. |
| 479 | + pub fn run( |
| 480 | + self, |
| 481 | + function_to_call: &str, |
| 482 | + storage_proof_size_behavior: StorageProofSizeBehavior, |
| 483 | + data: &[u8], |
| 484 | + ) -> Result<ReadyToRun, (StartErr, Self)> { |
| 485 | + self.run_vectored( |
| 486 | + function_to_call, |
| 487 | + storage_proof_size_behavior, |
| 488 | + iter::once(data), |
| 489 | + ) |
443 | 490 | }
|
444 | 491 |
|
445 | 492 | /// Same as [`HostVmPrototype::run`], except that the function doesn't need any parameter.
|
446 |
| - pub fn run_no_param(self, function_to_call: &str) -> Result<ReadyToRun, (StartErr, Self)> { |
447 |
| - self.run_vectored(function_to_call, iter::empty::<Vec<u8>>()) |
| 493 | + /// |
| 494 | + /// See the documentation of [`StorageProofSizeBehavior`] for an explanation of |
| 495 | + /// the `storage_proof_size_behavior` parameter. |
| 496 | + pub fn run_no_param( |
| 497 | + self, |
| 498 | + function_to_call: &str, |
| 499 | + storage_proof_size_behavior: StorageProofSizeBehavior, |
| 500 | + ) -> Result<ReadyToRun, (StartErr, Self)> { |
| 501 | + self.run_vectored( |
| 502 | + function_to_call, |
| 503 | + storage_proof_size_behavior, |
| 504 | + iter::empty::<Vec<u8>>(), |
| 505 | + ) |
448 | 506 | }
|
449 | 507 |
|
450 | 508 | /// Same as [`HostVmPrototype::run`], except that the function parameter can be passed as
|
451 | 509 | /// a list of buffers. All the buffers will be concatenated in memory.
|
| 510 | + /// |
| 511 | + /// See the documentation of [`StorageProofSizeBehavior`] for an explanation of |
| 512 | + /// the `storage_proof_size_behavior` parameter. |
452 | 513 | pub fn run_vectored(
|
453 | 514 | mut self,
|
454 | 515 | function_to_call: &str,
|
| 516 | + storage_proof_size_behavior: StorageProofSizeBehavior, |
455 | 517 | data: impl Iterator<Item = impl AsRef<[u8]>> + Clone,
|
456 | 518 | ) -> Result<ReadyToRun, (StartErr, Self)> {
|
457 | 519 | // Determine the total length of `data`.
|
@@ -535,6 +597,7 @@ impl HostVmPrototype {
|
535 | 597 | storage_transaction_depth: 0,
|
536 | 598 | signatures_batch_verification: None,
|
537 | 599 | allocator,
|
| 600 | + storage_proof_size_behavior, |
538 | 601 | }),
|
539 | 602 | })
|
540 | 603 | }
|
@@ -1182,7 +1245,22 @@ impl ReadyToRun {
|
1182 | 1245 | }
|
1183 | 1246 | }
|
1184 | 1247 | HostFunction::ext_storage_proof_size_storage_proof_size_version_1 => {
|
1185 |
| - host_fn_not_implemented!() |
| 1248 | + match self.inner.storage_proof_size_behavior { |
| 1249 | + StorageProofSizeBehavior::ConstantReturnValue(value) => { |
| 1250 | + HostVm::ReadyToRun(ReadyToRun { |
| 1251 | + inner: self.inner, |
| 1252 | + resume_value: Some(vm::WasmValue::I64(i64::from_ne_bytes( |
| 1253 | + value.to_ne_bytes(), |
| 1254 | + ))), |
| 1255 | + }) |
| 1256 | + } |
| 1257 | + StorageProofSizeBehavior::Unimplemented => HostVm::Error { |
| 1258 | + error: Error::HostFunctionNotImplemented { |
| 1259 | + function: host_fn.name(), |
| 1260 | + }, |
| 1261 | + prototype: self.inner.into_prototype(), |
| 1262 | + }, |
| 1263 | + } |
1186 | 1264 | }
|
1187 | 1265 | HostFunction::ext_default_child_storage_get_version_1 => {
|
1188 | 1266 | let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0);
|
@@ -3703,6 +3781,9 @@ struct Inner {
|
3703 | 3781 | /// Memory allocator in order to answer the calls to `malloc` and `free`.
|
3704 | 3782 | allocator: allocator::FreeingBumpHeapAllocator,
|
3705 | 3783 |
|
| 3784 | + /// Value passed as parameter. |
| 3785 | + storage_proof_size_behavior: StorageProofSizeBehavior, |
| 3786 | + |
3706 | 3787 | /// Fields that are kept as is even during the execution.
|
3707 | 3788 | common: Box<VmCommon>,
|
3708 | 3789 | }
|
|
0 commit comments