Skip to content

Commit 44e6312

Browse files
Add epoch to the UserChain and linera wallet show (#4458)
## Motivation The `linera wallet show` presents the data on the chain being tracked. Other information can be added easily. Fixes #2958 ## Proposal The `epoch` is always present in the output of `chain_info_query`. So, it can be added to the `UserChain` easily. Possible extension: * Adding if a chain is closed or not (it suffices to add a boolean to `ChainInfo`). ## Test Plan The readme test case fungible which is the only one with `linera wallet show` has been ## Release Plan - Nothing to do / These changes follow the usual release cycle. ## Links None.
1 parent 8a47278 commit 44e6312

File tree

9 files changed

+58
-21
lines changed

9 files changed

+58
-21
lines changed

linera-client/src/chain_listener.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use futures::{
1414
};
1515
use linera_base::{
1616
crypto::{CryptoHash, Signer},
17-
data_types::{ChainDescription, Timestamp},
17+
data_types::{ChainDescription, Epoch, Timestamp},
1818
identifiers::{AccountOwner, BlobType, ChainId},
1919
task::NonBlockingFuture,
2020
};
@@ -107,6 +107,7 @@ pub trait ClientContext {
107107
chain_id: ChainId,
108108
owner: Option<AccountOwner>,
109109
timestamp: Timestamp,
110+
epoch: Epoch,
110111
) -> Result<(), Error>;
111112

112113
async fn update_wallet(&mut self, client: &ContextChainClient<Self>) -> Result<(), Error>;
@@ -339,6 +340,7 @@ impl<C: ClientContext> ChainListener<C> {
339340
new_chain_id,
340341
Some(chain_owner),
341342
block.header.timestamp,
343+
block.header.epoch,
342344
)
343345
.await?;
344346
new_ids.insert(new_chain_id, ListeningMode::FullChain);

linera-client/src/client_context.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::sync::Arc;
66
use futures::Future;
77
use linera_base::{
88
crypto::{CryptoHash, ValidatorPublicKey},
9-
data_types::{BlockHeight, Timestamp},
9+
data_types::{BlockHeight, Epoch, Timestamp},
1010
identifiers::{Account, AccountOwner, ChainId},
1111
ownership::ChainOwnership,
1212
time::{Duration, Instant},
@@ -107,8 +107,9 @@ where
107107
chain_id: ChainId,
108108
owner: Option<AccountOwner>,
109109
timestamp: Timestamp,
110+
epoch: Epoch,
110111
) -> Result<(), Error> {
111-
self.update_wallet_for_new_chain(chain_id, owner, timestamp)
112+
self.update_wallet_for_new_chain(chain_id, owner, timestamp, epoch)
112113
.await
113114
}
114115

@@ -306,6 +307,7 @@ impl<Env: Environment, W: Persist<Target = Wallet>> ClientContext<Env, W> {
306307
chain_id: ChainId,
307308
owner: Option<AccountOwner>,
308309
timestamp: Timestamp,
310+
epoch: Epoch,
309311
) -> Result<(), Error> {
310312
if self.wallet.get(chain_id).is_none() {
311313
self.mutate_wallet(|w| {
@@ -316,6 +318,7 @@ impl<Env: Environment, W: Persist<Target = Wallet>> ClientContext<Env, W> {
316318
timestamp,
317319
next_block_height: BlockHeight::ZERO,
318320
pending_proposal: None,
321+
epoch: Some(epoch),
319322
})
320323
})
321324
.await?;
@@ -388,7 +391,14 @@ impl<Env: Environment, W: Persist<Target = Wallet>> ClientContext<Env, W> {
388391
}
389392

390393
self.wallet_mut()
391-
.mutate(|w| w.assign_new_chain_to_owner(owner, chain_id, chain_description.timestamp()))
394+
.mutate(|w| {
395+
w.assign_new_chain_to_owner(
396+
owner,
397+
chain_id,
398+
chain_description.timestamp(),
399+
chain_description.config().epoch,
400+
)
401+
})
392402
.await
393403
.map_err(|e| error::Inner::Persistence(Box::new(e)))?
394404
.context("assigning new chain")?;

linera-client/src/unit_tests/chain_listener.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::{sync::Arc, time::Duration};
88
use futures::{lock::Mutex, FutureExt as _};
99
use linera_base::{
1010
crypto::{AccountPublicKey, InMemorySigner},
11-
data_types::{Amount, BlockHeight, TimeDelta, Timestamp},
11+
data_types::{Amount, BlockHeight, Epoch, TimeDelta, Timestamp},
1212
identifiers::{Account, AccountOwner, ChainId},
1313
ownership::{ChainOwnership, TimeoutConfig},
1414
};
@@ -58,6 +58,7 @@ impl chain_listener::ClientContext for ClientContext {
5858
chain_id: ChainId,
5959
owner: Option<AccountOwner>,
6060
timestamp: Timestamp,
61+
epoch: Epoch,
6162
) -> Result<(), Error> {
6263
if self.wallet.get(chain_id).is_none() {
6364
self.wallet.insert(UserChain {
@@ -67,6 +68,7 @@ impl chain_listener::ClientContext for ClientContext {
6768
timestamp,
6869
next_block_height: BlockHeight::ZERO,
6970
pending_proposal: None,
71+
epoch: Some(epoch),
7072
});
7173
}
7274

@@ -105,6 +107,8 @@ async fn test_chain_listener() -> anyhow::Result<()> {
105107
let genesis_config = make_genesis_config(&builder);
106108
let admin_id = genesis_config.admin_id();
107109
let storage = builder.make_storage().await?;
110+
let epoch0 = client0.chain_info().await?.epoch;
111+
let epoch1 = client1.chain_info().await?.epoch;
108112

109113
let mut context = ClientContext {
110114
wallet: Wallet::new(genesis_config),
@@ -123,13 +127,14 @@ async fn test_chain_listener() -> anyhow::Result<()> {
123127
)),
124128
};
125129
context
126-
.update_wallet_for_new_chain(chain_id0, Some(owner), clock.current_time())
130+
.update_wallet_for_new_chain(chain_id0, Some(owner), clock.current_time(), epoch0)
127131
.await?;
128132
context
129133
.update_wallet_for_new_chain(
130134
client1.chain_id(),
131135
client1.preferred_owner(),
132136
clock.current_time(),
137+
epoch1,
133138
)
134139
.await?;
135140

linera-client/src/wallet.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::{collections::BTreeMap, iter::IntoIterator};
55

66
use linera_base::{
77
crypto::CryptoHash,
8-
data_types::{BlockHeight, ChainDescription, Timestamp},
8+
data_types::{BlockHeight, ChainDescription, Epoch, Timestamp},
99
ensure,
1010
identifiers::{AccountOwner, ChainId},
1111
};
@@ -109,6 +109,7 @@ impl Wallet {
109109
owner: AccountOwner,
110110
chain_id: ChainId,
111111
timestamp: Timestamp,
112+
epoch: Epoch,
112113
) -> Result<(), Error> {
113114
let user_chain = UserChain {
114115
chain_id,
@@ -117,6 +118,7 @@ impl Wallet {
117118
timestamp,
118119
next_block_height: BlockHeight(0),
119120
pending_proposal: None,
121+
epoch: Some(epoch),
120122
};
121123
self.insert(user_chain);
122124
Ok(())
@@ -144,6 +146,7 @@ impl Wallet {
144146
next_block_height: info.next_block_height,
145147
timestamp: info.timestamp,
146148
pending_proposal,
149+
epoch: Some(info.epoch),
147150
});
148151
}
149152

@@ -165,6 +168,7 @@ pub struct UserChain {
165168
pub timestamp: Timestamp,
166169
pub next_block_height: BlockHeight,
167170
pub pending_proposal: Option<PendingProposal>,
171+
pub epoch: Option<Epoch>,
168172
}
169173

170174
impl Clone for UserChain {
@@ -176,6 +180,7 @@ impl Clone for UserChain {
176180
timestamp: self.timestamp,
177181
next_block_height: self.next_block_height,
178182
pending_proposal: self.pending_proposal.clone(),
183+
epoch: self.epoch,
179184
}
180185
}
181186
}
@@ -187,18 +192,20 @@ impl UserChain {
187192
description: ChainDescription,
188193
timestamp: Timestamp,
189194
) -> Self {
195+
let epoch = description.config().epoch;
190196
Self {
191197
chain_id: description.into(),
192198
owner: Some(owner),
193199
block_hash: None,
194200
timestamp,
195201
next_block_height: BlockHeight::ZERO,
196202
pending_proposal: None,
203+
epoch: Some(epoch),
197204
}
198205
}
199206

200207
/// Creates an entry for a chain that we don't own. The timestamp must be the genesis
201-
/// timestamp or earlier.
208+
/// timestamp or earlier. The Epoch is `None`.
202209
pub fn make_other(chain_id: ChainId, timestamp: Timestamp) -> Self {
203210
Self {
204211
chain_id,
@@ -207,6 +214,7 @@ impl UserChain {
207214
timestamp,
208215
next_block_height: BlockHeight::ZERO,
209216
pending_proposal: None,
217+
epoch: None,
210218
}
211219
}
212220
}

linera-faucet/server/src/tests.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::{collections::VecDeque, path::PathBuf, sync::Arc};
88
use futures::lock::Mutex;
99
use linera_base::{
1010
crypto::{AccountPublicKey, CryptoHash, InMemorySigner, TestString},
11-
data_types::{Amount, Timestamp},
11+
data_types::{Amount, Epoch, Timestamp},
1212
identifiers::{AccountOwner, ChainId},
1313
};
1414
use linera_client::{chain_listener, wallet::Wallet};
@@ -58,6 +58,7 @@ impl chain_listener::ClientContext for ClientContext {
5858
_: ChainId,
5959
_: Option<AccountOwner>,
6060
_: Timestamp,
61+
_: Epoch,
6162
) -> Result<(), linera_client::Error> {
6263
self.update_calls += 1;
6364
Ok(())

linera-service/src/cli/main.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,10 @@ impl Runnable for Job {
171171
.await
172172
.context("Failed to open chain")?;
173173
let timestamp = certificate.block().header.timestamp;
174+
let epoch = certificate.block().header.epoch;
174175
let id = description.id();
175176
context
176-
.update_wallet_for_new_chain(id, Some(new_owner), timestamp)
177+
.update_wallet_for_new_chain(id, Some(new_owner), timestamp, epoch)
177178
.await?;
178179
let time_total = time_start.elapsed();
179180
info!(
@@ -225,8 +226,9 @@ impl Runnable for Job {
225226
// No owner. This chain can be assigned explicitly using the assign command.
226227
let owner = None;
227228
let timestamp = certificate.block().header.timestamp;
229+
let epoch = certificate.block().header.epoch;
228230
context
229-
.update_wallet_for_new_chain(id, owner, timestamp)
231+
.update_wallet_for_new_chain(id, owner, timestamp, epoch)
230232
.await?;
231233
let time_total = time_start.elapsed();
232234
info!(
@@ -2162,7 +2164,7 @@ async fn run(options: &ClientOptions) -> Result<i32, Error> {
21622164
genesis_config.persist().await?;
21632165
options
21642166
.create_wallet(genesis_config.into_value())?
2165-
.mutate(|wallet| wallet.extend(chains))
2167+
.mutate(|w| w.extend(chains))
21662168
.await?;
21672169
options.initialize_storage().boxed().await?;
21682170
info!(
@@ -2323,20 +2325,21 @@ async fn run(options: &ClientOptions) -> Result<i32, Error> {
23232325
owned,
23242326
} => {
23252327
let start_time = Instant::now();
2328+
let wallet = options.wallet().await?;
23262329
let chain_ids = if let Some(chain_id) = chain_id {
23272330
ensure!(!owned, "Cannot specify both --owned and a chain ID");
23282331
vec![*chain_id]
23292332
} else if *owned {
2330-
options.wallet().await?.owned_chain_ids()
2333+
wallet.owned_chain_ids()
23312334
} else {
2332-
options.wallet().await?.chain_ids()
2335+
wallet.chain_ids()
23332336
};
23342337
if *short {
23352338
for chain_id in chain_ids {
23362339
println!("{chain_id}");
23372340
}
23382341
} else {
2339-
wallet::pretty_print(&*options.wallet().await?, chain_ids).await;
2342+
wallet::pretty_print(&wallet, chain_ids).await;
23402343
}
23412344
info!("Wallet shown in {} ms", start_time.elapsed().as_millis());
23422345
Ok(0)
@@ -2384,9 +2387,7 @@ async fn run(options: &ClientOptions) -> Result<i32, Error> {
23842387
options
23852388
.wallet()
23862389
.await?
2387-
.mutate(|wallet| {
2388-
wallet.extend([UserChain::make_other(*chain_id, Timestamp::now())])
2389-
})
2390+
.mutate(|w| w.extend([UserChain::make_other(*chain_id, Timestamp::now())]))
23902391
.await?;
23912392
if *sync {
23922393
options.run_with_storage(Job(options.clone())).await??;

linera-service/src/schema_export.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::sync::Arc;
55

66
use linera_base::{
77
crypto::CryptoHash,
8-
data_types::{BlobContent, BlockHeight, NetworkDescription, Timestamp},
8+
data_types::{BlobContent, BlockHeight, Epoch, NetworkDescription, Timestamp},
99
identifiers::{AccountOwner, BlobId, ChainId},
1010
};
1111
use linera_chain::{
@@ -212,6 +212,7 @@ impl ClientContext for DummyContext {
212212
_: ChainId,
213213
_: Option<AccountOwner>,
214214
_: Timestamp,
215+
_: Epoch,
215216
) -> Result<(), Error> {
216217
Ok(())
217218
}

linera-service/src/wallet.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub async fn pretty_print(wallet: &Wallet, chain_ids: impl IntoIterator<Item = C
1818
Cell::new("Chain ID").add_attribute(Attribute::Bold),
1919
Cell::new("Latest Block").add_attribute(Attribute::Bold),
2020
]);
21+
2122
for chain_id in chain_ids {
2223
let Some(user_chain) = wallet.chains.get(&chain_id) else {
2324
panic!("Chain {} not found.", chain_id);
@@ -39,19 +40,25 @@ async fn update_table_with_chain(
3940
user_chain: &UserChain,
4041
is_default_chain: bool,
4142
) {
43+
let epoch = user_chain.epoch;
4244
let chain_id_cell = if is_default_chain {
4345
Cell::new(format!("{}", chain_id)).fg(Color::Green)
4446
} else {
4547
Cell::new(format!("{}", chain_id))
4648
};
49+
let epoch_str = match epoch {
50+
None => "-".to_string(),
51+
Some(epoch) => format!("{}", epoch),
52+
};
4753
let account_owner = user_chain.owner;
4854
table.add_row(vec![
4955
chain_id_cell,
5056
Cell::new(format!(
5157
r#"AccountOwner: {}
5258
Block Hash: {}
5359
Timestamp: {}
54-
Next Block Height: {}"#,
60+
Next Block Height: {}
61+
Epoch: {}"#,
5562
account_owner
5663
.as_ref()
5764
.map(|o| o.to_string())
@@ -61,7 +68,8 @@ Next Block Height: {}"#,
6168
.map(|bh| bh.to_string())
6269
.unwrap_or_else(|| "-".to_string()),
6370
user_chain.timestamp,
64-
user_chain.next_block_height
71+
user_chain.next_block_height,
72+
epoch_str
6573
)),
6674
]);
6775
}

linera-web/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ impl JsFaucet {
140140
account_owner,
141141
description.id(),
142142
description.timestamp(),
143+
description.config().epoch,
143144
)
144145
})
145146
.await??;

0 commit comments

Comments
 (0)