Skip to content

Commit 26dedea

Browse files
authored
Make the behavior of ext_storage_proof_size_storage_proof_size_version_1 configurable (#1834)
* Make the behavior of `ext_storage_proof_size_storage_proof_size_version_1` configurable * Tweak docs * Fix full node compilation * More fixing * Fix doctest
1 parent d269e4c commit 26dedea

File tree

12 files changed

+227
-26
lines changed

12 files changed

+227
-26
lines changed

full-node/src/consensus_service.rs

+3
Original file line numberDiff line numberDiff line change
@@ -3015,6 +3015,7 @@ pub async fn execute_block_and_insert(
30153015
parent_runtime,
30163016
call_function,
30173017
&call_parameter,
3018+
runtime_call::StorageProofSizeBehavior::Unimplemented,
30183019
storage_changes,
30193020
)
30203021
.await
@@ -3352,12 +3353,14 @@ pub async fn runtime_call(
33523353
runtime: host::HostVmPrototype,
33533354
function_to_call: &str,
33543355
parameter: &[u8],
3356+
storage_proof_size_behavior: runtime_call::StorageProofSizeBehavior,
33553357
initial_storage_changes: runtime_call::StorageChanges,
33563358
) -> Result<RuntimeCallSuccess, RuntimeCallError> {
33573359
let mut call = runtime_call::run(runtime_call::Config {
33583360
virtual_machine: runtime,
33593361
function_to_call,
33603362
parameter: iter::once(&parameter),
3363+
storage_proof_size_behavior,
33613364
storage_main_trie_changes: initial_storage_changes.into_main_trie_diff(),
33623365
max_log_level: 0,
33633366
calculate_trie_changes: true,

full-node/src/json_rpc_service/requests_handler.rs

+1
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ pub fn spawn_requests_handler(config: Config) {
328328
function_to_call: "Metadata_metadata",
329329
parameter: iter::empty::<&'static [u8]>(),
330330
max_log_level: 0,
331+
storage_proof_size_behavior: executor::runtime_call::StorageProofSizeBehavior::proof_recording_disabled(),
331332
storage_main_trie_changes: Default::default(),
332333
calculate_trie_changes: false,
333334
}) {

lib/src/author/runtime.rs

+6
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ pub fn build_block(config: Config) -> BlockBuild {
190190
},
191191
virtual_machine: config.parent_runtime,
192192
storage_main_trie_changes: Default::default(),
193+
storage_proof_size_behavior: runtime_call::StorageProofSizeBehavior::Unimplemented,
193194
max_log_level: config.max_log_level,
194195
calculate_trie_changes: config.calculate_trie_changes,
195196
});
@@ -341,6 +342,8 @@ impl BlockBuild {
341342
function_to_call: "BlockBuilder_apply_extrinsic",
342343
parameter: iter::once(extrinsic),
343344
storage_main_trie_changes: success.storage_changes.into_main_trie_diff(),
345+
storage_proof_size_behavior:
346+
runtime_call::StorageProofSizeBehavior::Unimplemented,
344347
max_log_level: shared.max_log_level,
345348
calculate_trie_changes: shared.calculate_trie_changes,
346349
});
@@ -539,6 +542,7 @@ impl InherentExtrinsics {
539542
.map(either::Left)
540543
.chain(encoded_list.map(either::Right))
541544
},
545+
storage_proof_size_behavior: runtime_call::StorageProofSizeBehavior::Unimplemented,
542546
storage_main_trie_changes: self.storage_changes.into_main_trie_diff(),
543547
max_log_level: self.shared.max_log_level,
544548
calculate_trie_changes: self.shared.calculate_trie_changes,
@@ -570,6 +574,7 @@ impl ApplyExtrinsic {
570574
virtual_machine: self.parent_runtime,
571575
function_to_call: "BlockBuilder_apply_extrinsic",
572576
parameter: iter::once(&extrinsic),
577+
storage_proof_size_behavior: runtime_call::StorageProofSizeBehavior::Unimplemented,
573578
storage_main_trie_changes: self.storage_changes.into_main_trie_diff(),
574579
max_log_level: self.shared.max_log_level,
575580
calculate_trie_changes: self.shared.calculate_trie_changes,
@@ -593,6 +598,7 @@ impl ApplyExtrinsic {
593598
virtual_machine: self.parent_runtime,
594599
function_to_call: "BlockBuilder_finalize_block",
595600
parameter: iter::empty::<&[u8]>(),
601+
storage_proof_size_behavior: runtime_call::StorageProofSizeBehavior::Unimplemented,
596602
storage_main_trie_changes: self.storage_changes.into_main_trie_diff(),
597603
max_log_level: self.shared.max_log_level,
598604
calculate_trie_changes: self.shared.calculate_trie_changes,

lib/src/chain/chain_information/build.rs

+2
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,8 @@ impl ChainInformationBuild {
494494
parameter: call.parameter_vectored(),
495495
virtual_machine: inner.virtual_machine.take().unwrap(),
496496
max_log_level: 0,
497+
storage_proof_size_behavior:
498+
runtime_call::StorageProofSizeBehavior::proof_recording_disabled(),
497499
storage_main_trie_changes: Default::default(),
498500
calculate_trie_changes: false,
499501
});

lib/src/executor/host.rs

+89-8
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,9 @@
143143
//! ## Example
144144
//!
145145
//! ```
146-
//! use smoldot::executor::host::{Config, HeapPages, HostVm, HostVmPrototype};
146+
//! use smoldot::executor::host::{
147+
//! Config, HeapPages, HostVm, HostVmPrototype, StorageProofSizeBehavior
148+
//! };
147149
//!
148150
//! # let wasm_binary_code: &[u8] = return;
149151
//!
@@ -155,7 +157,10 @@
155157
//! exec_hint: smoldot::executor::vm::ExecHint::ValidateAndExecuteOnce,
156158
//! allow_unresolved_imports: false
157159
//! }).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()
159164
//! };
160165
//!
161166
//! // We need to answer the calls that the runtime might perform.
@@ -234,6 +239,33 @@ pub struct Config<TModule> {
234239
pub allow_unresolved_imports: bool,
235240
}
236241

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+
237269
/// Prototype for an [`HostVm`].
238270
///
239271
/// > **Note**: This struct implements `Clone`. Cloning a [`HostVmPrototype`] allocates memory
@@ -380,7 +412,10 @@ impl HostVmPrototype {
380412

381413
// Call `Core_version` if no runtime version is known yet.
382414
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+
) {
384419
Ok(vm) => vm.into(),
385420
Err((err, _)) => return Err(NewErr::CoreVersion(CoreVersionError::Start(err))),
386421
};
@@ -438,20 +473,47 @@ impl HostVmPrototype {
438473
}
439474

440475
/// 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+
)
443490
}
444491

