Skip to content
Open
22 changes: 22 additions & 0 deletions linera-execution/src/execution_state_actor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,22 @@ where
.to_round()?;
callback.respond(validation_round);
}

TotalStorageSize {
application,
callback,
} => {
let view = self.state.users.try_load_entry(&application).await?;
let result = match view {
Some(view) => {
let total_size = view.total_size();
(total_size.key, total_size.value)
}
None => (0, 0),
};
tracing::info!("TotalStorageSize, result={result:?}");
callback.respond(result);
}
}

Ok(())
Expand Down Expand Up @@ -1215,4 +1231,10 @@ pub enum ExecutionRequest {
#[debug(skip)]
callback: Sender<Option<u32>>,
},

TotalStorageSize {
application: ApplicationId,
#[debug(skip)]
callback: Sender<(u32, u32)>,
},
}
3 changes: 3 additions & 0 deletions linera-execution/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,9 @@ pub trait BaseRuntime {

/// Asserts the existence of a data blob with the given hash.
fn assert_data_blob_exists(&mut self, hash: DataBlobHash) -> Result<(), ExecutionError>;

/// Returns true if the corresponding contract uses a zero amount of storage.
fn has_trivial_storage(&mut self, application: ApplicationId) -> Result<bool, ExecutionError>;
}

pub trait ServiceRuntime: BaseRuntime {
Expand Down
12 changes: 12 additions & 0 deletions linera-execution/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -897,6 +897,18 @@ where
.send_request(|callback| ExecutionRequest::AssertBlobExists { blob_id, callback })?
.recv_response()
}

fn has_trivial_storage(&mut self, application: ApplicationId) -> Result<bool, ExecutionError> {
let this = self.inner();
let (key_size, value_size) = this
.execution_state_sender
.send_request(move |callback| ExecutionRequest::TotalStorageSize {
application,
callback,
})?
.recv_response()?;
Ok(key_size + value_size == 0)
}
}

/// An extension trait to determine in compile time the different behaviors between contract and
Expand Down
12 changes: 12 additions & 0 deletions linera-execution/src/wasm/runtime_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,18 @@ where
.write_batch(Batch { operations })
.map_err(|error| RuntimeError::Custom(error.into()))
}

/// Returns true if the corresponding contract uses a zero amount of storage.
fn has_trivial_storage(
caller: &mut Caller,
application: ApplicationId,
) -> Result<bool, RuntimeError> {
caller
.user_data_mut()
.runtime_mut()
.has_trivial_storage(application)
.map_err(|error| RuntimeError::Custom(error.into()))
}
}

/// An implementation of the system API made available to services.
Expand Down
5 changes: 5 additions & 0 deletions linera-sdk/src/contract/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,11 @@ where
pub fn assert_data_blob_exists(&mut self, hash: DataBlobHash) {
base_wit::assert_data_blob_exists(hash.into())
}

/// Returns true if the corresponding contract uses a zero amount of storage.
pub fn has_trivial_storage(&mut self, application: ApplicationId) -> bool {
contract_wit::has_trivial_storage(application.into())
}
}

impl<Application> ContractRuntime<Application>
Expand Down
21 changes: 21 additions & 0 deletions linera-sdk/src/contract/test_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ where
expected_http_requests: VecDeque<(http::Request, http::Response)>,
expected_read_data_blob_requests: VecDeque<(DataBlobHash, Vec<u8>)>,
expected_assert_data_blob_exists_requests: VecDeque<(DataBlobHash, Option<()>)>,
expected_has_trivial_storage_requests: VecDeque<(ApplicationId, bool)>,
expected_open_chain_calls: VecDeque<(ChainOwnership, ApplicationPermissions, Amount, ChainId)>,
expected_publish_module_calls: VecDeque<ExpectedPublishModuleCall>,
expected_create_application_calls: VecDeque<ExpectedCreateApplicationCall>,
Expand Down Expand Up @@ -127,6 +128,7 @@ where
expected_http_requests: VecDeque::new(),
expected_read_data_blob_requests: VecDeque::new(),
expected_assert_data_blob_exists_requests: VecDeque::new(),
expected_has_trivial_storage_requests: VecDeque::new(),
expected_open_chain_calls: VecDeque::new(),
expected_publish_module_calls: VecDeque::new(),
expected_create_application_calls: VecDeque::new(),
Expand Down Expand Up @@ -936,6 +938,16 @@ where
.push_back((hash, response));
}

/// Adds an expected `has_trivial_storage` call, and the response it should return in the test.
pub fn add_expected_has_trivial_storage_requests(
&mut self,
application: ApplicationId,
response: bool,
) {
self.expected_has_trivial_storage_requests
.push_back((application, response));
}

/// Queries an application service as an oracle and returns the response.
///
/// Should only be used with queries where it is very likely that all validators will compute
Expand Down Expand Up @@ -997,6 +1009,15 @@ where
response.expect("Blob does not exist!");
}

/// Returns true if the corresponding contract uses a zero amount of storage.
pub fn has_trivial_storage(&mut self, application: ApplicationId) -> bool {
let maybe_request = self.expected_has_trivial_storage_requests.pop_front();
let (expected_application_id, response) =
maybe_request.expect("Unexpected has_trivial_storage request");
assert_eq!(application, expected_application_id);
response
}

/// Returns the round in which this block was validated.
pub fn validation_round(&mut self) -> Option<u32> {
self.round
Expand Down
1 change: 1 addition & 0 deletions linera-sdk/wit/contract-runtime-api.wit
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ interface contract-runtime-api {
consume-fuel: func(fuel: u64);
validation-round: func() -> option<u32>;
write-batch: func(operations: list<write-operation>);
has-trivial-storage: func(application: application-id) -> bool;

record account {
chain-id: chain-id,
Expand Down
3 changes: 2 additions & 1 deletion linera-views/src/views/key_value_store_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -392,8 +392,9 @@ impl<C: Context> KeyValueStoreView<C> {
/// # use linera_views::views::View;
/// # let context = MemoryContext::new_for_testing(());
/// let mut view = KeyValueStoreView::load(context).await.unwrap();
/// view.insert(vec![0, 1], vec![0, 1, 2, 3, 4]).await.unwrap();
/// let total_size = view.total_size();
/// assert_eq!(total_size, SizeData::default());
/// assert_eq!(total_size, SizeData { key: 2, value: 5 });
/// # })
/// ```
pub fn total_size(&self) -> SizeData {
Expand Down
Loading