Skip to content

Commit

Permalink
Implement the functionalities of listing the ChainIds. (#3355)
Browse files Browse the repository at this point in the history
## Motivation

We implement here the functionality of listing the Chain IDs from a storage.

## Proposal

The implementation follows the same path as from the implementation of
the listing of the BlobIds by using the `list_root_keys`.
The `list_root_keys` functionality is removed from the CLI.

## Test Plan

The functionality was tested locally by running the non-fungible test and listing the Chain IDs.

## Release Plan

Normal release schedule.
  • Loading branch information
MathieuDutSik authored Feb 19, 2025
1 parent 5102a03 commit e03ed99
Show file tree
Hide file tree
Showing 10 changed files with 81 additions and 47 deletions.
22 changes: 11 additions & 11 deletions CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ This document contains the help content for the `linera` command-line program.
* [`linera storage initialize`](#linera-storage-initialize)
* [`linera storage list_namespaces`](#linera-storage-list_namespaces)
* [`linera storage list_blob_ids`](#linera-storage-list_blob_ids)
* [`linera storage list_root_keys`](#linera-storage-list_root_keys)
* [`linera storage list_chain_ids`](#linera-storage-list_chain_ids)

## `linera`

Expand Down Expand Up @@ -961,20 +961,20 @@ Operation on the storage

###### **Subcommands:**

* `delete_all` — Delete all the namespaces of the database
* `delete_all` — Delete all the namespaces in the database
* `delete_namespace` — Delete a single namespace from the database
* `check_existence` — Check existence of a namespace in the database
* `check_absence` — Check absence of a namespace in the database
* `initialize` — Initialize a namespace in the database
* `list_namespaces` — List the namespaces of the database
* `list_blob_ids` — List the blobs of the database
* `list_root_keys` — List the root keys of the database
* `list_namespaces` — List the namespaces in the database
* `list_blob_ids` — List the blob IDs in the database
* `list_chain_ids` — List the chain IDs in the database



## `linera storage delete_all`

Delete all the namespaces of the database
Delete all the namespaces in the database

**Usage:** `linera storage delete_all --storage <STORAGE_CONFIG>`

Expand Down Expand Up @@ -1034,7 +1034,7 @@ Initialize a namespace in the database

## `linera storage list_namespaces`

List the namespaces of the database
List the namespaces in the database

**Usage:** `linera storage list_namespaces --storage <STORAGE_CONFIG>`

Expand All @@ -1046,7 +1046,7 @@ List the namespaces of the database

## `linera storage list_blob_ids`

List the blobs of the database
List the blob IDs in the database

**Usage:** `linera storage list_blob_ids --storage <STORAGE_CONFIG>`

Expand All @@ -1056,11 +1056,11 @@ List the blobs of the database



## `linera storage list_root_keys`
## `linera storage list_chain_ids`

List the root keys of the database
List the chain IDs in the database

**Usage:** `linera storage list_root_keys --storage <STORAGE_CONFIG>`
**Usage:** `linera storage list_chain_ids --storage <STORAGE_CONFIG>`

###### **Options:**

Expand Down
2 changes: 1 addition & 1 deletion linera-chain/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ impl Block {
blob_ids
}

/// Returns set of blob ids that were a result of an oracle call.
/// Returns set of blob IDs that were a result of an oracle call.
pub fn oracle_blob_ids(&self) -> BTreeSet<BlobId> {
let mut required_blob_ids = BTreeSet::new();
for responses in &self.body.oracle_responses {
Expand Down
14 changes: 7 additions & 7 deletions linera-client/src/client_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -944,7 +944,7 @@ pub static DEFAULT_PAUSE_AFTER_GQL_MUTATIONS_SECS: &str = "3";

#[derive(Clone, clap::Parser)]
pub enum DatabaseToolCommand {
/// Delete all the namespaces of the database
/// Delete all the namespaces in the database
#[command(name = "delete_all")]
DeleteAll {
/// Storage configuration for the blockchain history.
Expand Down Expand Up @@ -984,25 +984,25 @@ pub enum DatabaseToolCommand {
storage_config: String,
},

/// List the namespaces of the database
/// List the namespaces in the database
#[command(name = "list_namespaces")]
ListNamespaces {
/// Storage configuration for the blockchain history.
#[arg(long = "storage")]
storage_config: String,
},

/// List the blobs of the database
/// List the blob IDs in the database
#[command(name = "list_blob_ids")]
ListBlobIds {
/// Storage configuration for the blockchain history.
#[arg(long = "storage")]
storage_config: String,
},

/// List the root keys of the database
#[command(name = "list_root_keys")]
ListRootKeys {
/// List the chain IDs in the database
#[command(name = "list_chain_ids")]
ListChainIds {
/// Storage configuration for the blockchain history.
#[arg(long = "storage")]
storage_config: String,
Expand All @@ -1019,7 +1019,7 @@ impl DatabaseToolCommand {
DatabaseToolCommand::Initialize { storage_config } => storage_config,
DatabaseToolCommand::ListNamespaces { storage_config } => storage_config,
DatabaseToolCommand::ListBlobIds { storage_config } => storage_config,
DatabaseToolCommand::ListRootKeys { storage_config } => storage_config,
DatabaseToolCommand::ListChainIds { storage_config } => storage_config,
};
Ok(storage_config.parse::<StorageConfigNamespace>()?)
}
Expand Down
20 changes: 10 additions & 10 deletions linera-client/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
use std::{fmt, str::FromStr};

use async_trait::async_trait;
use linera_base::identifiers::BlobId;
use linera_base::identifiers::{BlobId, ChainId};
use linera_execution::WasmRuntime;
#[cfg(with_storage)]
use linera_storage::list_all_blob_ids;
use linera_storage::{list_all_blob_ids, list_all_chain_ids};
use linera_storage::{DbStorage, Storage};
#[cfg(feature = "storage-service")]
use linera_storage_service::{
Expand Down Expand Up @@ -558,7 +558,7 @@ impl StoreConfig {
}
}

/// Lists all the namespaces of the storage
/// Lists all the blobs of the storage
pub async fn list_blob_ids(self) -> Result<Vec<BlobId>, ViewError> {
match self {
StoreConfig::Memory(_, _) => Err(ViewError::StoreError {
Expand Down Expand Up @@ -593,28 +593,28 @@ impl StoreConfig {
}
}

/// Lists all root keys of the storage
pub async fn list_root_keys(self) -> Result<Vec<Vec<u8>>, ViewError> {
/// Lists all the chain IDs of the storage
pub async fn list_chain_ids(self) -> Result<Vec<ChainId>, ViewError> {
match self {
StoreConfig::Memory(_, _) => Err(ViewError::StoreError {
backend: "memory".to_string(),
error: "list_root_keys is not supported for the memory storage".to_string(),
error: "list_chain_ids is not supported for the memory storage".to_string(),
}),
#[cfg(feature = "storage-service")]
StoreConfig::Service(config, namespace) => {
Ok(ServiceStoreClient::list_root_keys(&config, &namespace).await?)
Ok(list_all_chain_ids::<ServiceStoreClient>(&config, &namespace).await?)
}
#[cfg(feature = "rocksdb")]
StoreConfig::RocksDb(config, namespace) => {
Ok(RocksDbStore::list_root_keys(&config, &namespace).await?)
Ok(list_all_chain_ids::<RocksDbStore>(&config, &namespace).await?)
}
#[cfg(feature = "dynamodb")]
StoreConfig::DynamoDb(config, namespace) => {
Ok(DynamoDbStore::list_root_keys(&config, &namespace).await?)
Ok(list_all_chain_ids::<DynamoDbStore>(&config, &namespace).await?)
}
#[cfg(feature = "scylladb")]
StoreConfig::ScyllaDb(config, namespace) => {
Ok(ScyllaDbStore::list_root_keys(&config, &namespace).await?)
Ok(list_all_chain_ids::<ScyllaDbStore>(&config, &namespace).await?)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion linera-core/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ pub trait ValidatorNode {
/// Returns the hash of the `Certificate` that last used a blob.
async fn blob_last_used_by(&self, blob_id: BlobId) -> Result<CryptoHash, NodeError>;

/// Returns the missing `Blob`s. by their ids.
/// Returns the missing `Blob`s. by their IDs.
async fn missing_blob_ids(&self, blob_ids: Vec<BlobId>) -> Result<Vec<BlobId>, NodeError>;
}

Expand Down
4 changes: 2 additions & 2 deletions linera-execution/src/applications.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ where
&mut self,
application: UserApplicationDescription,
) -> Result<UserApplicationId, SystemExecutionError> {
// Make sure that referenced applications ids have been registered.
// Make sure that referenced applications IDs have been registered.
for required_id in &application.required_application_ids {
self.describe_application(*required_id).await?;
}
Expand All @@ -69,7 +69,7 @@ where
parameters: Vec<u8>,
required_application_ids: Vec<UserApplicationId>,
) -> Result<(), SystemExecutionError> {
// Make sure that referenced applications ids have been registered.
// Make sure that referenced applications IDs have been registered.
for required_id in &required_application_ids {
self.describe_application(*required_id).await?;
}
Expand Down
2 changes: 1 addition & 1 deletion linera-rpc/src/grpc/conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ pub enum GrpcProtoConversionError {
SignatureError(ed25519_dalek::SignatureError),
#[error("Cryptographic error: {0}")]
CryptoError(#[from] CryptoError),
#[error("Inconsistent outer/inner chain ids")]
#[error("Inconsistent outer/inner chain IDs")]
InconsistentChainId,
#[error("Unrecognized certificate type")]
InvalidCertificateType,
Expand Down
8 changes: 4 additions & 4 deletions linera-service/src/linera/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1756,13 +1756,13 @@ async fn run(options: &ClientOptions) -> Result<i32, anyhow::Error> {
info!("Blob IDs listed in {} ms", start_time.elapsed().as_millis());
println!("The list of blob IDs is {:?}", blob_ids);
}
DatabaseToolCommand::ListRootKeys { .. } => {
let root_keys = Box::pin(full_storage_config.list_root_keys()).await?;
DatabaseToolCommand::ListChainIds { .. } => {
let chain_ids = Box::pin(full_storage_config.list_chain_ids()).await?;
info!(
"Root keys listed in {} ms",
"Chain IDs listed in {} ms",
start_time.elapsed().as_millis()
);
println!("The list of root keys is {:?}", root_keys);
println!("The list of chain IDs is {:?}", chain_ids);
}
}
Ok(0)
Expand Down
50 changes: 41 additions & 9 deletions linera-storage/src/db_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use linera_views::{
backends::dual::{DualStoreRootKeyAssignment, StoreInUse},
batch::Batch,
context::ViewContext,
store::{KeyIterable as _, KeyValueStore},
store::{AdminKeyValueStore, KeyIterable as _, KeyValueStore},
views::{View, ViewError},
};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -277,17 +277,21 @@ enum BaseKey {
Event(EventId),
}

const INDEX_BLOB: u8 = 3;
const BLOB_LENGTH: usize = std::mem::size_of::<BlobId>();
const INDEX_CHAIN_ID: u8 = 0;
const INDEX_BLOB_ID: u8 = 3;
const CHAIN_ID_LENGTH: usize = std::mem::size_of::<ChainId>();
const BLOB_ID_LENGTH: usize = std::mem::size_of::<BlobId>();

#[cfg(test)]
mod tests {
use linera_base::{
crypto::CryptoHash,
identifiers::{BlobId, BlobType},
identifiers::{BlobId, BlobType, ChainId},
};

use crate::db_storage::{BaseKey, INDEX_BLOB};
use crate::db_storage::{
BaseKey, BLOB_ID_LENGTH, CHAIN_ID_LENGTH, INDEX_BLOB_ID, INDEX_CHAIN_ID,
};

#[test]
fn test_base_key_serialization() {
Expand All @@ -296,24 +300,52 @@ mod tests {
let blob_id = BlobId::new(hash, blob_type);
let base_key = BaseKey::Blob(blob_id);
let key = bcs::to_bytes(&base_key).expect("a key");
assert_eq!(key[0], INDEX_BLOB);
assert_eq!(key[0], INDEX_BLOB_ID);
assert_eq!(key.len(), 1 + BLOB_ID_LENGTH);
}

#[test]
fn test_chain_id_serialization() {
let hash = CryptoHash::default();
let chain_id = ChainId(hash);
let base_key = BaseKey::ChainState(chain_id);
let key = bcs::to_bytes(&base_key).expect("a key");
assert_eq!(key[0], INDEX_CHAIN_ID);
assert_eq!(key.len(), 1 + CHAIN_ID_LENGTH);
}
}

/// Lists the blobs of the storage.
/// Lists the blob IDs of the storage.
pub async fn list_all_blob_ids<S: KeyValueStore>(store: &S) -> Result<Vec<BlobId>, ViewError> {
let prefix = &[INDEX_BLOB];
let prefix = &[INDEX_BLOB_ID];
let keys = store.find_keys_by_prefix(prefix).await?;
let mut blob_ids = Vec::new();
for key in keys.iterator() {
let key = key?;
let key_red = &key[..BLOB_LENGTH];
let key_red = &key[..BLOB_ID_LENGTH];
let blob_id = bcs::from_bytes(key_red)?;
blob_ids.push(blob_id);
}
Ok(blob_ids)
}

/// Lists the chain IDs of the storage.
pub async fn list_all_chain_ids<S: AdminKeyValueStore>(
config: &S::Config,
namespace: &str,
) -> Result<Vec<ChainId>, ViewError> {
let root_keys = S::list_root_keys(config, namespace).await?;
let mut chain_ids = Vec::new();
for root_key in root_keys {
if root_key.len() == 1 + CHAIN_ID_LENGTH && root_key[0] == INDEX_CHAIN_ID {
let root_key_red = &root_key[1..1 + CHAIN_ID_LENGTH];
let chain_id = bcs::from_bytes(root_key_red)?;
chain_ids.push(chain_id);
}
}
Ok(chain_ids)
}

/// An implementation of [`DualStoreRootKeyAssignment`] that stores the
/// chain states into the first store.
pub struct ChainStatesFirstAssignment;
Expand Down
4 changes: 3 additions & 1 deletion linera-storage/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ use {

#[cfg(with_testing)]
pub use crate::db_storage::TestClock;
pub use crate::db_storage::{list_all_blob_ids, ChainStatesFirstAssignment, DbStorage, WallClock};
pub use crate::db_storage::{
list_all_blob_ids, list_all_chain_ids, ChainStatesFirstAssignment, DbStorage, WallClock,
};
#[cfg(with_metrics)]
pub use crate::db_storage::{
READ_CERTIFICATE_COUNTER, READ_HASHED_CONFIRMED_BLOCK_COUNTER, WRITE_CERTIFICATE_COUNTER,
Expand Down

0 comments on commit e03ed99

Please sign in to comment.