Skip to content

Commit 75509b6

Browse files
committed
min multiplier definition and testing
1 parent a573244 commit 75509b6

File tree

4 files changed

+131
-22
lines changed

4 files changed

+131
-22
lines changed

sugondat/chain/runtimes/sugondat-kusama/src/lib.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight};
6565
use xcm::latest::prelude::BodyId;
6666

6767
pub use pallet_sugondat_blobs;
68+
pub use pallet_sugondat_length_fee_adjustment;
6869

6970
/// A hash of some data used by the chain.
7071
pub type Hash = sp_core::H256;
@@ -287,8 +288,10 @@ parameter_types! {
287288
// v = p / k * (1 - s*) = 0.3 / (300 * (1 - 0.16))
288289
// at most 30% (=p) fees variation in one hour, 300 blocks (=k)
289290
pub AdjustmentVariableBlockSize: Multiplier = Multiplier::saturating_from_rational(1, 840);
290-
// TODO: decide the value of MinimumMultiplierBlockSize, https://github.com/thrumdev/blobs/issues/154
291-
pub MinimumMultiplierBlockSize: Multiplier = Multiplier::saturating_from_rational(1, 10u128);
291+
// Using an adjustment variable block size of 1/840
292+
// and a minimum multiplier block size of 1/200,
293+
// it would require 5298 full blocks to grow back to one.
294+
pub MinimumMultiplierBlockSize: Multiplier = Multiplier::saturating_from_rational(1, 200u128);
292295
pub MaximumMultiplierBlockSize: Multiplier = Bounded::max_value();
293296
}
294297

sugondat/chain/runtimes/sugondat-kusama/tests/fee_adjustments.rs

+61-9
Original file line numberDiff line numberDiff line change
@@ -142,14 +142,6 @@ impl MultiplierType {
142142
}
143143
}
144144

