Skip to content

Commit 4ee4f79

Browse files
Implement the access to the shard_id (#4781)
## Motivation For debugging purposes, it is useful to access the shard index of the validators for a fixed chain. ## Proposal The implementation is straightforward: * Add it as an endpoint to the proxy. * Add it as a feature to the "linera" client. ## Test Plan No test has been added to the CI. However, the function has been tested locally with the following steps. A: Starting the validators ```bash ./target/debug/linera storage delete-all --storage service:tcp:localhost:1235:table_a rm -rf /tmp/WORK && mkdir -p /tmp/WORK export RUST_BACKTRACE=full ./target/debug/linera net up --policy-config testnet --storage service:tcp:localhost:1235:table_a --validators 4 --shards 4 --path /tmp/WORK ``` B: Running the faucet ```bash export LINERA_WALLET="/tmp/WORK/wallet_0.json" export LINERA_KEYSTORE="/tmp/WORK/keystore_0.json" export LINERA_STORAGE="rocksdb:/tmp/WORK/client_0.db" ./target/debug/linera faucet --amount 1000 --port 8079 --storage-path /tmp/WORK/faucet_storage.sqlite ``` C: Creating a chain, showing ```bash rm -rf /tmp/WORK_B && mkdir -p /tmp/WORK_B export LINERA_WALLET="/tmp/WORK_B/wallet_0.json" export LINERA_KEYSTORE="/tmp/WORK_B/keystore_0.json" export LINERA_STORAGE="rocksdb:/tmp/WORK_B/client_0.db" export FAUCET_URL=http://localhost:8079 ./target/debug/linera wallet init --faucet $FAUCET_URL ./target/debug/linera wallet request-chain --faucet $FAUCET_URL ./target/debug/linera wallet show ``` D: Showing up the result from the obtained `ChainId` ```bash ./target/debug/linera query-shard-info 42a1c60a969b9c6ce893fd3746ec6084e0c336820f1336fa40e39e4aa5708c5b Querying validators for shard information about chain 42a1c60a969b9c6ce893fd3746ec6084e0c336820f1336fa40e39e4aa5708c5b. Chain ID: 42a1c60a969b9c6ce893fd3746ec6084e0c336820f1336fa40e39e4aa5708c5b Validator Shard Information: Validator: 033f3e155e7c0c7fae94692df5501eeab55e98a8c086e568cb672d7a8270e7c08f Address: grpc:localhost:13004 Total Shards: 4 Shard ID for chain: 0 Validator: 02b7742453a60ad3e2d615f59aa6b00d72d0b126ea9181264f3bd459eb1e42b557 Address: grpc:localhost:13003 Total Shards: 4 Shard ID for chain: 3 Validator: 03b99ffb3804db5fa05534a5eb0bc890add528acb66b39931bca878ee2b68f72a7 Address: grpc:localhost:13001 Total Shards: 4 Shard ID for chain: 2 Validator: 02e33d49cc2279adfdfea6cafa523d739f95969ebddd13a96720f0dffafb2dceb2 Address: grpc:localhost:13002 Total Shards: 4 Shard ID for chain: 1 ``` ## Release Plan If this is feasible, then we should backport it to the TestNet Conway branch. ## Links None.
1 parent a0ea99b commit 4ee4f79

File tree

18 files changed

+214
-4
lines changed

18 files changed

+214
-4
lines changed

CLI.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ This document contains the help content for the `linera` command-line program.
2121
* [`linera process-inbox`](#linera-process-inbox)
2222
* [`linera query-validator`](#linera-query-validator)
2323
* [`linera query-validators`](#linera-query-validators)
24+
* [`linera query-shard-info`](#linera-query-shard-info)
2425
* [`linera sync-validator`](#linera-sync-validator)
2526
* [`linera sync-all-validators`](#linera-sync-all-validators)
2627
* [`linera set-validator`](#linera-set-validator)
@@ -94,6 +95,7 @@ Client implementation and command-line tool for the Linera blockchain
9495
* `process-inbox` — Process all pending incoming messages from the inbox of the given chain by creating as many blocks as needed to execute all (non-failing) messages. Failing messages will be marked as rejected and may bounce to their sender depending on their configuration
9596
* `query-validator` — Show the version and genesis config hash of a new validator, and print a warning if it is incompatible. Also print some information about the given chain while we are at it
9697
* `query-validators` — Show the current set of validators for a chain. Also print some information about the given chain while we are at it
98+
* `query-shard-info` — Query validators for shard information about a specific chain
9799
* `sync-validator` — Synchronizes a validator with the local state of chains
98100
* `sync-all-validators` — Synchronizes all validators with the local state of chains
99101
* `set-validator` — Add or modify a validator (admin only)
@@ -494,6 +496,18 @@ Show the current set of validators for a chain. Also print some information abou
494496

495497

496498

499+
## `linera query-shard-info`
500+
501+
Query validators for shard information about a specific chain
502+
503+
**Usage:** `linera query-shard-info <CHAIN_ID>`
504+
505+
###### **Arguments:**
506+
507+
* `<CHAIN_ID>` — The chain to query shard information for
508+
509+
510+
497511
## `linera sync-validator`
498512

499513
Synchronizes a validator with the local state of chains

linera-core/src/data_types.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,16 @@ pub struct ChainInfoResponse {
238238
pub signature: Option<ValidatorSignature>,
239239
}
240240

241+
/// Information about shard allocation for a chain.
242+
#[derive(Clone, Debug, Serialize, Deserialize)]
243+
#[cfg_attr(with_testing, derive(Eq, PartialEq))]
244+
pub struct ShardInfo {
245+
/// The shard ID that will process this chain.
246+
pub shard_id: usize,
247+
/// The total number of shards in the validator.
248+
pub total_shards: usize,
249+
}
250+
241251
/// An internal request between chains within a validator.
242252
#[derive(Clone, Debug, Serialize, Deserialize)]
243253
#[cfg_attr(with_testing, derive(Eq, PartialEq))]

linera-core/src/node.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,12 @@ pub trait ValidatorNode {
163163

164164
/// Returns the missing `Blob`s by their IDs.
165165
async fn missing_blob_ids(&self, blob_ids: Vec<BlobId>) -> Result<Vec<BlobId>, NodeError>;
166+
167+
/// Gets shard information for a specific chain.
168+
async fn get_shard_info(
169+
&self,
170+
chain_id: ChainId,
171+
) -> Result<crate::data_types::ShardInfo, NodeError>;
166172
}
167173

168174
/// Turn an address into a validator node.

linera-core/src/unit_tests/test_utils.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,17 @@ where
272272
})
273273
.await
274274
}
275+
276+
async fn get_shard_info(
277+
&self,
278+
_chain_id: ChainId,
279+
) -> Result<crate::data_types::ShardInfo, NodeError> {
280+
// For test purposes, return a dummy shard info
281+
Ok(crate::data_types::ShardInfo {
282+
shard_id: 0,
283+
total_shards: 1,
284+
})
285+
}
275286
}
276287

277288
impl<S> LocalValidatorClient<S>

linera-rpc/proto/rpc.proto

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ service ValidatorNode {
6666
// Request the network description seen by this node.
6767
rpc GetNetworkDescription(google.protobuf.Empty) returns (NetworkDescription);
6868

69+
// Request shard information for a specific chain.
70+
rpc GetShardInfo(ChainId) returns (ShardInfo);
71+
6972
// Download a blob.
7073
rpc DownloadBlob(BlobId) returns (BlobContent);
7174

@@ -156,6 +159,12 @@ message NetworkDescription {
156159
CryptoHash genesis_committee_blob_hash = 5;
157160
}
158161

162+
// Information about shard configuration for a specific chain.
163+
message ShardInfo {
164+
uint64 shard_id = 1;
165+
uint64 total_shards = 2;
166+
}
167+
159168
// A request for client to subscribe to notifications for a given `ChainId`
160169
message SubscriptionRequest {
161170
repeated ChainId chain_ids = 1;

linera-rpc/src/client.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,4 +298,16 @@ impl ValidatorNode for Client {
298298
Client::Simple(simple_client) => simple_client.missing_blob_ids(blob_ids).await?,
299299
})
300300
}
301+
302+
async fn get_shard_info(
303+
&self,
304+
chain_id: ChainId,
305+
) -> Result<linera_core::data_types::ShardInfo, NodeError> {
306+
Ok(match self {
307+
Client::Grpc(grpc_client) => grpc_client.get_shard_info(chain_id).await?,
308+
309+
#[cfg(with_simple_network)]
310+
Client::Simple(simple_client) => simple_client.get_shard_info(chain_id).await?,
311+
})
312+
}
301313
}

linera-rpc/src/grpc/client.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,4 +497,16 @@ impl ValidatorNode for GrpcClient {
497497
async fn missing_blob_ids(&self, blob_ids: Vec<BlobId>) -> Result<Vec<BlobId>, NodeError> {
498498
Ok(client_delegate!(self, missing_blob_ids, blob_ids)?.try_into()?)
499499
}
500+
501+
#[instrument(target = "grpc_client", skip(self), err(level = Level::WARN), fields(address = self.address))]
502+
async fn get_shard_info(
503+
&self,
504+
chain_id: ChainId,
505+
) -> Result<linera_core::data_types::ShardInfo, NodeError> {
506+
let response = client_delegate!(self, get_shard_info, chain_id)?;
507+
Ok(linera_core::data_types::ShardInfo {
508+
shard_id: response.shard_id as usize,
509+
total_shards: response.total_shards as usize,
510+
})
511+
}
500512
}

linera-rpc/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub mod simple;
2020
pub mod grpc;
2121

2222
pub use client::Client;
23-
pub use message::RpcMessage;
23+
pub use message::{RpcMessage, ShardInfo};
2424
pub use node_provider::{NodeOptions, NodeProvider};
2525

2626
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]

linera-rpc/src/message.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,20 @@ use linera_version::VersionInfo;
1919
use serde::{Deserialize, Serialize};
2020

2121
use crate::{
22-
HandleConfirmedCertificateRequest, HandleLiteCertRequest, HandleTimeoutCertificateRequest,
23-
HandleValidatedCertificateRequest,
22+
config::ShardId, HandleConfirmedCertificateRequest, HandleLiteCertRequest,
23+
HandleTimeoutCertificateRequest, HandleValidatedCertificateRequest,
2424
};
2525

26+
/// Information about shard configuration for a specific chain.
27+
#[derive(Clone, Serialize, Deserialize, Debug)]
28+
#[cfg_attr(with_testing, derive(Eq, PartialEq))]
29+
pub struct ShardInfo {
30+
/// The ID of the shard assigned to the chain.
31+
pub shard_id: ShardId,
32+
/// The total number of shards in the validator network.
33+
pub total_shards: usize,
34+
}
35+
2636
#[derive(Clone, Serialize, Deserialize, Debug)]
2737
#[cfg_attr(with_testing, derive(Eq, PartialEq))]
2838
pub enum RpcMessage {
@@ -65,6 +75,8 @@ pub enum RpcMessage {
6575

6676
BlobLastUsedByCertificate(Box<BlobId>),
6777
BlobLastUsedByCertificateResponse(Box<ConfirmedBlockCertificate>),
78+
ShardInfoQuery(ChainId),
79+
ShardInfoResponse(ShardInfo),
6880
}
6981

7082
impl RpcMessage {
@@ -85,6 +97,7 @@ impl RpcMessage {
8597
DownloadPendingBlob(request) => request.0,
8698
DownloadCertificatesByHeights(chain_id, _) => *chain_id,
8799
HandlePendingBlob(request) => request.0,
100+
ShardInfoQuery(chain_id) => *chain_id,
88101
Vote(_)
89102
| Error(_)
90103
| ChainInfoResponse(_)
@@ -107,6 +120,7 @@ impl RpcMessage {
107120
| BlobLastUsedByCertificateResponse(_)
108121
| MissingBlobIds(_)
109122
| MissingBlobIdsResponse(_)
123+
| ShardInfoResponse(_)
110124
| DownloadCertificatesResponse(_) => {
111125
return None;
112126
}
@@ -123,6 +137,7 @@ impl RpcMessage {
123137
match self {
124138
VersionInfoQuery
125139
| NetworkDescriptionQuery
140+
| ShardInfoQuery(_)
126141
| UploadBlob(_)
127142
| DownloadBlob(_)
128143
| DownloadConfirmedBlock(_)
@@ -143,6 +158,7 @@ impl RpcMessage {
143158
| ChainInfoResponse(_)
144159
| VersionInfoResponse(_)
145160
| NetworkDescriptionResponse(_)
161+
| ShardInfoResponse(_)
146162
| UploadBlobResponse(_)
147163
| DownloadPendingBlob(_)
148164
| DownloadPendingBlobResponse(_)
@@ -269,6 +285,17 @@ impl TryFrom<RpcMessage> for BlobId {
269285
}
270286
}
271287

288+
impl TryFrom<RpcMessage> for ShardInfo {
289+
type Error = NodeError;
290+
fn try_from(message: RpcMessage) -> Result<Self, Self::Error> {
291+
match message {
292+
RpcMessage::ShardInfoResponse(shard_info) => Ok(shard_info),
293+
RpcMessage::Error(error) => Err(*error),
294+
_ => Err(NodeError::UnexpectedMessage),
295+
}
296+
}
297+
}
298+
272299
impl From<NodeError> for RpcMessage {
273300
fn from(error: NodeError) -> Self {
274301
RpcMessage::Error(Box::new(error))

linera-rpc/src/simple/client.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,4 +259,16 @@ impl ValidatorNode for SimpleClient {
259259
async fn missing_blob_ids(&self, blob_ids: Vec<BlobId>) -> Result<Vec<BlobId>, NodeError> {
260260
self.query(RpcMessage::MissingBlobIds(blob_ids)).await
261261
}
262+
263+
async fn get_shard_info(
264+
&self,
265+
chain_id: ChainId,
266+
) -> Result<linera_core::data_types::ShardInfo, NodeError> {
267+
let rpc_shard_info: crate::message::ShardInfo =
268+
self.query(RpcMessage::ShardInfoQuery(chain_id)).await?;
269+
Ok(linera_core::data_types::ShardInfo {
270+
shard_id: rpc_shard_info.shard_id,
271+
total_shards: rpc_shard_info.total_shards,
272+
})
273+
}
262274
}

0 commit comments

Comments
 (0)