Skip to content

Commit dbeb3e3

Browse files
authored
Use ChainClientOptions in more places. (#4051)
## Motivation Clippy rightly thinks that `Client::new` has `too_many_arguments`. ## Proposal Use `ChainClientOptions` instead of passing in individual parameters. ## Test Plan CI ## Release Plan - Nothing to do / These changes follow the usual release cycle. ## Links - [reviewer checklist](https://github.com/linera-io/linera-protocol/blob/main/CONTRIBUTING.md#reviewer-checklist)
1 parent af51607 commit dbeb3e3

File tree

5 files changed

+79
-87
lines changed

5 files changed

+79
-87
lines changed

linera-client/src/client_context.rs

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ use linera_base::{
1515
};
1616
use linera_chain::types::ConfirmedBlockCertificate;
1717
use linera_core::{
18-
client::{ChainClient, Client, MessagePolicy},
18+
client::{ChainClient, Client},
1919
data_types::{ChainInfoQuery, ClientOutcome},
2020
join_set_ext::JoinSet,
21-
node::{CrossChainMessageDelivery, ValidatorNode},
21+
node::ValidatorNode,
2222
Environment, JoinSetExt as _,
2323
};
2424
use linera_persistent::{Persist, PersistExt as _};
@@ -119,7 +119,6 @@ where
119119
retry_delay: options.retry_delay,
120120
max_retries: options.max_retries,
121121
});
122-
let delivery = CrossChainMessageDelivery::new(options.wait_for_outgoing_messages);
123122
let chain_ids = wallet.chain_ids();
124123
let name = match chain_ids.len() {
125124
0 => "Client node".to_string(),
@@ -132,19 +131,12 @@ where
132131
storage,
133132
signer,
134133
},
135-
options.max_pending_message_bundles,
136134
wallet.genesis_admin_chain(),
137-
MessagePolicy::new(
138-
options.blanket_message_policy,
139-
options.restrict_chain_ids_to,
140-
),
141-
delivery,
142135
options.long_lived_services,
143136
chain_ids,
144137
name,
145138
options.max_loaded_chains,
146-
options.grace_period,
147-
options.blob_download_timeout,
139+
options.to_chain_client_options(),
148140
);
149141

150142
ClientContext {
@@ -160,7 +152,7 @@ where
160152

161153
#[cfg(with_testing)]
162154
pub fn new_test_client_context(storage: S, wallet: W, signer: Si) -> Self {
163-
use linera_core::DEFAULT_GRACE_PERIOD;
155+
use linera_core::{client::ChainClientOptions, node::CrossChainMessageDelivery};
164156

165157
let send_recv_timeout = Duration::from_millis(4000);
166158
let retry_delay = Duration::from_millis(1000);
@@ -172,7 +164,6 @@ where
172164
retry_delay,
173165
max_retries,
174166
};
175-
let delivery = CrossChainMessageDelivery::new(true);
176167
let chain_ids = wallet.chain_ids();
177168
let name = match chain_ids.len() {
178169
0 => "Client node".to_string(),
@@ -185,16 +176,15 @@ where
185176
network: NodeProvider::new(node_options),
186177
signer,
187178
},
188-
10,
189179
wallet.genesis_admin_chain(),
190-
MessagePolicy::new_accept_all(),
191-
delivery,
192180
false,
193181
chain_ids,
194182
name,
195183
NonZeroUsize::new(20).expect("Chain worker limit should not be zero"),
196-
DEFAULT_GRACE_PERIOD,
197-
Duration::from_secs(1),
184+
ChainClientOptions {
185+
cross_chain_message_delivery: CrossChainMessageDelivery::Blocking,
186+
..ChainClientOptions::test_default()
187+
},
198188
);
199189

