Skip to content

Commit f7963ff

Browse files
authored
feat(code/test): Middleware for testing (circlefin#948)
* Add concept of middleware to change from the tests how votes and proposals are built * Make `new_prevote`, `new_precommit` and `new_proposal` methods of `Context` instead of static functions * Stuff middleware in the `TestContext` instead of static variable * Remove unused dependency * Add way to access middleware from TestContext * Replace `is_byzantine_proposer` config by a middleware * Fix logging
1 parent c3e0bea commit f7963ff

File tree

20 files changed

+253
-84
lines changed

20 files changed

+253
-84
lines changed

code/crates/config/src/lib.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -649,8 +649,6 @@ pub struct TestConfig {
649649
pub max_retain_blocks: usize,
650650
#[serde(default)]
651651
pub vote_extensions: VoteExtensionsConfig,
652-
#[serde(default)]
653-
pub is_byzantine_proposer: bool,
654652
}
655653

656654
impl Default for TestConfig {
@@ -663,7 +661,6 @@ impl Default for TestConfig {
663661
exec_time_per_tx: Duration::from_millis(1),
664662
max_retain_blocks: 1000,
665663
vote_extensions: VoteExtensionsConfig::default(),
666-
is_byzantine_proposer: false,
667664
}
668665
}
669666
}

