Skip to content

Commit db5f020

Browse files
committed
apollo_consensus_orchestrator: use the config manager client to update consensus context config
1 parent aa775a7 commit db5f020

File tree

13 files changed

+210
-4
lines changed

13 files changed

+210
-4
lines changed

Cargo.lock

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/apollo_config_manager/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ apollo_config.workspace = true
1717
apollo_config_manager_config.workspace = true
1818
apollo_config_manager_types.workspace = true
1919
apollo_consensus_config.workspace = true
20+
apollo_consensus_orchestrator_config.workspace = true
2021
apollo_infra.workspace = true
2122
apollo_mempool_config.workspace = true
2223
apollo_metrics.workspace = true

crates/apollo_config_manager/src/config_manager.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use apollo_config_manager_config::config::ConfigManagerConfig;
22
use apollo_config_manager_types::communication::{ConfigManagerRequest, ConfigManagerResponse};
33
use apollo_config_manager_types::config_manager_types::ConfigManagerResult;
44
use apollo_consensus_config::config::ConsensusDynamicConfig;
5+
use apollo_consensus_orchestrator_config::config::ContextDynamicConfig;
56
use apollo_infra::component_definitions::{ComponentRequestHandler, ComponentStarter};
67
use apollo_mempool_config::config::MempoolDynamicConfig;
78
use apollo_node_config::node_config::NodeDynamicConfig;
@@ -38,6 +39,10 @@ impl ConfigManager {
3839
Ok(self.latest_node_dynamic_config.consensus_dynamic_config.as_ref().unwrap().clone())
3940
}
4041

42+
pub(crate) fn get_context_dynamic_config(&self) -> ConfigManagerResult<ContextDynamicConfig> {
43+
Ok(self.latest_node_dynamic_config.context_dynamic_config.as_ref().unwrap().clone())
44+
}
45+
4146
pub(crate) fn get_mempool_dynamic_config(&self) -> ConfigManagerResult<MempoolDynamicConfig> {
4247
Ok(self.latest_node_dynamic_config.mempool_dynamic_config.as_ref().unwrap().clone())
4348
}
@@ -54,6 +59,9 @@ impl ComponentRequestHandler<ConfigManagerRequest, ConfigManagerResponse> for Co
5459
self.get_consensus_dynamic_config(),
5560
)
5661
}
62+
ConfigManagerRequest::GetContextDynamicConfig => {
63+
ConfigManagerResponse::GetContextDynamicConfig(self.get_context_dynamic_config())
64+
}
5765
ConfigManagerRequest::GetMempoolDynamicConfig => {
5866
ConfigManagerResponse::GetMempoolDynamicConfig(self.get_mempool_dynamic_config())
5967
}

crates/apollo_config_manager_types/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ workspace = true
1111

1212
[dependencies]
1313
apollo_consensus_config.workspace = true
14+
apollo_consensus_orchestrator_config.workspace = true
1415
apollo_infra.workspace = true
1516
apollo_mempool_config.workspace = true
1617
apollo_metrics.workspace = true

crates/apollo_config_manager_types/src/communication.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::sync::Arc;
22

33
use apollo_consensus_config::config::ConsensusDynamicConfig;
4+
use apollo_consensus_orchestrator_config::config::ContextDynamicConfig;
45
use apollo_infra::component_client::{ClientError, LocalComponentClient, RemoteComponentClient};
56
use apollo_infra::component_definitions::{ComponentClient, PrioritizedRequest, RequestWrapper};
67
use apollo_infra::{impl_debug_for_infra_requests_and_responses, impl_labeled_request};
@@ -32,6 +33,8 @@ pub trait ConfigManagerClient: Send + Sync {
3233
&self,
3334
) -> ConfigManagerClientResult<ConsensusDynamicConfig>;
3435

36+
async fn get_context_dynamic_config(&self) -> ConfigManagerClientResult<ContextDynamicConfig>;
37+
3538
async fn get_mempool_dynamic_config(&self) -> ConfigManagerClientResult<MempoolDynamicConfig>;
3639

3740
async fn set_node_dynamic_config(
@@ -48,6 +51,7 @@ pub trait ConfigManagerClient: Send + Sync {
4851
)]
4952
pub enum ConfigManagerRequest {
5053
GetConsensusDynamicConfig,
54+
GetContextDynamicConfig,
5155
GetMempoolDynamicConfig,
5256
SetNodeDynamicConfig(NodeDynamicConfig),
5357
}
@@ -65,6 +69,7 @@ generate_permutation_labels! {
6569
#[derive(Clone, Serialize, Deserialize, AsRefStr)]
6670
pub enum ConfigManagerResponse {
6771
GetConsensusDynamicConfig(ConfigManagerResult<ConsensusDynamicConfig>),
72+
GetContextDynamicConfig(ConfigManagerResult<ContextDynamicConfig>),
6873
GetMempoolDynamicConfig(ConfigManagerResult<MempoolDynamicConfig>),
6974
SetNodeDynamicConfig(ConfigManagerResult<()>),
7075
}
@@ -96,6 +101,17 @@ where
96101
)
97102
}
98103