200190
ClientContext {

linera-client/src/client_options.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ use linera_base::{
99
ownership::{ChainOwnership, TimeoutConfig},
1010
time::Duration,
1111
};
12-
use linera_core::{client::BlanketMessagePolicy, DEFAULT_GRACE_PERIOD};
12+
use linera_core::{
13+
client::{BlanketMessagePolicy, ChainClientOptions, MessagePolicy},
14+
node::CrossChainMessageDelivery,
15+
DEFAULT_GRACE_PERIOD,
16+
};
1317
use linera_execution::ResourceControlPolicy;
1418

1519
use crate::util;
@@ -112,6 +116,25 @@ pub struct ClientContextOptions {
112116
pub blob_download_timeout: Duration,
113117
}
114118

119+
impl ClientContextOptions {
120+
/// Creates [`ChainClientOptions`] with the corresponding values.
121+
pub fn to_chain_client_options(&self) -> ChainClientOptions {
122+
let message_policy = MessagePolicy::new(
123+
self.blanket_message_policy,
124+
self.restrict_chain_ids_to.clone(),
125+
);
126+
let cross_chain_message_delivery =
127+
CrossChainMessageDelivery::new(self.wait_for_outgoing_messages);
128+
ChainClientOptions {
129+
max_pending_message_bundles: self.max_pending_message_bundles,
130+
message_policy,
131+
cross_chain_message_delivery,
132+
grace_period: self.grace_period,
133+
blob_download_timeout: self.blob_download_timeout,
134+
}
135+
}
136+
}
137+
115138
#[derive(Debug, Clone, clap::Args)]
116139
pub struct ChainOwnershipConfig {
117140
/// The new super owners.

linera-client/src/unit_tests/chain_listener.rs

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,9 @@ use linera_base::{
1313
ownership::{ChainOwnership, TimeoutConfig},
1414
};
1515
use linera_core::{
16-
client::{ChainClient, Client, MessagePolicy},
16+
client::{ChainClient, ChainClientOptions, Client},
1717
environment,
18-
node::CrossChainMessageDelivery,
1918
test_utils::{MemoryStorageBuilder, StorageBuilder as _, TestBuilder},
20-
DEFAULT_GRACE_PERIOD,
2119
};
2220
use linera_execution::system::Recipient;
2321
use linera_storage::Storage;
@@ -102,7 +100,6 @@ async fn test_chain_listener() -> anyhow::Result<()> {
102100
let genesis_config = make_genesis_config(&builder);
103101
let admin_id = genesis_config.admin_id();
104102
let storage = builder.make_storage().await?;
105-
let delivery = CrossChainMessageDelivery::NonBlocking;
106103

107104
let mut context = ClientContext {
108105
wallet: Wallet::new(genesis_config),
@@ -112,16 +109,12 @@ async fn test_chain_listener() -> anyhow::Result<()> {
112109
network: builder.make_node_provider(),
113110
signer,
114111
},
115-
10,
116112
admin_id,
117-
MessagePolicy::new_accept_all(),
118-
delivery,
119113
false,
120114
[chain_id0],
121115
format!("Client node for {:.8}", chain_id0),
122116
NonZeroUsize::new(20).expect("Chain worker LRU cache size must be non-zero"),
123-
DEFAULT_GRACE_PERIOD,
124-
Duration::from_secs(1),
117+
ChainClientOptions::test_default(),
125118
)),
126119
};
127120
context
@@ -191,7 +184,6 @@ async fn test_chain_listener_admin_chain() -> anyhow::Result<()> {
191184
let genesis_config = make_genesis_config(&builder);
192185
let admin_id = genesis_config.admin_id();
193186
let storage = builder.make_storage().await?;
194-
let delivery = CrossChainMessageDelivery::NonBlocking;
195187

196188
let context = ClientContext {
197189
wallet: Wallet::new(genesis_config),
@@ -201,16 +193,12 @@ async fn test_chain_listener_admin_chain() -> anyhow::Result<()> {
201193
network: builder.make_node_provider(),
202194
signer,
203195
},
204-
10,
205196
admin_id,
206-
MessagePolicy::new_accept_all(),
207-
delivery,
208197
false,
209198
[],
210199
"Client node with no chains".to_string(),
211200
NonZeroUsize::new(20).expect("Chain worker LRU cache size must be non-zero"),
212-
DEFAULT_GRACE_PERIOD,
213-
Duration::from_secs(1),
201+
ChainClientOptions::test_default(),
214202
)),
215203
};
216204
let context = Arc::new(Mutex::new(context));

linera-core/src/client/mod.rs

