Skip to content

Commit 5b1424e

Browse files
Address a bug with the root_keys in linera-storage-service. (#4858)
## Motivation There is a bug in the handling of the root_keys in the `linera-storage-service`. The `root_key` is directly appended to the `start_key`. The result is an object which is not prefix-free. ## Proposal Replace ```rust start_key.extend(root_key) ``` by ```rust start_key.extend(bcs::to_bytes(&root_key)?) ``` by doing so, we no longer have ambiguity in the construction of `start_key`. ## Test Plan The CI. Added a test that fails on main on that precise problem. ## Release Plan Since, the `linera-storage-service` is not used in TestNet Conway, no backport is needed. ## Links None.
1 parent c338843 commit 5b1424e

File tree

3 files changed

+30
-6
lines changed

3 files changed

+30
-6
lines changed

linera-storage-service/src/client.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -304,14 +304,14 @@ impl WritableKeyValueStore for StorageServiceStoreInternal {
304304
chunk_size += self.start_key.len();
305305
}
306306

307-
let root_key_len = self.start_key.len() - self.prefix_len;
307+
let bcs_root_key_len = self.start_key.len() - self.prefix_len;
308308
for operation in batch.operations {
309309
let (key_len, value_len) = match &operation {
310310
WriteOperation::Delete { key } => (key.len(), 0),
311311
WriteOperation::Put { key, value } => (key.len(), value.len()),
312312
WriteOperation::DeletePrefix { key_prefix } => (key_prefix.len(), 0),
313313
};
314-
let operation_size = key_len + value_len + root_key_len;
314+
let operation_size = key_len + value_len + bcs_root_key_len;
315315
ensure!(
316316
key_len <= MAX_KEY_SIZE,
317317
StorageServiceStoreError::KeyTooLong
@@ -488,7 +488,7 @@ impl KeyValueDatabase for StorageServiceDatabaseInternal {
488488
let max_stream_queries = self.max_stream_queries;
489489
let mut start_key = vec![KeyPrefix::Key as u8];
490490
start_key.extend(&self.namespace);
491-
start_key.extend(root_key);
491+
start_key.extend(bcs::to_bytes(root_key)?);
492492
let prefix_len = self.namespace.len() + 1;
493493
Ok(StorageServiceStoreInternal {
494494
channel,

linera-storage-service/src/server.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,14 @@ impl StorageServer {
186186
pub async fn list_root_keys(&self, namespace: &[u8]) -> Result<Vec<Vec<u8>>, Status> {
187187
let mut full_key = vec![KeyPrefix::RootKey as u8];
188188
full_key.extend(namespace);
189-
self.find_keys_by_prefix(&full_key).await
189+
let bcs_root_keys = self.find_keys_by_prefix(&full_key).await?;
190+
let mut root_keys = Vec::new();
191+
for bcs_root_key in bcs_root_keys {
192+
let root_key = bcs::from_bytes::<Vec<u8>>(&bcs_root_key)
193+
.map_err(|e| Status::unknown(format!("Bcs error {e:?} at list_root_keys")))?;
194+
root_keys.push(root_key);
195+
}
196+
Ok(root_keys)
190197
}
191198

192199
pub async fn delete_all(&self) -> Result<(), Status> {

linera-storage-service/tests/store_test.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44
#![cfg(feature = "storage-service")]
55

66
use anyhow::Result;
7-
use linera_storage_service::client::StorageServiceDatabaseInternal;
7+
use linera_storage_service::client::{StorageServiceDatabase, StorageServiceDatabaseInternal};
88
use linera_views::{
99
batch::Batch,
10-
store::TestKeyValueDatabase as _,
10+
store::{
11+
KeyValueDatabase as _, ReadableKeyValueStore as _, TestKeyValueDatabase as _,
12+
WritableKeyValueStore as _,
13+
},
1114
test_utils::{
1215
get_random_byte_vector, get_random_test_scenarios, namespace_admin_test,
1316
root_key_admin_test, run_reads, run_test_batch_from_blank, run_writes_from_blank,
@@ -60,3 +63,17 @@ async fn test_storage_service_big_raw_write() -> Result<()> {
6063
run_test_batch_from_blank(&store, key_prefix, batch).await;
6164
Ok(())
6265
}
66+
67+
#[tokio::test]
68+
async fn test_storage_service_open_shared() -> Result<()> {
69+
let database = StorageServiceDatabase::connect_test_namespace().await?;
70+
let store1 = database.open_shared(&[2, 3, 4, 5])?;
71+
let mut batch = Batch::new();
72+
batch.put_key_value_bytes(vec![6, 7], vec![123, 135]);
73+
store1.write_batch(batch).await?;
74+
75+
let store2 = database.open_shared(&[])?;
76+
let key_values = store2.find_key_values_by_prefix(&[2]).await?;
77+
assert_eq!(key_values.len(), 0);
78+
Ok(())
79+
}

0 commit comments

Comments
 (0)