Skip to content

Commit 59e061b

Browse files
authored
⚡️ Improve phase transition points and fix instant-mode (#298)
## What? - Fix instant-mode benchmarks - Improve dry-run-benches just command - Improve phase transition points ## Why? - The calculation on the instantiator was inaccurate because the phase transition points were 1 block off - Just command can now run for a specific mode and runtime ## How? - Now the start block of a state is the same block where on_initialize is called. Before it was the next block, even though the current one was still possible to call the extrinsics for that state ## Testing? `just dry-run-benchmarks instant-mode`
1 parent 73d796e commit 59e061b

12 files changed

+113
-172
lines changed

justfile

+20-14
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,31 @@ test-runtime-features runtime="polimec-runtime":
2121
test-integration:
2222
cargo test -p integration-tests
2323

24-
dry-run-benchmarks runtime="politest,polimec" pallet="*" extrinsic="*" :
24+
dry-run-benchmarks mode="fast-mode" runtime="politest,polimec" pallet="*" extrinsic="*" :
2525
#!/bin/bash
2626
# Set the internal field separator for splitting the runtime variable
2727
IFS=','
2828
# Read the runtime variable into an array
2929
read -ra runtimes <<< "{{runtime}}"
30-
# Build the project
31-
cargo build --features runtime-benchmarks --release
32-
# Loop over each runtime and run the benchmark
33-
for runtime in "${runtimes[@]}"; do \
34-
echo -e "\033[34mRunning benchmarks for runtime: \033[92m$runtime\033[34m\033[0m"
35-
./target/release/polimec-node benchmark pallet \
36-
--chain=${runtime}-local \
37-
--steps=2 \
38-
--repeat=1 \
39-
--pallet={{ pallet }} \
40-
--extrinsic={{ extrinsic }} \
41-
--wasm-execution=compiled \
42-
--heap-pages=4096
30+
read -ra modes <<< "{{mode}}"
31+
32+
# Build the project with each mode
33+
for mode in "${modes[@]}"; do \
34+
echo -e "\033[34mBuilding runtime with mode: \033[92m$mode\033[34m\033[0m"
35+
cargo build --features runtime-benchmarks,$mode --release
36+
# Loop over each runtime and run the benchmark
37+
for runtime in "${runtimes[@]}"; do \
38+
echo -e "\033[34mRunning benchmarks for runtime: \033[92m$runtime\033[34m\033[0m"
39+
40+
./target/release/polimec-node benchmark pallet \
41+
--chain=${runtime}-local \
42+
--steps=2 \
43+
--repeat=1 \
44+
--pallet={{ pallet }} \
45+
--extrinsic={{ extrinsic }} \
46+
--wasm-execution=compiled \
47+
--heap-pages=4096
48+
done
4349
done
4450

4551
# src: https://github.com/polkadot-fellows/runtimes/blob/48ccfae6141d2924f579d81e8b1877efd208693f/system-parachains/asset-hubs/asset-hub-polkadot/src/weights/cumulus_pallet_xcmp_queue.rs

pallets/funding/src/benchmarking.rs

+3-14
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,7 @@ mod benchmarks {
639639

640640
let current_block = inst.current_block();
641641
// `do_auction_opening` fn will try to add an automatic transition 1 block after the last opening round block
642-
let insertion_block_number: BlockNumberFor<T> = current_block + T::AuctionOpeningDuration::get() + One::one();
642+
let insertion_block_number: BlockNumberFor<T> = current_block + T::AuctionOpeningDuration::get();
643643

644644
fill_projects_to_update::<T>(x, insertion_block_number);
645645

@@ -2108,19 +2108,8 @@ mod benchmarks {
21082108

21092109
inst.bid_for_users(project_id, accepted_bids).unwrap();
21102110

2111-
let now = inst.current_block();
2112-
frame_system::Pallet::<T>::set_block_number(now + <T as Config>::AuctionOpeningDuration::get());
2113-
// automatic transition to opening auction
2114-
inst.advance_time(1u32.into()).unwrap();
2115-
2116-
let project_details = inst.get_project_details(project_id);
2117-
let auction_closing_block_end = project_details.phase_transition_points.auction_closing.end().unwrap();
2118-
// probably the last block will always be after random end
2119-
let random_ending: BlockNumberFor<T> = auction_closing_block_end;
2120-
frame_system::Pallet::<T>::set_block_number(random_ending);
2121-
2122-
inst.bid_for_users(project_id, rejected_bids).unwrap();
2123-
2111+
let transition_block = inst.get_update_block(project_id, &UpdateType::AuctionClosingStart).unwrap();
2112+
inst.jump_to_block(transition_block);
21242113
let auction_closing_end_block =
21252114
inst.get_project_details(project_id).phase_transition_points.auction_closing.end().unwrap();
21262115
// we don't use advance time to avoid triggering on_initialize. This benchmark should only measure the fn

pallets/funding/src/functions.rs

+14-13
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,9 @@ impl<T: Config> Pallet<T> {
8585
ensure!(project_metadata.policy_ipfs_cid.is_some(), Error::<T>::CidNotProvided);
8686

8787
// * Calculate new variables *
88-
let evaluation_end_block = now + T::EvaluationDuration::get();
88+
let evaluation_end_block = now.saturating_add(T::EvaluationDuration::get()).saturating_sub(One::one());
8989
project_details.phase_transition_points.application.update(None, Some(now));
90-
project_details.phase_transition_points.evaluation.update(Some(now + 1u32.into()), Some(evaluation_end_block));
90+
project_details.phase_transition_points.evaluation.update(Some(now), Some(evaluation_end_block));
9191
project_details.is_frozen = true;
9292
project_details.status = ProjectStatus::EvaluationRound;
9393

@@ -162,9 +162,10 @@ impl<T: Config> Pallet<T> {
162162
let usd_total_amount_bonded = project_details.evaluation_round_info.total_bonded_usd;
163163
let evaluation_target_usd = <T as Config>::EvaluationSuccessThreshold::get() * fundraising_target_usd;
164164

165-
let auction_initialize_period_start_block = now + 1u32.into();
166-
let auction_initialize_period_end_block =
167-
auction_initialize_period_start_block + T::AuctionInitializePeriodDuration::get();
165+
let auction_initialize_period_start_block = now;
166+
let auction_initialize_period_end_block = auction_initialize_period_start_block
167+
.saturating_add(T::AuctionInitializePeriodDuration::get())
168+
.saturating_sub(One::one());
168169

169170
// Check which logic path to follow
170171
let is_funded = usd_total_amount_bonded >= evaluation_target_usd;
@@ -267,8 +268,8 @@ impl<T: Config> Pallet<T> {
267268
ensure!(project_details.status == ProjectStatus::AuctionInitializePeriod, Error::<T>::IncorrectRound);
268269

269270
// * Calculate new variables *
270-
let opening_start_block = now + 1u32.into();
271-
let opening_end_block = now + T::AuctionOpeningDuration::get();
271+
let opening_start_block = now;
272+
let opening_end_block = now.saturating_add(T::AuctionOpeningDuration::get()).saturating_sub(One::one());
272273

273274
// * Update Storage *
274275
project_details
@@ -340,8 +341,8 @@ impl<T: Config> Pallet<T> {
340341
ensure!(project_details.status == ProjectStatus::AuctionOpening, Error::<T>::IncorrectRound);
341342

342343
// * Calculate new variables *
343-
let closing_start_block = now + 1u32.into();
344-
let closing_end_block = now + T::AuctionClosingDuration::get();
344+
let closing_start_block = now;
345+
let closing_end_block = now.saturating_add(T::AuctionClosingDuration::get()).saturating_sub(One::one());
345346

346347
// * Update Storage *
347348
project_details
@@ -407,8 +408,8 @@ impl<T: Config> Pallet<T> {
407408

408409
// * Calculate new variables *
409410
let end_block = Self::select_random_block(auction_closing_start_block, auction_closing_end_block);
410-
let community_start_block = now + 1u32.into();
411-
let community_end_block = now + T::CommunityFundingDuration::get();
411+
let community_start_block = now;
412+
let community_end_block = now.saturating_add(T::CommunityFundingDuration::get()).saturating_sub(One::one());
412413
// * Update Storage *
413414
let calculation_result = Self::calculate_weighted_average_price(
414415
project_id,
@@ -495,8 +496,8 @@ impl<T: Config> Pallet<T> {
495496
);
496497

497498
// * Calculate new variables *
498-
let remainder_start_block = now + 1u32.into();
499-
let remainder_end_block = now + T::RemainderFundingDuration::get();
499+
let remainder_start_block = now;
500+
let remainder_end_block = now.saturating_add(T::RemainderFundingDuration::get()).saturating_sub(One::one());
500501

501502
// * Update Storage *
502503
project_details

pallets/funding/src/instantiator/async_features.rs

+12-6
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ pub async fn async_create_evaluating_project<
171171
let mut inst = instantiator.lock().await;
172172

173173
inst.start_evaluation(project_id, issuer).unwrap();
174+
let now = inst.current_block();
174175
project_id
175176
}
176177

@@ -191,7 +192,7 @@ pub async fn async_start_auction<
191192
if project_details.status == ProjectStatus::EvaluationRound {
192193
let update_block = inst.get_update_block(project_id, &UpdateType::EvaluationEnd).unwrap();
193194
let notify = Arc::new(Notify::new());
194-
block_orchestrator.add_awaiting_project(update_block + 1u32.into(), notify.clone()).await;
195+
block_orchestrator.add_awaiting_project(update_block, notify.clone()).await;
195196

196197
// Wait for the notification that our desired block was reached to continue
197198
drop(inst);
@@ -282,7 +283,7 @@ pub async fn async_start_community_funding<
282283
let mut inst = instantiator.lock().await;
283284

284285
let update_block = inst.get_update_block(project_id, &UpdateType::AuctionClosingStart).unwrap();
285-
let closing_start = update_block + 1u32.into();
286+
let closing_start = update_block;
286287

287288
let notify = Arc::new(Notify::new());
288289

@@ -296,7 +297,7 @@ pub async fn async_start_community_funding<
296297

297298
inst = instantiator.lock().await;
298299
let update_block = inst.get_update_block(project_id, &UpdateType::CommunityFundingStart).unwrap();
299-
let community_start = update_block + 1u32.into();
300+
let community_start = update_block;
300301

301302
let notify = Arc::new(Notify::new());
302303

@@ -433,7 +434,7 @@ pub async fn async_start_remainder_or_end_funding<
433434
assert_eq!(inst.get_project_details(project_id).status, ProjectStatus::CommunityRound);
434435

435436
let update_block = inst.get_update_block(project_id, &UpdateType::RemainderFundingStart).unwrap();
436-
let remainder_start = update_block + 1u32.into();
437+
let remainder_start = update_block;
437438

438439
let notify = Arc::new(Notify::new());
439440

@@ -550,7 +551,9 @@ pub async fn async_finish_funding<
550551
let update_block = inst.get_update_block(project_id, &UpdateType::FundingEnd).unwrap();
551552

552553
let notify = Arc::new(Notify::new());
553-
block_orchestrator.add_awaiting_project(update_block + 1u32.into(), notify.clone()).await;
554+
block_orchestrator.add_awaiting_project(update_block, notify.clone()).await;
555+
drop(inst);
556+
notify.notified().await;
554557
Ok(())
555558
}
556559

@@ -768,7 +771,9 @@ pub async fn async_create_project_at<
768771
let time_to_community: BlockNumberFor<T> =
769772
time_to_auction + <T as Config>::AuctionOpeningDuration::get() + <T as Config>::AuctionClosingDuration::get();
770773
let time_to_remainder: BlockNumberFor<T> = time_to_community + <T as Config>::CommunityFundingDuration::get();
771-
let time_to_finish: BlockNumberFor<T> = time_to_remainder + <T as Config>::RemainderFundingDuration::get();
774+
let time_to_finish: BlockNumberFor<T> = time_to_remainder +
775+
<T as Config>::RemainderFundingDuration::get() +
776+
<T as Config>::SuccessToSettlementTime::get();
772777
let mut inst = mutex_inst.lock().await;
773778
let now = inst.current_block();
774779
drop(inst);
@@ -786,6 +791,7 @@ pub async fn async_create_project_at<
786791
block_orchestrator.add_awaiting_project(now + time_to_finish - time_to_evaluation, notify.clone()).await;
787792
// Wait for the notification that our desired block was reached to continue
788793
notify.notified().await;
794+
let now = mutex_inst.lock().await.current_block();
789795
async_create_evaluating_project(
790796
mutex_inst.clone(),
791797
test_project_params.metadata,

pallets/funding/src/instantiator/chain_interactions.rs

+25-24
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,16 @@ impl<
165165
})
166166
}
167167

168+
pub fn jump_to_block(&mut self, block: BlockNumberFor<T>) {
169+
let current_block = self.current_block();
170+
if block > current_block {
171+
self.execute(|| frame_system::Pallet::<T>::set_block_number(block - One::one()));
172+
self.advance_time(One::one()).unwrap();
173+
} else {
174+
panic!("Cannot jump to a block in the present or past")
175+
}
176+
}
177+
168178
pub fn do_free_plmc_assertions(&mut self, correct_funds: Vec<UserToPLMCBalance<T>>) {
169179
for UserToPLMCBalance { account, plmc_amount } in correct_funds {
170180
self.execute(|| {
@@ -230,6 +240,10 @@ impl<
230240
pub fn test_ct_created_for(&mut self, project_id: ProjectId) {
231241
self.execute(|| {
232242
let metadata = ProjectsMetadata::<T>::get(project_id).unwrap();
243+
assert!(
244+
<T as Config>::ContributionTokenCurrency::asset_exists(project_id),
245+
"Asset should exist, since funding was successful"
246+
);
233247
assert_eq!(
234248
<T as Config>::ContributionTokenCurrency::name(project_id),
235249
metadata.token_information.name.to_vec()
@@ -430,10 +444,9 @@ impl<
430444
let project_details = self.get_project_details(project_id);
431445

432446
if project_details.status == ProjectStatus::EvaluationRound {
433-
let evaluation_end = project_details.phase_transition_points.evaluation.end().unwrap();
434-
let auction_start = evaluation_end.saturating_add(2u32.into());
435-
let blocks_to_start = auction_start.saturating_sub(self.current_block());
436-
self.advance_time(blocks_to_start + 1u32.into()).unwrap();
447+
let now = self.current_block();
448+
let evaluation_end_execution = self.get_update_block(project_id, &UpdateType::EvaluationEnd).unwrap();
449+
self.advance_time(evaluation_end_execution - now).unwrap();
437450
};
438451

439452
assert_eq!(self.get_project_details(project_id).status, ProjectStatus::AuctionInitializePeriod);
@@ -501,26 +514,14 @@ impl<
501514
}
502515

503516
pub fn start_community_funding(&mut self, project_id: ProjectId) -> Result<(), DispatchError> {
504-
let opening_end = self
505-
.get_project_details(project_id)
506-
.phase_transition_points
507-
.auction_opening
508-
.end()
509-
.expect("Auction Opening end point should exist");
510-
511-
self.execute(|| frame_system::Pallet::<T>::set_block_number(opening_end));
512-
// run on_initialize
513-
self.advance_time(2u32.into()).unwrap();
514-
515-
let closing_end = self
516-
.get_project_details(project_id)
517-
.phase_transition_points
518-
.auction_closing
519-
.end()
520-
.expect("closing end point should exist");
521-
522-
self.execute(|| frame_system::Pallet::<T>::set_block_number(closing_end));
523-
// run on_initialize
517+
if let Some(update_block) = self.get_update_block(project_id, &UpdateType::AuctionClosingStart) {
518+
self.execute(|| frame_system::Pallet::<T>::set_block_number(update_block - One::one()));
519+
self.advance_time(1u32.into()).unwrap();
520+
}
521+
let Some(update_block) = self.get_update_block(project_id, &UpdateType::CommunityFundingStart) else {
522+
unreachable!()
523+
};
524+
self.execute(|| frame_system::Pallet::<T>::set_block_number(update_block - One::one()));
524525
self.advance_time(1u32.into()).unwrap();
525526

526527
ensure!(

pallets/funding/src/mock.rs

+9-8
Original file line numberDiff line numberDiff line change
@@ -290,14 +290,15 @@ pub const HOURS: BlockNumber = 300u64;
290290

291291
// REMARK: In the production configuration we use DAYS instead of HOURS.
292292
parameter_types! {
293-
pub const EvaluationDuration: BlockNumber = (28 * HOURS) as BlockNumber;
294-
pub const AuctionInitializePeriodDuration: BlockNumber = (7 * HOURS) as BlockNumber;
295-
pub const AuctionOpeningDuration: BlockNumber = (2 * HOURS) as BlockNumber;
296-
pub const AuctionClosingDuration: BlockNumber = (3 * HOURS) as BlockNumber;
297-
pub const CommunityRoundDuration: BlockNumber = (5 * HOURS) as BlockNumber;
298-
pub const RemainderFundingDuration: BlockNumber = (1 * HOURS) as BlockNumber;
299-
pub const ManualAcceptanceDuration: BlockNumber = (3 * HOURS) as BlockNumber;
300-
pub const SuccessToSettlementTime: BlockNumber =(4 * HOURS) as BlockNumber;
293+
pub const EvaluationDuration: BlockNumber = 3u64;
294+
pub const AuctionInitializePeriodDuration: BlockNumber = 3u64;
295+
pub const AuctionOpeningDuration: BlockNumber = 3u64;
296+
pub const AuctionClosingDuration: BlockNumber = 3u64;
297+
pub const CommunityRoundDuration: BlockNumber = 3u64;
298+
pub const RemainderFundingDuration: BlockNumber = 3u64;
299+
pub const ManualAcceptanceDuration: BlockNumber = 3u64;
300+
pub const SuccessToSettlementTime: BlockNumber = 3u64;
301+
301302
pub const FundingPalletId: PalletId = PalletId(*b"py/cfund");
302303
pub FeeBrackets: Vec<(Percent, Balance)> = vec![
303304
(Percent::from_percent(10), 1_000_000 * USD_UNIT),

pallets/funding/src/tests/2_evaluation.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,8 @@ mod start_evaluation_extrinsic {
305305
phase_transition_points: PhaseTransitionPoints {
306306
application: BlockNumberPair { start: Some(1u64), end: Some(1u64) },
307307
evaluation: BlockNumberPair {
308-
start: Some(2u64),
309-
end: Some(1u64 + <TestRuntime as Config>::EvaluationDuration::get()),
308+
start: Some(1u64),
309+
end: Some(<TestRuntime as Config>::EvaluationDuration::get()),
310310
},
311311
auction_initialize_period: BlockNumberPair { start: None, end: None },
312312
auction_opening: BlockNumberPair { start: None, end: None },

pallets/funding/src/tests/3_auction.rs

+13-9
Original file line numberDiff line numberDiff line change
@@ -722,10 +722,14 @@ mod start_auction_extrinsic {
722722
inst.mint_plmc_to(required_plmc);
723723
inst.mint_plmc_to(ed_plmc);
724724
inst.evaluate_for_users(project_id, evaluations).unwrap();
725-
inst.advance_time(<TestRuntime as Config>::EvaluationDuration::get() + 1).unwrap();
726-
assert_eq!(inst.get_project_details(project_id).status, ProjectStatus::AuctionInitializePeriod);
727-
inst.advance_time(<TestRuntime as Config>::AuctionInitializePeriodDuration::get() + 2).unwrap();
728-
assert_eq!(inst.get_project_details(project_id).status, ProjectStatus::AuctionOpening);
725+
726+
let update_block = inst.get_update_block(project_id, &UpdateType::EvaluationEnd).unwrap();
727+
inst.execute(|| System::set_block_number(update_block - 1));
728+
inst.advance_time(1).unwrap();
729+
730+
let update_block = inst.get_update_block(project_id, &UpdateType::AuctionOpeningStart).unwrap();
731+
inst.execute(|| System::set_block_number(update_block - 1));
732+
inst.advance_time(1).unwrap();
729733
}
730734

731735
#[test]
@@ -809,15 +813,15 @@ mod start_auction_extrinsic {
809813
inst.mint_plmc_to(required_plmc);
810814
inst.mint_plmc_to(ed_plmc);
811815
inst.evaluate_for_users(project_id, evaluations).unwrap();
812-
inst.advance_time(<TestRuntime as Config>::EvaluationDuration::get() + 1).unwrap();
813-
inst.advance_time(<TestRuntime as Config>::AuctionInitializePeriodDuration::get() + 2).unwrap();
814-
assert_eq!(inst.get_project_details(project_id).status, ProjectStatus::AuctionOpening);
816+
inst.start_auction(project_id, ISSUER_1).unwrap();
815817

816818
// Main test with failed evaluation
817819
let mut inst = MockInstantiator::new(Some(RefCell::new(new_test_ext())));
818820
let project_id = inst.create_evaluating_project(default_project_metadata(ISSUER_1), ISSUER_1);
819-
inst.advance_time(<TestRuntime as Config>::EvaluationDuration::get() + 1).unwrap();
820-
inst.advance_time(<TestRuntime as Config>::AuctionInitializePeriodDuration::get() + 2).unwrap();
821+
822+
let evaluation_end_execution = inst.get_update_block(project_id, &UpdateType::EvaluationEnd).unwrap();
823+
inst.execute(|| System::set_block_number(evaluation_end_execution - 1));
824+
inst.advance_time(1).unwrap();
821825
assert_eq!(inst.get_project_details(project_id).status, ProjectStatus::FundingFailed);
822826
}
823827
}

pallets/funding/src/tests/4_community.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,7 @@ mod community_contribute_extrinsic {
760760
inst.bid_for_users(project_id, successful_bids).unwrap();
761761
inst.advance_time(
762762
<TestRuntime as Config>::AuctionOpeningDuration::get() +
763-
<TestRuntime as Config>::AuctionClosingDuration::get() +
763+
<TestRuntime as Config>::AuctionClosingDuration::get() -
764764
1,
765765
)
766766
.unwrap();

pallets/funding/src/tests/6_funding_end.rs

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ fn automatic_acceptance_on_manual_decision_after_time_delta() {
5656
let project_id = project_id;
5757
inst.advance_time(1u64 + <TestRuntime as Config>::ManualAcceptanceDuration::get()).unwrap();
5858
assert_eq!(inst.get_project_details(project_id).status, ProjectStatus::FundingSuccessful);
59+
dbg!(inst.get_project_details(project_id));
5960
inst.advance_time(<TestRuntime as Config>::SuccessToSettlementTime::get()).unwrap();
6061

6162
inst.test_ct_created_for(project_id);

0 commit comments

Comments
 (0)