145-
// k = 1 / (v * s*)
146-
fn k_bound(&self) -> u64 {
147-
(Multiplier::saturating_from_integer(1)
148-
/ (self.target_percentage() * self.adjustment_variable()))
149-
.to_float()
150-
.ceil() as u64
151-
}
152-
153145
fn run_with<F>(&self, w: Weight, assertions: F)
154146
where
155147
F: Fn() -> (),
@@ -248,6 +240,10 @@ fn multiplier_cannot_go_below_limit() {
248240

249241
#[test]
250242
fn time_to_reach_zero() {
243+
// TODO: 1440 needs to be used instead of 7200
244+
// when updating to asynchronous backing
245+
// https://github.com/thrumdev/blobs/issues/166
246+
//
251247
// blocks per 24h in cumulus-node: 7200 (k)
252248
// s* = 0.1875 (TargetBlockFullness) or 0.16 (TargetBlockSize)
253249
// The bound from the research in an empty chain is:
@@ -268,7 +264,11 @@ fn time_to_reach_zero() {
268264
// start from 1, the default.
269265
let mut fm = Multiplier::one();
270266
let mut iterations: u64 = 0;
271-
let limit = mul_type.k_bound();
267+
let limit = (Multiplier::saturating_from_integer(1)
268+
/ (mul_type.target_percentage() * mul_type.adjustment_variable()))
269+
.to_float()
270+
.ceil() as u64;
271+
272272
loop {
273273
let next = mul_type.runtime_multiplier_update(fm);
274274
fm = next;
@@ -285,6 +285,54 @@ fn time_to_reach_zero() {
285285
test(MultiplierType::Length);
286286
}
287287

288+
#[test]
289+
fn time_to_reach_one() {
290+
// TODO: 1440 needs to ne used insted of 7200
291+
// when updating to asynchronous backing
292+
// https://github.com/thrumdev/blobs/issues/166
293+
//
294+
// blocks per 24h in cumulus-node: 7200 (k)
295+
// s* = 0.1875 (TargetBlockFullness) or 0.16 (TargetBlockSize)
296+
// The bound from the research in an full chain is:
297+
// v <~ (p / k(1 - s*))
298+
// p > v * k * (1 - s*)
299+
// to get p == 1 we'd need (going from zero to target)
300+
// 1 > v * k * (1 - s*)
301+
// k < 1 / (v * (1 - s*))
302+
303+
// if s* = 0.1875
304+
// then k > 17_778 ~ 2.47 days
305+
// else s* = 0.16
306+
// then k > 1000 ~ 3.3 hours
307+
308+
let test = |mul_type: MultiplierType| {
309+
mul_type.run_with(mul_type.max(), || {
310+
// start from min_multiplier, the default.
311+
let mut fm = mul_type.min_multiplier();
312+
let mut iterations: u64 = 0;
313+
314+
let limit = (Multiplier::saturating_from_integer(1)
315+
/ ((Multiplier::saturating_from_integer(1) - mul_type.target_percentage())
316+
* mul_type.adjustment_variable()))
317+
.to_float()
318+
.ceil() as u64;
319+
320+
loop {
321+
let next = mul_type.runtime_multiplier_update(fm);
322+
fm = next;
323+
if fm >= Multiplier::one() {
324+
break;
325+
}
326+
iterations += 1;
327+
}
328+
assert!(iterations > limit);
329+
})
330+
};
331+
332+
test(MultiplierType::Fee);
333+
test(MultiplierType::Length);
334+
}
335+
288336
#[test]
289337
fn min_change_per_day() {
290338
let test = |mul_type: MultiplierType| {
@@ -296,6 +344,10 @@ fn min_change_per_day() {
296344
let next = mul_type.runtime_multiplier_update(fm);
297345
fm = next;
298346
}
347+
// TODO: 1440 needs to ne used insted of 7200
348+
// when updating to asynchronous backing
349+
// https://github.com/thrumdev/blobs/issues/166
350+
//
299351
// 7200 blocks per day with one 12 seconds blocks
300352
// v * k * (1 - s)
301353
let expected = mul_type.adjustment_variable()

sugondat/chain/runtimes/test/src/lib.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -355,8 +355,10 @@ parameter_types! {
355355
// v = p / k * (1 - s*) = 0.3 / (300 * (1 - 0.16))
356356
// at most 30% (=p) fees variation in one hour, 300 blocks (=k)
357357
pub AdjustmentVariableBlockSize: Multiplier = Multiplier::saturating_from_rational(1, 840);
358-
// TODO: decide the value of MinimumMultiplierBlockSize, https://github.com/thrumdev/blobs/issues/154
359-
pub MinimumMultiplierBlockSize: Multiplier = Multiplier::saturating_from_rational(1, 1000u128);
358+
// Using an adjustment variable block size of 1/840
359+
// and a minimum multiplier block size of 1/200,
360+
// it would require 5298 full blocks to grow back to one.
361+
pub MinimumMultiplierBlockSize: Multiplier = Multiplier::saturating_from_rational(1, 200u128);
360362
pub MaximumMultiplierBlockSize: Multiplier = Bounded::max_value();
361363
}
362364

sugondat/chain/runtimes/test/tests/fee_adjustments.rs

+61-9
Original file line numberDiff line numberDiff line change
@@ -138,14 +138,6 @@ impl MultiplierType {
138138
}
139139
}
140140

141-
// k = 1 / (v * s*)
142-
fn k_bound(&self) -> u64 {
143-
(Multiplier::saturating_from_integer(1)
144-
/ (self.target_percentage() * self.adjustment_variable()))
145-
.to_float()
146-
.ceil() as u64
147-
}
148-
149141
fn run_with<F>(&self, w: Weight, assertions: F)
150142
where
151143
F: Fn() -> (),
@@ -244,6 +236,10 @@ fn multiplier_cannot_go_below_limit() {
244236

245237
#[test]
246238
fn time_to_reach_zero() {
239+
// TODO: 1440 needs to be used instead of 7200
240+
// when updating to asynchronous backing
241+
// https://github.com/thrumdev/blobs/issues/166
242+
//
247243
// blocks per 24h in cumulus-node: 7200 (k)
248244
// s* = 0.1875 (TargetBlockFullness) or 0.16 (TargetBlockSize)
249245
// The bound from the research in an empty chain is:
@@ -264,7 +260,11 @@ fn time_to_reach_zero() {
264260
// start from 1, the default.
265261
let mut fm = Multiplier::one();
266262
let mut iterations: u64 = 0;
267-
let limit = mul_type.k_bound();
263+
let limit = (Multiplier::saturating_from_integer(1)
264+
/ (mul_type.target_percentage() * mul_type.adjustment_variable()))
265+
.to_float()
266+
.ceil() as u64;
267+
268268
loop {
269269
let next = mul_type.runtime_multiplier_update(fm);
270270
fm = next;
@@ -281,6 +281,54 @@ fn time_to_reach_zero() {
281281
test(MultiplierType::Length);
282282
}
283283

284+
#[test]
285+
fn time_to_reach_one() {
286+
// TODO: 1440 needs to ne used insted of 7200
287+
// when updating to asynchronous backing
288+
// https://github.com/thrumdev/blobs/issues/166
289+
//
290+
// blocks per 24h in cumulus-node: 7200 (k)
291+
// s* = 0.1875 (TargetBlockFullness) or 0.16 (TargetBlockSize)
292+
// The bound from the research in an full chain is:
293+
// v <~ (p / k(1 - s*))
294+
// p > v * k * (1 - s*)
295+
// to get p == 1 we'd need (going from zero to target)
296+
// 1 > v * k * (1 - s*)
297+
// k < 1 / (v * (1 - s*))
298+
299+
// if s* = 0.1875
300+
// then k > 17_778 ~ 2.47 days
301+
// else s* = 0.16
302+
// then k > 1000 ~ 3.3 hours
303+
304+
let test = |mul_type: MultiplierType| {
305+
mul_type.run_with(mul_type.max(), || {
306+
// start from min_multiplier, the default.
307+
let mut fm = mul_type.min_multiplier();
308+
let mut iterations: u64 = 0;
309+
310+
let limit = (Multiplier::saturating_from_integer(1)
311+
/ ((Multiplier::saturating_from_integer(1) - mul_type.target_percentage())
312+
* mul_type.adjustment_variable()))
313+
.to_float()
314+
.ceil() as u64;
315+
316+
loop {
317+
let next = mul_type.runtime_multiplier_update(fm);
318+
fm = next;
319+
if fm >= Multiplier::one() {
320+
break;
321+
}
322+
iterations += 1;
323+
}
324+
assert!(iterations > limit);
325+
})
326+
};
327+
328+
test(MultiplierType::Fee);
329+
test(MultiplierType::Length);
330+
}
331+
284332
#[test]
285333
fn min_change_per_day() {
286334
let test = |mul_type: MultiplierType| {
@@ -292,6 +340,10 @@ fn min_change_per_day() {
292340
let next = mul_type.runtime_multiplier_update(fm);
293341
fm = next;
294342
}
343+
// TODO: 1440 needs to ne used insted of 7200
344+
// when updating to asynchronous backing
345+
// https://github.com/thrumdev/blobs/issues/166
346+
//
295347
// 7200 blocks per day with one 12 seconds blocks
296348
// v * k * (1 - s)
297349
let expected = mul_type.adjustment_variable()

0 commit comments

Comments
 (0)