code/crates/core-consensus/src/handle/proposed_value.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ where
3939
// b) In any mode if the proposed value was provided by Sync, where we do net get a Proposal message but only the full value and the certificate
4040
if state.params.value_payload.parts_only() || origin == ValueOrigin::Sync {
4141
let proposal = Ctx::new_proposal(
42+
&state.ctx,
4243
proposed_value.height,
4344
proposed_value.round,
4445
proposed_value.value.clone(),

code/crates/core-driver/src/driver.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ where
501501
let info = Info::new(input_round, &self.address, proposer.address());
502502

503503
// Apply the input to the round state machine
504-
let transition = round_state.apply(&info, input);
504+
let transition = round_state.apply(&self.ctx, &info, input);
505505

506506
// Update state
507507
self.round_state = transition.next_state;

code/crates/core-state-machine/src/output.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,33 +33,36 @@ where
3333
impl<Ctx: Context> Output<Ctx> {
3434
/// Build a `Proposal` output.
3535
pub fn proposal(
36+
ctx: &Ctx,
3637
height: Ctx::Height,
3738
round: Round,
3839
value: Ctx::Value,
3940
pol_round: Round,
4041
address: Ctx::Address,
4142
) -> Self {
42-
Output::Proposal(Ctx::new_proposal(height, round, value, pol_round, address))
43+
Output::Proposal(ctx.new_proposal(height, round, value, pol_round, address))
4344
}
4445

4546
/// Build a `Vote` output for a prevote.
4647
pub fn prevote(
48+
ctx: &Ctx,
4749
height: Ctx::Height,
4850
round: Round,
4951
value_id: NilOrVal<ValueId<Ctx>>,
5052
address: Ctx::Address,
5153
) -> Self {
52-
Output::Vote(Ctx::new_prevote(height, round, value_id, address))
54+
Output::Vote(ctx.new_prevote(height, round, value_id, address))
5355
}
5456

5557
/// Build a `Vote` output for a precommit.
5658
pub fn precommit(
59+
ctx: &Ctx,
5760
height: Ctx::Height,
5861
round: Round,
5962
value_id: NilOrVal<ValueId<Ctx>>,
6063
address: Ctx::Address,
6164
) -> Self {
62-
Output::Vote(Ctx::new_precommit(height, round, value_id, address))
65+
Output::Vote(ctx.new_precommit(height, round, value_id, address))
6366
}
6467

6568
/// Build a `ScheduleTimeout` output.

code/crates/core-state-machine/src/state.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,8 @@ where
130130
}
131131

132132
/// Apply the given input to the current state, triggering a transition.
133-
pub fn apply(self, data: &Info<Ctx>, input: Input<Ctx>) -> Transition<Ctx> {
134-
crate::state_machine::apply(self, data, input)
133+
pub fn apply(self, ctx: &Ctx, data: &Info<Ctx>, input: Input<Ctx>) -> Transition<Ctx> {
134+
crate::state_machine::apply(ctx, self, data, input)
135135
}
136136

137137
/// Return the traces logged during execution.

code/crates/core-state-machine/src/state_machine.rs

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,12 @@ where
6868
/// Valid transitions result in at least a change to the state and/or an output.
6969
///
7070
/// Commented numbers refer to line numbers in the spec paper.
71-
pub fn apply<Ctx>(mut state: State<Ctx>, info: &Info<Ctx>, input: Input<Ctx>) -> Transition<Ctx>
71+
pub fn apply<Ctx>(
72+
ctx: &Ctx,
73+
mut state: State<Ctx>,
74+
info: &Info<Ctx>,
75+
input: Input<Ctx>,
76+
) -> Transition<Ctx>
7277
where
7378
Ctx: Context,
7479
{
@@ -87,7 +92,7 @@ where
8792
debug_trace!(state, Line::L11Proposer);
8893

8994
// We are the proposer
90-
propose_valid_or_get_value(state, info.address)
95+
propose_valid_or_get_value(ctx, state, info.address)
9196
}
9297

9398
// L11/L20
@@ -109,7 +114,7 @@ where
109114
(Step::Propose, Input::ProposeValue(value)) if this_round => {
110115
debug_assert!(info.is_proposer());
111116

112-
propose(state, value, info.address)
117+
propose(ctx, state, value, info.address)
113118
}
114119

115120
// L22 with valid proposal
@@ -118,18 +123,20 @@ where
118123
{
119124
debug_trace!(state, Line::L22);
120125

121-
prevote(state, info.address, &proposal)
126+
prevote(ctx, state, info.address, &proposal)
122127
}
123128

124129
// L22 with invalid proposal
125-
(Step::Propose, Input::InvalidProposal) if this_round => prevote_nil(state, info.address),
130+
(Step::Propose, Input::InvalidProposal) if this_round => {
131+
prevote_nil(ctx, state, info.address)
132+
}
126133

127134
// L28 with valid proposal
128135
(Step::Propose, Input::ProposalAndPolkaPrevious(proposal))
129136
if this_round && is_valid_pol_round(&state, proposal.pol_round()) =>
130137
{
131138
debug_trace!(state, Line::L28ValidProposal);
132-
prevote_previous(state, info.address, &proposal)
139+
prevote_previous(ctx, state, info.address, &proposal)
133140
}
134141

135142
// L28 with invalid proposal
@@ -139,23 +146,23 @@ where
139146
debug_trace!(state, Line::L28InvalidProposal);
140147
debug_trace!(state, Line::L32InvalidValue);
141148

142-
prevote_nil(state, info.address)
149+
prevote_nil(ctx, state, info.address)
143150
}
144151

145152
// L57
146153
// We are the proposer.
147154
(Step::Propose, Input::TimeoutPropose) if this_round && info.is_proposer() => {
148155
debug_trace!(state, Line::L59Proposer);
149156

150-
prevote_nil(state, info.address)
157+
prevote_nil(ctx, state, info.address)
151158
}
152159

153160
// L57
154161
// We are not the proposer.
155162
(Step::Propose, Input::TimeoutPropose) if this_round => {
156163
debug_trace!(state, Line::L59NonProposer);
157164

158-
prevote_nil(state, info.address)
165+
prevote_nil(ctx, state, info.address)
159166
}
160167

161168
//
@@ -174,22 +181,22 @@ where
174181
(Step::Prevote, Input::PolkaNil) if this_round => {
175182
debug_trace!(state, Line::L45);
176183

177-
precommit_nil(state, info.address)
184+
precommit_nil(ctx, state, info.address)
178185
}
179186

180187
// L36/L37
181188
// NOTE: Only executed the first time, as the votekeeper will only emit this threshold once.
182189
(Step::Prevote, Input::ProposalAndPolkaCurrent(proposal)) if this_round => {
183190
debug_trace!(state, Line::L36ValidProposal);
184191

185-
precommit(state, info.address, proposal)
192+
precommit(ctx, state, info.address, proposal)
186193
}
187194

188195
// L61
189196
(Step::Prevote, Input::TimeoutPrevote) if this_round => {
190197
debug_trace!(state, Line::L61);
191198

192-
precommit_nil(state, info.address)
199+
precommit_nil(ctx, state, info.address)
193200
}
194201

195202
//
@@ -251,6 +258,7 @@ where
251258
///
252259
/// Ref: L13-L16, L19
253260
pub fn propose_valid_or_get_value<Ctx>(
261+
ctx: &Ctx,
254262
mut state: State<Ctx>,
255263
address: &Ctx::Address,
256264
) -> Transition<Ctx>
@@ -264,6 +272,7 @@ where
264272
// L16
265273
let pol_round = round_value.round;
266274
let proposal = Output::proposal(
275+
ctx,
267276
state.height,
268277
state.round,
269278
round_value.value.clone(),
@@ -294,6 +303,7 @@ where
294303
///
295304
/// Ref: L13, L17-18
296305
pub fn propose<Ctx>(
306+
ctx: &Ctx,
297307
mut state: State<Ctx>,
298308
value: Ctx::Value,
299309
address: &Ctx::Address,
@@ -302,6 +312,7 @@ where
302312
Ctx: Context,
303313
{
304314
let proposal = Output::proposal(
315+
ctx,
305316
state.height,
306317
state.round,
307318
value,
@@ -322,6 +333,7 @@ where
322333
///
323334
/// Ref: L22 with valid proposal
324335
pub fn prevote<Ctx>(
336+
ctx: &Ctx,
325337
mut state: State<Ctx>,
326338
address: &Ctx::Address,
327339
proposal: &Ctx::Proposal,
@@ -350,7 +362,7 @@ where
350362
}
351363
};
352364

353-
let output = Output::prevote(state.height, state.round, value, address.clone());
365+
let output = Output::prevote(ctx, state.height, state.round, value, address.clone());
354366
Transition::to(state.with_step(Step::Prevote)).with_output(output)
355367
}
356368

@@ -359,6 +371,7 @@ where
359371
///
360372
/// Ref: L28
361373
pub fn prevote_previous<Ctx>(
374+
ctx: &Ctx,
362375
mut state: State<Ctx>,
363376
address: &Ctx::Address,
364377
proposal: &Ctx::Proposal,
@@ -394,18 +407,19 @@ where
394407
}
395408
};
396409

397-
let output = Output::prevote(state.height, state.round, value, address.clone());
410+
let output = Output::Vote(ctx.new_prevote(state.height, state.round, value, address.clone()));
398411
Transition::to(state.with_step(Step::Prevote)).with_output(output)
399412
}
400413

401414
/// Received a complete proposal for an empty or invalid value, or timed out; prevote nil.
402415
///
403416
/// Ref: L22/L25, L28/L31, L57
404-
pub fn prevote_nil<Ctx>(state: State<Ctx>, address: &Ctx::Address) -> Transition<Ctx>
417+
pub fn prevote_nil<Ctx>(ctx: &Ctx, state: State<Ctx>, address: &Ctx::Address) -> Transition<Ctx>
405418
where
406419
Ctx: Context,
407420
{
408-
let output = Output::prevote(state.height, state.round, NilOrVal::Nil, address.clone());
421+
let output =
422+
Output::Vote(ctx.new_prevote(state.height, state.round, NilOrVal::Nil, address.clone()));
409423

410424
Transition::to(state.with_step(Step::Prevote)).with_output(output)
411425
}
@@ -421,6 +435,7 @@ where
421435
/// NOTE: Only one of this and set_valid_value should be called once in a round
422436
/// How do we enforce this?
423437
pub fn precommit<Ctx>(
438+
ctx: &Ctx,
424439
state: State<Ctx>,
425440
address: &Ctx::Address,
426441
proposal: Ctx::Proposal,
@@ -434,6 +449,7 @@ where
434449

435450
let value = proposal.value();
436451
let output = Output::precommit(
452+
ctx,
437453
state.height,
438454
state.round,
439455
NilOrVal::Val(value.id()),
@@ -451,11 +467,13 @@ where
451467
/// Received a polka for nil or timed out of prevote; precommit nil.
452468
///
453469
/// Ref: L44, L61
454-
pub fn precommit_nil<Ctx>(state: State<Ctx>, address: &Ctx::Address) -> Transition<Ctx>
470+
pub fn precommit_nil<Ctx>(ctx: &Ctx, state: State<Ctx>, address: &Ctx::Address) -> Transition<Ctx>
455471
where
456472
Ctx: Context,
457473
{
458-
let output = Output::precommit(state.height, state.round, NilOrVal::Nil, address.clone());
474+
let output =
475+
Output::Vote(ctx.new_precommit(state.height, state.round, NilOrVal::Nil, address.clone()));
476+
459477
Transition::to(state.with_step(Step::Precommit)).with_output(output)
460478
}
461479

code/crates/core-types/src/context.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ where
5050

5151
/// Build a new proposal for the given value at the given height, round and POL round.
5252
fn new_proposal(
53+
&self,
5354
height: Self::Height,
5455
round: Round,
5556
value: Self::Value,
@@ -60,6 +61,7 @@ where
6061
/// Build a new prevote vote by the validator with the given address,
6162
/// for the value identified by the given value id, at the given round.
6263
fn new_prevote(
64+
&self,
6365
height: Self::Height,
6466
round: Round,
6567
value_id: NilOrVal<ValueId<Self>>,
@@ -69,6 +71,7 @@ where
6971
/// Build a new precommit vote by the validator with the given address,
7072
/// for the value identified by the given value id, at the given round.
7173
fn new_precommit(
74+
&self,
7275
height: Self::Height,
7376
round: Round,
7477
value_id: NilOrVal<ValueId<Self>>,

code/crates/starknet/p2p-types/src/context.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ impl Context for MockContext {
5151
}
5252

5353
fn new_proposal(
54+
&self,
5455
height: Height,
5556
round: Round,
5657
value_id: Hash,
@@ -61,6 +62,7 @@ impl Context for MockContext {
6162
}
6263

6364
fn new_prevote(
65+
&self,
6466
height: Height,
6567
round: Round,
6668
value_id: NilOrVal<Hash>,
@@ -70,6 +72,7 @@ impl Context for MockContext {
7072
}
7173

7274
fn new_precommit(
75+
&self,
7376
height: Height,
7477
round: Round,
7578
value_id: NilOrVal<Hash>,

code/crates/test/Cargo.toml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,7 @@ malachitebft-core-types = { workspace = true }
1717
malachitebft-config = { workspace = true }
1818
malachitebft-core-consensus = { workspace = true }
1919
malachitebft-proto = { workspace = true }
20-
malachitebft-signing-ed25519 = { workspace = true, features = [
21-
"rand",
22-
"serde",
23-
] }
20+
malachitebft-signing-ed25519 = { workspace = true, features = ["rand", "serde"] }
2421
malachitebft-sync = { workspace = true }
2522

2623
async-trait = { workspace = true }

0 commit comments

Comments
 (0)