104+
async fn get_context_dynamic_config(&self) -> ConfigManagerClientResult<ContextDynamicConfig> {
105+
let request = ConfigManagerRequest::GetContextDynamicConfig;
106+
handle_all_response_variants!(
107+
ConfigManagerResponse,
108+
GetContextDynamicConfig,
109+
ConfigManagerClientError,
110+
ConfigManagerError,
111+
Direct
112+
)
113+
}
114+
99115
async fn get_mempool_dynamic_config(&self) -> ConfigManagerClientResult<MempoolDynamicConfig> {
100116
let request = ConfigManagerRequest::GetMempoolDynamicConfig;
101117
handle_all_response_variants!(

crates/apollo_consensus_manager/src/consensus_manager.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ impl ConsensusManager {
144144
let consensus_context = self.create_sequencer_consensus_context(
145145
&votes_broadcast_channels,
146146
outbound_internal_sender,
147+
self.config_manager_client.clone(),
147148
);
148149

149150
let current_height =
@@ -264,6 +265,7 @@ impl ConsensusManager {
264265
&self,
265266
votes_broadcast_channels: &BroadcastTopicChannels<Vote>,
266267
outbound_internal_sender: mpsc::Sender<(HeightAndRound, mpsc::Receiver<ProposalPart>)>,
268+
config_manager_client: SharedConfigManagerClient,
267269
) -> SequencerConsensusContext {
268270
SequencerConsensusContext::new(
269271
self.config.context_config.clone(),
@@ -282,6 +284,7 @@ impl ConsensusManager {
282284
clock: Arc::new(DefaultClock),
283285
outbound_proposal_sender: outbound_internal_sender,
284286
vote_broadcast_client: votes_broadcast_channels.broadcast_topic_client.clone(),
287+
config_manager_client: Some(Arc::clone(&config_manager_client)),
285288
},
286289
)
287290
}

crates/apollo_consensus_orchestrator/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ apollo_batcher.workspace = true
1111
apollo_batcher_types.workspace = true
1212
apollo_class_manager_types.workspace = true
1313
apollo_config.workspace = true
14+
apollo_config_manager_types.workspace = true
1415
apollo_consensus.workspace = true
1516
apollo_consensus_orchestrator_config.workspace = true
1617
apollo_infra_utils.workspace = true
@@ -52,6 +53,7 @@ apollo_batcher.workspace = true
5253
apollo_batcher_types = { workspace = true, features = ["testing"] }
5354
apollo_class_manager_types = { workspace = true, features = ["testing"] }
5455
apollo_config.workspace = true
56+
apollo_config_manager_types = { workspace = true, features = ["testing"] }
5557
apollo_infra = { workspace = true, features = ["testing"] }
5658
apollo_infra_utils = { workspace = true, features = ["testing"] }
5759
apollo_l1_gas_price_types = { workspace = true, features = ["testing"] }

crates/apollo_consensus_orchestrator/src/sequencer_consensus_context.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use apollo_batcher_types::batcher_types::{
1818
};
1919
use apollo_batcher_types::communication::BatcherClient;
2020
use apollo_class_manager_types::transaction_converter::TransactionConverterTrait;
21+
use apollo_config_manager_types::communication::SharedConfigManagerClient;
2122
use apollo_consensus::types::{
2223
ConsensusContext,
2324
ConsensusError,
@@ -177,6 +178,7 @@ pub struct SequencerConsensusContextDeps {
177178
pub outbound_proposal_sender: mpsc::Sender<(HeightAndRound, mpsc::Receiver<ProposalPart>)>,
178179
// Used to broadcast votes to other consensus nodes.
179180
pub vote_broadcast_client: BroadcastTopicClient<Vote>,
181+
pub config_manager_client: Option<SharedConfigManagerClient>,
180182
}
181183

182184
impl SequencerConsensusContext {
@@ -723,6 +725,10 @@ impl ConsensusContext for SequencerConsensusContext {
723725
height: BlockNumber,
724726
round: Round,
725727
) -> Result<(), ConsensusError> {
728+
if let Some(config_manager_client) = self.deps.config_manager_client.clone() {
729+
self.config.dynamic_config =
730+
config_manager_client.get_context_dynamic_config().await.unwrap();
731+
}
726732
if self.current_height.map(|h| height > h).unwrap_or(true) {
727733
self.current_height = Some(height);
728734
assert_eq!(round, 0);
@@ -734,13 +740,25 @@ impl ConsensusContext for SequencerConsensusContext {
734740
// return to the old height.
735741
return Ok(self.deps.batcher.start_height(StartHeightInput { height }).await?);
736742
}
737-
assert_eq!(Some(height), self.current_height);
743+
assert_eq!(
744+
Some(height),
745+
self.current_height,
746+
"height {} is not equal to current height {:?}",
747+
height,
748+
self.current_height
749+
);
738750
if round == self.current_round {
739751
return Ok(());
740752
}
741-
assert!(round > self.current_round);
753+
assert!(
754+
round > self.current_round,
755+
"round {} is not greater than current round {}",
756+
round,
757+
self.current_round
758+
);
742759
self.interrupt_active_proposal().await;
743760
self.current_round = round;
761+
744762
let mut to_process = None;
745763
while let Some(entry) = self.queued_proposals.first_entry() {
746764
match self.current_round.cmp(entry.key()) {

crates/apollo_consensus_orchestrator/src/sequencer_consensus_context_test.rs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::sync::Arc;
44
use apollo_batcher_types::batcher_types::{CentralObjects, DecisionReachedResponse};
55
use apollo_batcher_types::communication::BatcherClientError;
66
use apollo_batcher_types::errors::BatcherError;
7+
use apollo_config_manager_types::communication::MockConfigManagerClient;
78
use apollo_consensus::types::{ConsensusContext, Round};
89
use apollo_consensus_orchestrator_config::config::{ContextConfig, ContextDynamicConfig};
910
use apollo_infra::component_client::ClientError;
@@ -1027,3 +1028,119 @@ async fn override_prices_behavior(
10271028
);
10281029
}
10291030
}
1031+
1032+
#[tokio::test]
1033+
async fn change_gas_price_overrides() {
1034+
let (mut deps, mut network) = create_test_and_network_deps();
1035+
1036+
// Validate two blocks, between the first and the second we will change the gas price overrides.
1037+
// After the second block we will do another round with another dynamic config change.
1038+
deps.setup_deps_for_validate(BlockNumber(0), INTERNAL_TX_BATCH.len(), 3);
1039+
deps.setup_deps_for_build(BlockNumber(2), INTERNAL_TX_BATCH.len(), 1);
1040+
1041+
// set up batcher decision_reached
1042+
deps.batcher.expect_decision_reached().times(2).returning(|_| {
1043+
Ok(DecisionReachedResponse {
1044+
state_diff: ThinStateDiff::default(),
1045+
l2_gas_used: GasAmount::default(),
1046+
central_objects: CentralObjects::default(),
1047+
block_header_commitments: BlockHeaderCommitments::default(),
1048+
})
1049+
});
1050+
1051+
// required for decision reached flow
1052+
deps.state_sync_client.expect_add_new_block().times(2).returning(|_| Ok(()));
1053+
// Mock sync to never provide any blocks in this test.
1054+
deps.state_sync_client.expect_get_latest_block_number().returning(|| Ok(None));
1055+
deps.cende_ambassador.expect_prepare_blob_for_next_height().times(2).returning(|_| Ok(()));
1056+
1057+
let mut context = deps.build_context();
1058+
1059+
// Validate block number 0.
1060+
context.set_height_and_round(BlockNumber(0), 0).await.unwrap();
1061+
1062+
let content_receiver =
1063+
send_proposal_to_validator_context(&mut context, block_info(BlockNumber(0))).await;
1064+
let fin_receiver =
1065+
context.validate_proposal(ProposalInit::default(), TIMEOUT, content_receiver).await;
1066+
1067+
let proposal_commitment = fin_receiver.await.unwrap();
1068+
assert_eq!(proposal_commitment.0, STATE_DIFF_COMMITMENT.0.0);
1069+
1070+
context.decision_reached(BlockNumber(0), proposal_commitment).await.unwrap();
1071+
1072+
let new_dynamic_config = ContextDynamicConfig {
1073+
override_l2_gas_price_fri: Some(ODDLY_SPECIFIC_L2_GAS_PRICE),
1074+
..Default::default()
1075+
};
1076+
let config_manager_client = make_config_manager_client(new_dynamic_config);
1077+
context.deps.config_manager_client = Some(Arc::new(config_manager_client));
1078+
1079+
// Modify the incoming block info to make sure it matches the overrides. If we don't, the
1080+
// proposal will fail validation.
1081+
let mut modified_block_info = block_info(BlockNumber(1));
1082+
modified_block_info.l2_gas_price_fri = GasPrice(ODDLY_SPECIFIC_L2_GAS_PRICE);
1083+
1084+
// Validate block number 1, round 0.
1085+
context.set_height_and_round(BlockNumber(1), 0).await.unwrap();
1086+
let init = ProposalInit { height: BlockNumber(1), ..Default::default() };
1087+
1088+
let content_receiver =
1089+
send_proposal_to_validator_context(&mut context, modified_block_info).await;
1090+
let fin_receiver = context.validate_proposal(init, TIMEOUT, content_receiver).await;
1091+
let proposal_commitment = fin_receiver.await.unwrap();
1092+
assert_eq!(proposal_commitment.0, STATE_DIFF_COMMITMENT.0.0);
1093+
1094+
// Validate block number 1, round 1.
1095+
let new_dynamic_config = ContextDynamicConfig {
1096+
min_l1_data_gas_price_wei: ODDLY_SPECIFIC_L1_DATA_GAS_PRICE,
1097+
..Default::default()
1098+
};
1099+
let config_manager_client = make_config_manager_client(new_dynamic_config);
1100+
context.deps.config_manager_client = Some(Arc::new(config_manager_client));
1101+
1102+
let mut modified_block_info = block_info(BlockNumber(1));
1103+
modified_block_info.l1_data_gas_price_wei = GasPrice(ODDLY_SPECIFIC_L1_DATA_GAS_PRICE);
1104+
1105+
context.set_height_and_round(BlockNumber(1), 1).await.unwrap();
1106+
let init = ProposalInit { height: BlockNumber(1), round: 1, ..Default::default() };
1107+
1108+
let content_receiver =
1109+
send_proposal_to_validator_context(&mut context, modified_block_info).await;
1110+
let fin_receiver = context.validate_proposal(init, TIMEOUT, content_receiver).await;
1111+
let proposal_commitment = fin_receiver.await.unwrap();
1112+
assert_eq!(proposal_commitment.0, STATE_DIFF_COMMITMENT.0.0);
1113+
1114+
context.decision_reached(BlockNumber(1), proposal_commitment).await.unwrap();
1115+
1116+
// Now build a proposal for height 2.
1117+
let new_dynamic_config = ContextDynamicConfig {
1118+
override_eth_to_fri_rate: Some(ODDLY_SPECIFIC_CONVERSION_RATE),
1119+
..Default::default()
1120+
};
1121+
let config_manager_client = make_config_manager_client(new_dynamic_config);
1122+
context.deps.config_manager_client = Some(Arc::new(config_manager_client));
1123+
1124+
let init = ProposalInit { height: BlockNumber(2), ..Default::default() };
1125+
1126+
let fin_receiver = context.build_proposal(init, TIMEOUT).await.unwrap().await.unwrap();
1127+
1128+
assert_eq!(fin_receiver.0, STATE_DIFF_COMMITMENT.0.0);
1129+
let (_, mut receiver) = network.outbound_proposal_receiver.next().await.unwrap();
1130+
1131+
assert_eq!(receiver.next().await.unwrap(), init.into());
1132+
let info = receiver.next().await.unwrap();
1133+
let ProposalPart::BlockInfo(info) = info else {
1134+
panic!("Expected ProposalPart::BlockInfo");
1135+
};
1136+
assert_eq!(info.eth_to_fri_rate, ODDLY_SPECIFIC_CONVERSION_RATE);
1137+
}
1138+
1139+
fn make_config_manager_client(provider_config: ContextDynamicConfig) -> MockConfigManagerClient {
1140+
let mut config_manager_client = MockConfigManagerClient::new();
1141+
config_manager_client
1142+
.expect_get_context_dynamic_config()
1143+
.returning(move || Ok(provider_config.clone()));
1144+
config_manager_client.expect_set_node_dynamic_config().returning(|_| Ok(()));
1145+
config_manager_client
1146+
}

crates/apollo_consensus_orchestrator/src/test_utils.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ impl From<TestDeps> for SequencerConsensusContextDeps {
117117
clock: deps.clock,
118118
outbound_proposal_sender: deps.outbound_proposal_sender,
119119
vote_broadcast_client: deps.vote_broadcast_client,
120+
config_manager_client: None,
120121
}
121122
}
122123
}
@@ -146,7 +147,6 @@ impl TestDeps {
146147
);
147148
self.batcher
148149
.expect_start_height()
149-
.times(1)
150150
.withf(move |input| input.height == block_number)
151151
.return_const(Ok(()));
152152
let proposal_id_clone = Arc::clone(&proposal_id);
@@ -183,6 +183,7 @@ impl TestDeps {
183183
assert!(final_n_executed_txs <= INTERNAL_TX_BATCH.len());
184184
self.setup_default_expectations();
185185
let mut seq = Sequence::new();
186+
186187
for _ in 0..number_of_times {
187188
let proposal_id = Arc::new(OnceLock::new());
188189

0 commit comments

Comments
 (0)