Lines changed: 42 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -149,17 +149,8 @@ pub struct Client<Env: Environment> {
149149
/// Local node to manage the execution state and the local storage of the chains that we are
150150
/// tracking.
151151
local_node: LocalNodeClient<Env::Storage>,
152-
/// Maximum number of pending message bundles processed at a time in a block.
153-
max_pending_message_bundles: usize,
154-
/// The policy for automatically handling incoming messages.
155-
message_policy: MessagePolicy,
156152
/// The admin chain ID.
157153
admin_id: ChainId,
158-
/// Whether to block on cross-chain message delivery.
159-
cross_chain_message_delivery: CrossChainMessageDelivery,
160-
/// An additional delay, after reaching a quorum, to wait for additional validator signatures,
161-
/// as a fraction of time taken to reach quorum.
162-
grace_period: f64,
163154
/// Chains that should be tracked by the client.
164155
// TODO(#2412): Merge with set of chains the client is receiving notifications from validators
165156
tracked_chains: Arc<RwLock<HashSet<ChainId>>>,
@@ -169,26 +160,21 @@ pub struct Client<Env: Environment> {
169160
chains: DashMap<ChainId, ChainClientState>,
170161
/// The maximum active chain workers.
171162
max_loaded_chains: NonZeroUsize,
172-
/// The delay when downloading a blob, after which we try a second validator.
173-
blob_download_timeout: Duration,
163+
/// Configuration options.
164+
options: ChainClientOptions,
174165
}
175166

176167
impl<Env: Environment> Client<Env> {
177168
/// Creates a new `Client` with a new cache and notifiers.
178-
#[expect(clippy::too_many_arguments)]
179169
#[instrument(level = "trace", skip_all)]
180170
pub fn new(
181171
environment: Env,
182-
max_pending_message_bundles: usize,
183172
admin_id: ChainId,
184-
message_policy: MessagePolicy,
185-
cross_chain_message_delivery: CrossChainMessageDelivery,
186173
long_lived_services: bool,
187174
tracked_chains: impl IntoIterator<Item = ChainId>,
188175
name: impl Into<String>,
189176
max_loaded_chains: NonZeroUsize,
190-
grace_period: f64,
191-
blob_download_timeout: Duration,
177+
options: ChainClientOptions,
192178
) -> Self {
193179
let tracked_chains = Arc::new(RwLock::new(tracked_chains.into_iter().collect()));
194180
let state = WorkerState::new_for_client(
@@ -206,15 +192,11 @@ impl<Env: Environment> Client<Env> {
206192
environment,
207193
local_node,
208194
chains: DashMap::new(),
209-
max_pending_message_bundles,
210195
admin_id,
211-
message_policy,
212-
cross_chain_message_delivery,
213-
grace_period,
214196
tracked_chains,
215197
notifier: Arc::new(ChannelNotifier::default()),
216198
max_loaded_chains,
217-
blob_download_timeout,
199+
options,
218200
}
219201
}
220202

@@ -267,13 +249,7 @@ impl<Env: Environment> Client<Env> {
267249
ChainClient {
268250
client: self.clone(),
269251
chain_id,
270-
options: ChainClientOptions {
271-
max_pending_message_bundles: self.max_pending_message_bundles,
272-
message_policy: self.message_policy.clone(),
273-
cross_chain_message_delivery: self.cross_chain_message_delivery,
274-
grace_period: self.grace_period,
275-
blob_download_timeout: self.blob_download_timeout,
276-
},
252+
options: self.options.clone(),
277253
preferred_owner,
278254
initial_block_hash: block_hash,
279255
initial_next_block_height: next_block_height,
@@ -292,10 +268,13 @@ impl<Env: Environment> Client<Env> {
292268
// If the chain is missing then the error is a WorkerError
293269
// and so a BlobsNotFound
294270
// TODO(#2351): make sure the blobs are legitimate!
295-
let blobs =
296-
RemoteNode::download_blobs(&blob_ids, validators, self.blob_download_timeout)
297-
.await
298-
.ok_or(LocalNodeError::BlobsNotFound(blob_ids))?;
271+
let blobs = RemoteNode::download_blobs(
272+
&blob_ids,
273+
validators,
274+
self.options.blob_download_timeout,
275+
)
276+
.await
277+
.ok_or(LocalNodeError::BlobsNotFound(blob_ids))?;
299278
self.local_node.storage_client().write_blobs(&blobs).await?;
300279
self.local_node.chain_info(chain_id).await
301280
}
@@ -484,9 +463,10 @@ impl<Env: Environment> Client<Env> {
484463
// Recover history from the current validators, according to the admin chain.
485464
// TODO(#2351): make sure that the blob is legitimately created!
486465
let nodes = self.validator_nodes().await?;
487-
let blob = RemoteNode::download_blob(&nodes, chain_desc_id, self.blob_download_timeout)
488-
.await
489-
.ok_or(LocalNodeError::BlobsNotFound(vec![chain_desc_id]))?;
466+
let blob =
467+
RemoteNode::download_blob(&nodes, chain_desc_id, self.options.blob_download_timeout)
468+
.await
469+
.ok_or(LocalNodeError::BlobsNotFound(vec![chain_desc_id]))?;
490470
self.local_node.storage_client().write_blob(&blob).await?;
491471
Ok(blob)
492472
}
@@ -521,7 +501,7 @@ impl<Env: Environment> Client<Env> {
521501
let hashed_value = ConfirmedBlock::new(certificate.inner().block().clone());
522502
let finalize_action = CommunicateAction::FinalizeBlock {
523503
certificate: Box::new(certificate),
524-
delivery: self.cross_chain_message_delivery,
504+
delivery: self.options.cross_chain_message_delivery,
525505
};
526506
let certificate = self
527507
.communicate_chain_action(committee, finalize_action, hashed_value)
@@ -587,7 +567,7 @@ impl<Env: Environment> Client<Env> {
587567
.await
588568
})
589569
},
590-
self.grace_period,
570+
self.options.grace_period,
591571
)
592572
.await?;
593573
Ok(())
@@ -622,7 +602,7 @@ impl<Env: Environment> Client<Env> {
622602
let action = action.clone();
623603
Box::pin(async move { updater.send_chain_update(action).await })
624604
},
625-
self.grace_period,
605+
self.options.grace_period,
626606
)
627607
.await?;
628608
ensure!(
@@ -715,10 +695,13 @@ impl<Env: Environment> Client<Env> {
715695
if let Err(err) = self.process_certificate(certificate.clone()).await {
716696
match &err {
717697
LocalNodeError::BlobsNotFound(blob_ids) => {
718-
let blobs =
719-
RemoteNode::download_blobs(blob_ids, &nodes, self.blob_download_timeout)
720-
.await
721-
.ok_or(err)?;
698+
let blobs = RemoteNode::download_blobs(
699+
blob_ids,
700+
&nodes,
701+
self.options.blob_download_timeout,
702+
)
703+
.await
704+
.ok_or(err)?;
722705
self.local_node.store_blobs(&blobs).await?;
723706
self.process_certificate(certificate).await?;
724707
}
@@ -933,7 +916,7 @@ impl<Env: Environment> Client<Env> {
933916
self.try_synchronize_chain_state_from(&remote_node, chain_id)
934917
.await
935918
},
936-
self.grace_period,
919+
self.options.grace_period,
937920
)
938921
.await?;
939922

@@ -1294,7 +1277,6 @@ impl MessagePolicy {
12941277
}
12951278
}
12961279

1297-
#[non_exhaustive]
12981280
#[derive(Debug, Clone)]
12991281
pub struct ChainClientOptions {
13001282
/// Maximum number of pending message bundles processed at a time in a block.
@@ -1310,6 +1292,21 @@ pub struct ChainClientOptions {
13101292
pub blob_download_timeout: Duration,
13111293
}
13121294

1295+
#[cfg(with_testing)]
1296+
impl ChainClientOptions {
1297+
pub fn test_default() -> Self {
1298+
use crate::DEFAULT_GRACE_PERIOD;
1299+
1300+
ChainClientOptions {
1301+
max_pending_message_bundles: 10,
1302+
message_policy: MessagePolicy::new_accept_all(),
1303+
cross_chain_message_delivery: CrossChainMessageDelivery::NonBlocking,
1304+
grace_period: DEFAULT_GRACE_PERIOD,
1305+
blob_download_timeout: Duration::from_secs(1),
1306+
}
1307+
}
1308+
}
1309+
13131310
/// Client to operate a chain by interacting with validators and the given local storage
13141311
/// implementation.
13151312
/// * The chain being operated is called the "local chain" or just the "chain".

0 commit comments

Comments
 (0)