Skip to content

Commit 26c1a99

Browse files
authored
[MFP] add the block list for tx submission for transaction driver (#24161)
## Description Adding support for the a transaction submission block list. For the configuration we can not have both an allow list and a block list - those are mutually exclusive configurations. ## Test plan CI --- ## Release notes Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required. For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates. - [ ] Protocol: - [ ] Nodes (Validators and Full nodes): - [ ] gRPC: - [ ] JSON-RPC: - [ ] GraphQL: - [ ] CLI: - [ ] Rust SDK:
1 parent 90e014f commit 26c1a99

File tree

6 files changed

+102
-12
lines changed

6 files changed

+102
-12
lines changed

crates/sui-config/src/node.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,11 @@ pub struct TransactionDriverConfig {
235235
#[serde(default, skip_serializing_if = "Vec::is_empty")]
236236
pub allowed_submission_validators: Vec<String>,
237237

238+
/// The list of validators that are blocked from submitting block transactions to (via the transaction driver).
239+
/// Each entry is a validator display name.
240+
#[serde(default, skip_serializing_if = "Vec::is_empty")]
241+
pub blocked_submission_validators: Vec<String>,
242+
238243
/// Enable early transaction validation before submission to consensus.
239244
/// This checks for non-retriable errors (like old object versions) and rejects
240245
/// transactions early to provide fast feedback to clients.
@@ -247,6 +252,7 @@ impl Default for TransactionDriverConfig {
247252
fn default() -> Self {
248253
Self {
249254
allowed_submission_validators: vec![],
255+
blocked_submission_validators: vec![],
250256
enable_early_validation: true,
251257
}
252258
}

crates/sui-core/src/transaction_driver/effects_certifier.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,13 @@ impl EffectsCertifier {
9999
}
100100
};
101101

102-
let mut retrier =
103-
RequestRetrier::new(authority_aggregator, client_monitor, tx_type, vec![]);
102+
let mut retrier = RequestRetrier::new(
103+
authority_aggregator,
104+
client_monitor,
105+
tx_type,
106+
vec![],
107+
vec![],
108+
);
104109
let ping_type = get_ping_type(&tx_digest, tx_type);
105110

106111
// Setting this to None at first because if the full effects are already provided,

crates/sui-core/src/transaction_driver/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ pub struct SubmitTransactionOptions {
5555
/// When submitting a transaction, only the validators in the allowed validator list can be used to submit the transaction to.
5656
/// When the allowed validator list is empty, any validator can be used.
5757
pub allowed_validators: Vec<String>,
58+
59+
/// When submitting a transaction, the validators in the blocked validator list cannot be used to submit the transaction to.
60+
/// When the blocked validator list is empty, no restrictions are applied.
61+
pub blocked_validators: Vec<String>,
5862
}
5963

6064
#[derive(Clone, Debug)]

crates/sui-core/src/transaction_driver/request_retrier.rs

Lines changed: 68 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ const SELECT_LATENCY_DELTA: f64 = 0.02;
2929
/// When an `allowed_validators` is provided, only the validators in the list will be used to submit the transaction to.
3030
/// When the allowed validator list is empty, any validator can be used an then the validators are selected based on their scores.
3131
///
32+
/// When a `blocked_validators` is provided, the validators in the list cannot be used to submit the transaction to.
33+
/// When the blocked validator list is empty, no restrictions are applied.
34+
///
3235
/// This component helps to manager this retry pattern.
3336
pub(crate) struct RequestRetrier<A: Clone> {
3437
ranked_clients: VecDeque<(AuthorityName, Arc<SafeClient<A>>)>,
@@ -42,6 +45,7 @@ impl<A: Clone> RequestRetrier<A> {
4245
client_monitor: &Arc<ValidatorClientMonitor<A>>,
4346
tx_type: TxType,
4447
allowed_validators: Vec<String>,
48+
blocked_validators: Vec<String>,
4549
) -> Self {
4650
let ranked_validators = client_monitor.select_shuffled_preferred_validators(
4751
&auth_agg.committee,
@@ -50,11 +54,14 @@ impl<A: Clone> RequestRetrier<A> {
5054
);
5155
let ranked_clients = ranked_validators
5256
.into_iter()
53-
.filter(|name| {
54-
let display_name = auth_agg.get_display_name(name);
55-
allowed_validators.is_empty() || allowed_validators.contains(&display_name)
57+
.map(|name| (name, auth_agg.get_display_name(&name)))
58+
.filter(|(_name, display_name)| {
59+
allowed_validators.is_empty() || allowed_validators.contains(display_name)
60+
})
61+
.filter(|(_name, display_name)| {
62+
blocked_validators.is_empty() || !blocked_validators.contains(display_name)
5663
})
57-
.filter_map(|name| {
64+
.filter_map(|(name, _display_name)| {
5865
// There is not guarantee that the `name` are in the `auth_agg.authority_clients` if those are coming from the list
5966
// of `allowed_validators`, as the provided `auth_agg` might have been updated with a new committee that doesn't contain the validator in question.
6067
auth_agg
@@ -167,8 +174,13 @@ mod tests {
167174
async fn test_next_target() {
168175
let auth_agg = Arc::new(get_authority_aggregator(4));
169176
let client_monitor = Arc::new(ValidatorClientMonitor::new_for_test(auth_agg.clone()));
170-
let mut retrier =
171-
RequestRetrier::new(&auth_agg, &client_monitor, TxType::SingleWriter, vec![]);
177+
let mut retrier = RequestRetrier::new(
178+
&auth_agg,
179+
&client_monitor,
180+
TxType::SingleWriter,
181+
vec![],
182+
vec![],
183+
);
172184

173185
for name in auth_agg.committee.names() {
174186
retrier.next_target().unwrap();
@@ -215,6 +227,7 @@ mod tests {
215227
&client_monitor,
216228
TxType::SingleWriter,
217229
allowed_validators,
230+
vec![],
218231
);
219232

220233
// Should only have 1 remaining client (the known validator)
@@ -234,13 +247,48 @@ mod tests {
234247
&client_monitor,
235248
TxType::SingleWriter,
236249
allowed_validators,
250+
vec![],
237251
);
238252

239253
// Should have no remaining clients since none of the allowed validators exist
240254
assert_eq!(retrier.ranked_clients.len(), 0);
241255
}
242256
}
243257

258+
#[tokio::test]
259+
async fn test_blocked_validators() {
260+
let auth_agg = Arc::new(get_authority_aggregator(4));
261+
let client_monitor = Arc::new(ValidatorClientMonitor::new_for_test(auth_agg.clone()));
262+
263+
// Create a list of validators that should be blocked and never picked up by the retrier.
264+
let blocked_validators = auth_agg
265+
.committee
266+
.names()
267+
.take(3)
268+
.copied()
269+
.collect::<Vec<_>>();
270+
let blocked_display_names = blocked_validators
271+
.iter()
272+
.map(|name| auth_agg.get_display_name(name))
273+
.collect::<Vec<_>>();
274+
275+
// Only the last validator will be picked up.
276+
let allowed_validator = auth_agg.committee.names().nth(3).unwrap();
277+
278+
let mut retrier = RequestRetrier::new(
279+
&auth_agg,
280+
&client_monitor,
281+
TxType::SingleWriter,
282+
vec![],
283+
blocked_display_names,
284+
);
285+
286+
// The last validator will be picked up.
287+
assert_eq!(retrier.next_target().unwrap().0, *allowed_validator);
288+
// No more validators will be picked up.
289+
assert!(retrier.next_target().is_err());
290+
}
291+
244292
#[tokio::test]
245293
async fn test_add_error() {
246294
let auth_agg = Arc::new(get_authority_aggregator(4));
@@ -249,8 +297,13 @@ mod tests {
249297
// Add retriable errors.
250298
{
251299
let client_monitor = Arc::new(ValidatorClientMonitor::new_for_test(auth_agg.clone()));
252-
let mut retrier =
253-
RequestRetrier::new(&auth_agg, &client_monitor, TxType::SingleWriter, vec![]);
300+
let mut retrier = RequestRetrier::new(
301+
&auth_agg,
302+
&client_monitor,
303+
TxType::SingleWriter,
304+
vec![],
305+
vec![],
306+
);
254307

255308
// 25% stake.
256309
retrier
@@ -286,8 +339,13 @@ mod tests {
286339
// Add mix of retriable and non-retriable errors.
287340
{
288341
let client_monitor = Arc::new(ValidatorClientMonitor::new_for_test(auth_agg.clone()));
289-
let mut retrier =
290-
RequestRetrier::new(&auth_agg, &client_monitor, TxType::SingleWriter, vec![]);
342+
let mut retrier = RequestRetrier::new(
343+
&auth_agg,
344+
&client_monitor,
345+
TxType::SingleWriter,
346+
vec![],
347+
vec![],
348+
);
291349

292350
// 25% stake retriable error.
293351
retrier

crates/sui-core/src/transaction_driver/transaction_submitter.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ impl TransactionSubmitter {
7171
client_monitor,
7272
tx_type,
7373
options.allowed_validators.clone(),
74+
options.blocked_validators.clone(),
7475
);
7576

7677
let ping_label = if request.ping_type.is_some() {

crates/sui-core/src/transaction_orchestrator.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ pub struct TransactionOrchestrator<A: Clone> {
7979
transaction_driver: Option<Arc<TransactionDriver<A>>>,
8080
td_percentage: u8,
8181
td_allowed_submission_list: Vec<String>,
82+
td_blocked_submission_list: Vec<String>,
8283
enable_early_validation: bool,
8384
}
8485

@@ -174,6 +175,19 @@ where
174175
.map(|config| config.allowed_submission_validators.clone())
175176
.unwrap_or_default();
176177

178+
let td_blocked_submission_list = node_config
179+
.transaction_driver_config
180+
.as_ref()
181+
.map(|config| config.blocked_submission_validators.clone())
182+
.unwrap_or_default();
183+
184+
if !td_allowed_submission_list.is_empty() && !td_blocked_submission_list.is_empty() {
185+
panic!(
186+
"Both allowed and blocked submission lists are set, this is not allowed, {:?} {:?}",
187+
td_allowed_submission_list, td_blocked_submission_list
188+
);
189+
}
190+
177191
let enable_early_validation = node_config
178192
.transaction_driver_config
179193
.as_ref()
@@ -190,6 +204,7 @@ where
190204
transaction_driver,
191205
td_percentage,
192206
td_allowed_submission_list,
207+
td_blocked_submission_list,
193208
enable_early_validation,
194209
}
195210
}
@@ -699,6 +714,7 @@ where
699714
SubmitTransactionOptions {
700715
forwarded_client_addr: client_addr,
701716
allowed_validators: self.td_allowed_submission_list.clone(),
717+
blocked_validators: self.td_blocked_submission_list.clone(),
702718
},
703719
timeout_duration,
704720
)

0 commit comments

Comments
 (0)