Skip to content

Commit a4005cd

Browse files
authored
No oracles in fast blocks; automatically propose a regular block if oracles. (#2977)
* Automatically propose a regular block if there is an oracle call. * Disallow all oracles in fast blocks. * Improve comment.
1 parent a7c3228 commit a4005cd

File tree

5 files changed

+38
-26
lines changed

5 files changed

+38
-26
lines changed

linera-base/src/data_types.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -761,13 +761,6 @@ pub enum OracleResponse {
761761
Assert,
762762
}
763763

764-
impl OracleResponse {
765-
/// Wether an `OracleResponse` is permitted in fast blocks or not.
766-
pub fn is_permitted_in_fast_blocks(&self) -> bool {
767-
matches!(self, OracleResponse::Blob(_))
768-
}
769-
}
770-
771764
impl Display for OracleResponse {
772765
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
773766
match self {

linera-chain/src/data_types.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,12 @@ impl BlockExecutionOutcome {
728728

729729
required_blob_ids
730730
}
731+
732+
pub fn has_oracle_responses(&self) -> bool {
733+
self.oracle_responses
734+
.iter()
735+
.any(|responses| !responses.is_empty())
736+
}
731737
}
732738

733739
/// The data a block proposer signs.

linera-core/src/chain_worker/state/temporary_changes.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -240,16 +240,10 @@ where
240240
.with_value(value)
241241
.ok_or_else(|| WorkerError::InvalidLiteCertificate)?;
242242
}
243-
if round.is_fast() {
244-
ensure!(
245-
outcome
246-
.oracle_responses
247-
.iter()
248-
.flatten()
249-
.all(|response| response.is_permitted_in_fast_blocks()),
250-
WorkerError::FastBlockUsingOracles
251-
);
252-
}
243+
ensure!(
244+
!round.is_fast() || !outcome.has_oracle_responses(),
245+
WorkerError::FastBlockUsingOracles
246+
);
253247
// Check if the counters of tip_state would be valid.
254248
self.0
255249
.chain

linera-core/src/client/mod.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2352,7 +2352,7 @@ where
23522352
};
23532353

23542354
let identity = self.identity().await?;
2355-
let round = match Self::round_for_new_proposal(&info, &identity, &executed_block.block)? {
2355+
let round = match Self::round_for_new_proposal(&info, &identity, &executed_block)? {
23562356
Either::Left(round) => round,
23572357
Either::Right(timeout) => return Ok(ClientOutcome::WaitForTimeout(timeout)),
23582358
};
@@ -2442,20 +2442,23 @@ where
24422442
fn round_for_new_proposal(
24432443
info: &ChainInfo,
24442444
identity: &Owner,
2445-
block: &Block,
2445+
executed_block: &ExecutedBlock,
24462446
) -> Result<Either<Round, RoundTimeout>, ChainClientError> {
2447+
let manager = &info.manager;
2448+
let block = &executed_block.block;
24472449
// If there is a conflicting proposal in the current round, we can only propose if the
24482450
// next round can be started without a timeout, i.e. if we are in a multi-leader round.
2449-
let manager = &info.manager;
2450-
let conflicting_proposal = manager.requested_proposed.as_ref().is_some_and(|proposal| {
2451+
// Similarly, we cannot propose a block that uses oracles in the fast round.
2452+
let conflict = manager.requested_proposed.as_ref().is_some_and(|proposal| {
24512453
proposal.content.round == manager.current_round && proposal.content.block != *block
2452-
});
2453-
let round = if !conflicting_proposal {
2454+
}) || (manager.current_round.is_fast()
2455+
&& executed_block.outcome.has_oracle_responses());
2456+
let round = if !conflict {
24542457
manager.current_round
24552458
} else if let Some(round) = manager
24562459
.ownership
24572460
.next_round(manager.current_round)
2458-
.filter(|_| manager.current_round.is_multi_leader())
2461+
.filter(|_| manager.current_round.is_multi_leader() || manager.current_round.is_fast())
24592462
{
24602463
round
24612464
} else if let Some(timeout) = info.round_timeout() {

linera-core/src/unit_tests/client_tests.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2432,6 +2432,18 @@ where
24322432
let client2 = builder.add_initial_chain(description2, Amount::ONE).await?;
24332433
let client3 = builder.add_initial_chain(description3, Amount::ONE).await?;
24342434

2435+
// Configure the clients as super owners, so they make fast blocks by default.
2436+
for client in [&client1, &client2, &client3] {
2437+
let pub_key = client.public_key().await?;
2438+
let owner_change_op = Operation::System(SystemOperation::ChangeOwnership {
2439+
super_owners: vec![pub_key],
2440+
owners: vec![],
2441+
multi_leader_rounds: 10,
2442+
timeout_config: TimeoutConfig::default(),
2443+
});
2444+
client.execute_operation(owner_change_op.clone()).await?;
2445+
}
2446+
24352447
// Take one validator down
24362448
builder.set_fault_type([3], FaultType::Offline).await;
24372449

@@ -2440,19 +2452,21 @@ where
24402452
CryptoHash::new(&BlobBytes(blob_bytes.clone())),
24412453
BlobType::Data,
24422454
);
2443-
client1
2455+
let certificate = client1
24442456
.publish_data_blob(blob_bytes)
24452457
.await
24462458
.unwrap()
24472459
.unwrap();
2460+
assert_eq!(certificate.round, Round::Fast);
24482461

24492462
// Send a message from chain 2 to chain 3.
2450-
client2
2463+
let certificate = client2
24512464
.transfer(None, Amount::from_millis(1), Recipient::chain(chain_id3))
24522465
.await
24532466
.unwrap()
24542467
.unwrap();
24552468
client3.synchronize_from_validators().await.unwrap();
2469+
assert_eq!(certificate.round, Round::Fast);
24562470

24572471
builder.set_fault_type([2], FaultType::Offline).await;
24582472
builder.set_fault_type([3], FaultType::Honest).await;
@@ -2463,6 +2477,8 @@ where
24632477
.await
24642478
.unwrap()
24652479
.unwrap();
2480+
// This read a new blob, so it cannot be a fast block.
2481+
assert_eq!(certificate.round, Round::MultiLeader(0));
24662482
let executed_block = certificate.executed_block();
24672483
assert_eq!(executed_block.block.incoming_bundles.len(), 1);
24682484
assert_eq!(executed_block.required_blob_ids().len(), 1);

0 commit comments

Comments
 (0)