-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
562 additions
and
488 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
use std::time::{Duration, Instant}; | ||
|
||
/// Adjustable limits for block size ceiled by | ||
/// maximum block size allowed by the protocol | ||
#[derive(Debug, Clone)] | ||
pub struct BlockSizeLimits { | ||
// maximum block size allowed by the protocol | ||
pub protocol_max_block_size: u64, | ||
// estimated maximum block size we can build in time | ||
pub max_block_size: u64, | ||
pub increment_period: Duration, | ||
pub last_block_size_increment: Instant, | ||
} | ||
|
||
impl BlockSizeLimits { | ||
/// Never go lower than 10 kilobytes | ||
pub const MAX_BLOCK_SIZE_FLOOR: u64 = 10_000; | ||
/// When adjusting max block size, it will be decremented or incremented | ||
/// by current value / `MAX_BLOCK_SIZE_CHANGE_DIVISOR` | ||
pub const MAX_BLOCK_SIZE_CHANGE_DIVISOR: u64 = 10; | ||
|
||
pub fn new(protocol_max_block_size: u64, increment_period: Duration) -> Self { | ||
Self { | ||
protocol_max_block_size, | ||
max_block_size: protocol_max_block_size, | ||
increment_period, | ||
last_block_size_increment: Instant::now(), | ||
} | ||
} | ||
|
||
/// If increment period has elapsed or `force` flag is set, | ||
/// increment [`Self::max_block_size`] by current value * [`Self::MAX_BLOCK_SIZE_CHANGE_DIVISOR`] | ||
/// with [`Self::protocol_max_block_size`] as a ceiling | ||
pub fn try_increment_block_size(&mut self, force: bool) { | ||
if force || self.last_block_size_increment.elapsed() >= self.increment_period { | ||
self.max_block_size = std::cmp::min( | ||
self.max_block_size | ||
+ self | ||
.max_block_size | ||
.div_ceil(Self::MAX_BLOCK_SIZE_CHANGE_DIVISOR), | ||
self.protocol_max_block_size, | ||
); | ||
self.last_block_size_increment = Instant::now(); | ||
} | ||
} | ||
|
||
/// Decrement [`Self::max_block_size`] by current value * [`Self::MAX_BLOCK_SIZE_CHANGE_DIVISOR`] | ||
/// with [`Self::MAX_BLOCK_SIZE_FLOOR`] as a floor | ||
pub fn decrement_block_size(&mut self) { | ||
self.max_block_size = std::cmp::max( | ||
self.max_block_size | ||
- self | ||
.max_block_size | ||
.div_ceil(Self::MAX_BLOCK_SIZE_CHANGE_DIVISOR), | ||
Self::MAX_BLOCK_SIZE_FLOOR, | ||
); | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use marketplace_builder_shared::testing::constants::{ | ||
TEST_MAX_BLOCK_SIZE_INCREMENT_PERIOD, TEST_PROTOCOL_MAX_BLOCK_SIZE, | ||
}; | ||
|
||
use super::*; | ||
|
||
#[test] | ||
fn test_increment_block_size() { | ||
let mut block_size_limits = | ||
BlockSizeLimits::new(TEST_PROTOCOL_MAX_BLOCK_SIZE, Duration::from_millis(25)); | ||
// Simulate decreased limits | ||
block_size_limits.max_block_size = TEST_PROTOCOL_MAX_BLOCK_SIZE / 2; | ||
|
||
// Shouldn't increment, increment period hasn't passed yet | ||
block_size_limits.try_increment_block_size(false); | ||
assert!(block_size_limits.max_block_size == TEST_PROTOCOL_MAX_BLOCK_SIZE / 2); | ||
|
||
// Should increment, increment period hasn't passed yet, but force flag is set | ||
block_size_limits.try_increment_block_size(true); | ||
assert!(block_size_limits.max_block_size > TEST_PROTOCOL_MAX_BLOCK_SIZE / 2); | ||
let new_size = block_size_limits.max_block_size; | ||
|
||
std::thread::sleep(Duration::from_millis(30)); | ||
|
||
// Should increment, increment period has passed | ||
block_size_limits.try_increment_block_size(false); | ||
assert!(block_size_limits.max_block_size > new_size); | ||
} | ||
|
||
#[test] | ||
fn test_decrement_block_size() { | ||
let mut block_size_limits = BlockSizeLimits::new( | ||
TEST_PROTOCOL_MAX_BLOCK_SIZE, | ||
TEST_MAX_BLOCK_SIZE_INCREMENT_PERIOD, | ||
); | ||
block_size_limits.decrement_block_size(); | ||
assert!(block_size_limits.max_block_size < TEST_PROTOCOL_MAX_BLOCK_SIZE); | ||
} | ||
|
||
#[test] | ||
fn test_max_block_size_floor() { | ||
let mut block_size_limits = BlockSizeLimits::new( | ||
BlockSizeLimits::MAX_BLOCK_SIZE_FLOOR + 1, | ||
TEST_MAX_BLOCK_SIZE_INCREMENT_PERIOD, | ||
); | ||
block_size_limits.decrement_block_size(); | ||
assert_eq!( | ||
block_size_limits.max_block_size, | ||
BlockSizeLimits::MAX_BLOCK_SIZE_FLOOR | ||
); | ||
} | ||
} |
Oops, something went wrong.