445492
/// 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+
)
448506
}
449507

450508
/// Same as [`HostVmPrototype::run`], except that the function parameter can be passed as
451509
/// 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.
452513
pub fn run_vectored(
453514
mut self,
454515
function_to_call: &str,
516+
storage_proof_size_behavior: StorageProofSizeBehavior,
455517
data: impl Iterator<Item = impl AsRef<[u8]>> + Clone,
456518
) -> Result<ReadyToRun, (StartErr, Self)> {
457519
// Determine the total length of `data`.
@@ -535,6 +597,7 @@ impl HostVmPrototype {
535597
storage_transaction_depth: 0,
536598
signatures_batch_verification: None,
537599
allocator,
600+
storage_proof_size_behavior,
538601
}),
539602
})
540603
}
@@ -1182,7 +1245,22 @@ impl ReadyToRun {
11821245
}
11831246
}
11841247
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+
}
11861264
}
11871265
HostFunction::ext_default_child_storage_get_version_1 => {
11881266
let (child_trie_ptr, child_trie_size) = expect_pointer_size_raw!(0);
@@ -3703,6 +3781,9 @@ struct Inner {
37033781
/// Memory allocator in order to answer the calls to `malloc` and `free`.
37043782
allocator: allocator::FreeingBumpHeapAllocator,
37053783

3784+
/// Value passed as parameter.
3785+
storage_proof_size_behavior: StorageProofSizeBehavior,
3786+
37063787
/// Fields that are kept as is even during the execution.
37073788
common: Box<VmCommon>,
37083789
}

lib/src/executor/host/tests.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
#![cfg(test)]
1919

20-
use super::{vm::ExecHint, Config, HeapPages, HostVm, HostVmPrototype};
20+
use super::{vm::ExecHint, Config, HeapPages, HostVm, HostVmPrototype, StorageProofSizeBehavior};
2121

2222
mod hash_algorithms;
2323
mod initialization;
@@ -97,7 +97,13 @@ fn basic_core_version() {
9797
})
9898
.unwrap();
9999

100-
let mut vm = proto.run_no_param("Core_version").unwrap().run();
100+
let mut vm = proto
101+
.run_no_param(
102+
"Core_version",
103+
StorageProofSizeBehavior::proof_recording_disabled(),
104+
)
105+
.unwrap()
106+
.run();
101107
loop {
102108
match vm {
103109
HostVm::ReadyToRun(r) => vm = r.run(),

lib/src/executor/host/tests/hash_algorithms.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
// You should have received a copy of the GNU General Public License
1616
// along with this program. If not, see <http://www.gnu.org/licenses/>.
1717

18-
use super::super::{vm::ExecHint, Config, HeapPages, HostVm, HostVmPrototype};
18+
use super::super::{
19+
vm::ExecHint, Config, HeapPages, HostVm, HostVmPrototype, StorageProofSizeBehavior,
20+
};
1921
use super::with_core_version_custom_sections;
2022

2123
/*
@@ -221,7 +223,15 @@ macro_rules! gen_test {
221223
})
222224
.unwrap();
223225

224-
let mut vm = HostVm::from(proto.run("test", &$expected_out).unwrap());
226+
let mut vm = HostVm::from(
227+
proto
228+
.run(
229+
"test",
230+
StorageProofSizeBehavior::proof_recording_disabled(),
231+
&$expected_out,
232+
)
233+
.unwrap(),
234+
);
225235
loop {
226236
match vm {
227237
HostVm::ReadyToRun(r) => vm = r.run(),

0 commit comments

Comments
 (0)