Skip to content

Commit 299c1d0

Browse files
committed
apollo_consensus_orchestrator: use the config manager client to update consensus context config
1 parent 4e6e120 commit 299c1d0

File tree

13 files changed

+238
-3
lines changed

13 files changed

+238
-3
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_http_server_config.workspace = true
2122
apollo_infra.workspace = true
2223
apollo_mempool_config.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_http_server_config::config::HttpServerDynamicConfig;
67
use apollo_infra::component_definitions::{ComponentRequestHandler, ComponentStarter};
78
use apollo_mempool_config::config::MempoolDynamicConfig;
@@ -39,6 +40,10 @@ impl ConfigManager {
3940
Ok(self.latest_node_dynamic_config.consensus_dynamic_config.as_ref().unwrap().clone())
4041
}
4142

43+
pub(crate) fn get_context_dynamic_config(&self) -> ConfigManagerResult<ContextDynamicConfig> {
44+
Ok(self.latest_node_dynamic_config.context_dynamic_config.as_ref().unwrap().clone())
45+
}
46+
4247
pub(crate) fn get_http_server_dynamic_config(
4348
&self,
4449
) -> ConfigManagerResult<HttpServerDynamicConfig> {
@@ -61,6 +66,9 @@ impl ComponentRequestHandler<ConfigManagerRequest, ConfigManagerResponse> for Co
6166
self.get_consensus_dynamic_config(),
6267
)
6368
}
69+
ConfigManagerRequest::GetContextDynamicConfig => {
70+
ConfigManagerResponse::GetContextDynamicConfig(self.get_context_dynamic_config())
71+
}
6472
ConfigManagerRequest::GetHttpServerDynamicConfig => {
6573
ConfigManagerResponse::GetHttpServerDynamicConfig(
6674
self.get_http_server_dynamic_config(),

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_http_server_config.workspace = true
1516
apollo_infra.workspace = true
1617
apollo_mempool_config.workspace = true

crates/apollo_config_manager_types/src/communication.rs

Lines changed: 15 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_http_server_config::config::HttpServerDynamicConfig;
56
use apollo_infra::component_client::{ClientError, LocalComponentClient, RemoteComponentClient};
67
use apollo_infra::component_definitions::{ComponentClient, PrioritizedRequest, RequestWrapper};
@@ -33,6 +34,7 @@ pub trait ConfigManagerClient: Send + Sync {
3334
&self,
3435
) -> ConfigManagerClientResult<ConsensusDynamicConfig>;
3536

37+
async fn get_context_dynamic_config(&self) -> ConfigManagerClientResult<ContextDynamicConfig>;
3638
async fn get_http_server_dynamic_config(
3739
&self,
3840
) -> ConfigManagerClientResult<HttpServerDynamicConfig>;
@@ -53,6 +55,7 @@ pub trait ConfigManagerClient: Send + Sync {
5355
)]
5456
pub enum ConfigManagerRequest {
5557
GetConsensusDynamicConfig,
58+
GetContextDynamicConfig,
5659
GetHttpServerDynamicConfig,
5760
GetMempoolDynamicConfig,
5861
SetNodeDynamicConfig(NodeDynamicConfig),
@@ -71,6 +74,7 @@ generate_permutation_labels! {
7174
#[derive(Clone, Serialize, Deserialize, AsRefStr)]
7275
pub enum ConfigManagerResponse {
7376
GetConsensusDynamicConfig(ConfigManagerResult<ConsensusDynamicConfig>),
77+
GetContextDynamicConfig(ConfigManagerResult<ContextDynamicConfig>),
7478
GetHttpServerDynamicConfig(ConfigManagerResult<HttpServerDynamicConfig>),
7579
GetMempoolDynamicConfig(ConfigManagerResult<MempoolDynamicConfig>),
7680
SetNodeDynamicConfig(ConfigManagerResult<()>),
@@ -103,6 +107,17 @@ where
103107
)
104108
}
105109

110+
async fn get_context_dynamic_config(&self) -> ConfigManagerClientResult<ContextDynamicConfig> {
111+
let request = ConfigManagerRequest::GetContextDynamicConfig;
112+
handle_all_response_variants!(
113+
ConfigManagerResponse,
114+
GetContextDynamicConfig,
115+
ConfigManagerClientError,
116+
ConfigManagerError,
117+
Direct
118+
)
119+
}
120+
106121
async fn get_http_server_dynamic_config(
107122
&self,
108123
) -> ConfigManagerClientResult<HttpServerDynamicConfig> {

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
@@ -10,6 +10,7 @@ description = "Implements the consensus context and orchestrates the node's comp
1010
apollo_batcher.workspace = true
1111
apollo_batcher_types.workspace = true
1212
apollo_class_manager_types.workspace = true
13+
apollo_config_manager_types.workspace = true
1314
apollo_consensus.workspace = true
1415
apollo_consensus_orchestrator_config.workspace = true
1516
apollo_infra_utils.workspace = true
@@ -50,6 +51,7 @@ url = { workspace = true, features = ["serde"] }
5051
apollo_batcher.workspace = true
5152
apollo_batcher_types = { workspace = true, features = ["testing"] }
5253
apollo_class_manager_types = { workspace = true, features = ["testing"] }
54+
apollo_config_manager_types = { workspace = true, features = ["testing"] }
5355
apollo_infra = { workspace = true, features = ["testing"] }
5456
apollo_infra_utils = { workspace = true, features = ["testing"] }
5557
apollo_l1_gas_price_types = { workspace = true, features = ["testing"] }

crates/apollo_consensus_orchestrator/src/sequencer_consensus_context.rs

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use apollo_class_manager_types::transaction_converter::{
2121
TransactionConverterError,
2222
TransactionConverterTrait,
2323
};
24+
use apollo_config_manager_types::communication::SharedConfigManagerClient;
2425
use apollo_consensus::types::{
2526
ConsensusContext,
2627
ConsensusError,
@@ -185,6 +186,7 @@ pub struct SequencerConsensusContextDeps {
185186
pub outbound_proposal_sender: mpsc::Sender<(HeightAndRound, mpsc::Receiver<ProposalPart>)>,
186187
// Used to broadcast votes to other consensus nodes.
187188
pub vote_broadcast_client: BroadcastTopicClient<Vote>,
189+
pub config_manager_client: Option<SharedConfigManagerClient>,
188190
}
189191

190192
#[derive(thiserror::Error, PartialEq, Debug)]
@@ -785,6 +787,7 @@ impl ConsensusContext for SequencerConsensusContext {
785787
round: Round,
786788
) -> Result<(), ConsensusError> {
787789
if self.current_height.map(|h| height > h).unwrap_or(true) {
790+
self.update_dynamic_config().await;
788791
self.current_height = Some(height);
789792
assert_eq!(round, 0);
790793
self.current_round = round;
@@ -795,13 +798,26 @@ impl ConsensusContext for SequencerConsensusContext {
795798
// return to the old height.
796799
return Ok(self.deps.batcher.start_height(StartHeightInput { height }).await?);
797800
}
798-
assert_eq!(Some(height), self.current_height);
801+
assert_eq!(
802+
Some(height),
803+
self.current_height,
804+
"height {} is not equal to current height {:?}",
805+
height,
806+
self.current_height
807+
);
799808
if round == self.current_round {
800809
return Ok(());
801810
}
802-
assert!(round > self.current_round);
811+
assert!(
812+
round > self.current_round,
813+
"round {} is not greater than current round {}",
814+
round,
815+
self.current_round
816+
);
803817
self.interrupt_active_proposal().await;
804818
self.current_round = round;
819+
self.update_dynamic_config().await;
820+
805821
let mut to_process = None;
806822
while let Some(entry) = self.queued_proposals.first_entry() {
807823
match self.current_round.cmp(entry.key()) {
@@ -903,6 +919,23 @@ impl SequencerConsensusContext {
903919
}
904920
}
905921
}
922+
923+
async fn update_dynamic_config(&mut self) {
924+
if let Some(config_manager_client) = self.deps.config_manager_client.clone() {
925+
let config_result = config_manager_client.get_context_dynamic_config().await;
926+
match config_result {
927+
Ok(config) => {
928+
self.config.dynamic_config = config;
929+
}
930+
Err(e) => {
931+
error!(
932+
"Failed to get dynamic config for consensus context. Config not updated. \
933+
Error: {e:?}"
934+
);
935+
}
936+
}
937+
}
938+
}
906939
}
907940

908941
async fn validate_and_send(

crates/apollo_consensus_orchestrator/src/sequencer_consensus_context_test.rs

Lines changed: 126 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;
@@ -1042,3 +1043,128 @@ async fn override_prices_behavior(
10421043
);
10431044
}
10441045
}
1046+
1047+
#[tokio::test]
1048+
async fn change_gas_price_overrides() {
1049+
let (mut deps, mut network) = create_test_and_network_deps();
1050+
1051+
// Validate two blocks, between the first and the second we will change the gas price overrides.
1052+
// After the second block we will do another round with another dynamic config change.
1053+
deps.setup_deps_for_validate(SetupDepsArgs { number_of_times: 2, ..Default::default() });
1054+
deps.setup_deps_for_validate(SetupDepsArgs {
1055+
number_of_times: 1,
1056+
expect_start_height: false,
1057+
start_block_number: BlockNumber(2),
1058+
..Default::default()
1059+
});
1060+
deps.setup_deps_for_build(SetupDepsArgs {
1061+
start_block_number: BlockNumber(2),
1062+
..Default::default()
1063+
});
1064+
1065+
// set up batcher decision_reached
1066+
deps.batcher.expect_decision_reached().times(2).returning(|_| {
1067+
Ok(DecisionReachedResponse {
1068+
state_diff: ThinStateDiff::default(),
1069+
l2_gas_used: GasAmount::default(),
1070+
central_objects: CentralObjects::default(),
1071+
block_header_commitments: BlockHeaderCommitments::default(),
1072+
})
1073+
});
1074+
1075+
// required for decision reached flow
1076+
deps.state_sync_client.expect_add_new_block().times(2).returning(|_| Ok(()));
1077+
// Mock sync to never provide any blocks in this test.
1078+
deps.state_sync_client.expect_get_latest_block_number().returning(|| Ok(None));
1079+
deps.cende_ambassador.expect_prepare_blob_for_next_height().times(2).returning(|_| Ok(()));
1080+
1081+
let mut context = deps.build_context();
1082+
1083+
// Validate block number 0.
1084+
context.set_height_and_round(BlockNumber(0), 0).await.unwrap();
1085+
1086+
let content_receiver =
1087+
send_proposal_to_validator_context(&mut context, block_info(BlockNumber(0))).await;
1088+
let fin_receiver =
1089+
context.validate_proposal(ProposalInit::default(), TIMEOUT, content_receiver).await;
1090+
1091+
let proposal_commitment = fin_receiver.await.unwrap();
1092+
assert_eq!(proposal_commitment.0, STATE_DIFF_COMMITMENT.0.0);
1093+
1094+
context.decision_reached(BlockNumber(0), proposal_commitment).await.unwrap();
1095+
1096+
let new_dynamic_config = ContextDynamicConfig {
1097+
override_l2_gas_price_fri: Some(ODDLY_SPECIFIC_L2_GAS_PRICE),
1098+
..Default::default()
1099+
};
1100+
let config_manager_client = make_config_manager_client(new_dynamic_config);
1101+
context.deps.config_manager_client = Some(Arc::new(config_manager_client));
1102+
1103+
// Modify the incoming block info to make sure it matches the overrides. If we don't, the
1104+
// proposal will fail validation.
1105+
let mut modified_block_info = block_info(BlockNumber(1));
1106+
modified_block_info.l2_gas_price_fri = GasPrice(ODDLY_SPECIFIC_L2_GAS_PRICE);
1107+
1108+
// Validate block number 1, round 0.
1109+
context.set_height_and_round(BlockNumber(1), 0).await.unwrap();
1110+
let init = ProposalInit { height: BlockNumber(1), ..Default::default() };
1111+
1112+
let content_receiver =
1113+
send_proposal_to_validator_context(&mut context, modified_block_info).await;
1114+
let fin_receiver = context.validate_proposal(init, TIMEOUT, content_receiver).await;
1115+
let proposal_commitment = fin_receiver.await.unwrap();
1116+
assert_eq!(proposal_commitment.0, STATE_DIFF_COMMITMENT.0.0);
1117+
1118+
// Validate block number 1, round 1.
1119+
let new_dynamic_config = ContextDynamicConfig {
1120+
min_l1_data_gas_price_wei: ODDLY_SPECIFIC_L1_DATA_GAS_PRICE,
1121+
..Default::default()
1122+
};
1123+
let config_manager_client = make_config_manager_client(new_dynamic_config);
1124+
context.deps.config_manager_client = Some(Arc::new(config_manager_client));
1125+
1126+
let mut modified_block_info = block_info(BlockNumber(1));
1127+
modified_block_info.l1_data_gas_price_wei = GasPrice(ODDLY_SPECIFIC_L1_DATA_GAS_PRICE);
1128+
1129+
context.set_height_and_round(BlockNumber(1), 1).await.unwrap();
1130+
let init = ProposalInit { height: BlockNumber(1), round: 1, ..Default::default() };
1131+
1132+
let content_receiver =
1133+
send_proposal_to_validator_context(&mut context, modified_block_info).await;
1134+
let fin_receiver = context.validate_proposal(init, TIMEOUT, content_receiver).await;
1135+
let proposal_commitment = fin_receiver.await.unwrap();
1136+
assert_eq!(proposal_commitment.0, STATE_DIFF_COMMITMENT.0.0);
1137+
1138+
context.decision_reached(BlockNumber(1), proposal_commitment).await.unwrap();
1139+
1140+
// Now build a proposal for height 2.
1141+
let new_dynamic_config = ContextDynamicConfig {
1142+
override_eth_to_fri_rate: Some(ODDLY_SPECIFIC_CONVERSION_RATE),
1143+
..Default::default()
1144+
};
1145+
let config_manager_client = make_config_manager_client(new_dynamic_config);
1146+
context.deps.config_manager_client = Some(Arc::new(config_manager_client));
1147+
1148+
let init = ProposalInit { height: BlockNumber(2), ..Default::default() };
1149+
1150+
let fin_receiver = context.build_proposal(init, TIMEOUT).await.unwrap().await.unwrap();
1151+
1152+
assert_eq!(fin_receiver.0, STATE_DIFF_COMMITMENT.0.0);
1153+
let (_, mut receiver) = network.outbound_proposal_receiver.next().await.unwrap();
1154+
1155+
assert_eq!(receiver.next().await.unwrap(), init.into());
1156+
let info = receiver.next().await.unwrap();
1157+
let ProposalPart::BlockInfo(info) = info else {
1158+
panic!("Expected ProposalPart::BlockInfo");
1159+
};
1160+
assert_eq!(info.eth_to_fri_rate, ODDLY_SPECIFIC_CONVERSION_RATE);
1161+
}
1162+
1163+
fn make_config_manager_client(provider_config: ContextDynamicConfig) -> MockConfigManagerClient {
1164+
let mut config_manager_client = MockConfigManagerClient::new();
1165+
config_manager_client
1166+
.expect_get_context_dynamic_config()
1167+
.returning(move || Ok(provider_config.clone()));
1168+
config_manager_client.expect_set_node_dynamic_config().returning(|_| Ok(()));
1169+
config_manager_client
1170+
}

crates/apollo_consensus_orchestrator/src/test_utils.rs

Lines changed: 1 addition & 0 deletions
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
}

0 commit comments

Comments
 (0)