Skip to content

Commit e212f2e

Browse files
authored
Merge pull request #1698 from radixdlt/feature/bls_aggregate_verify_costing
Improve costing calculation for BLS related methods
2 parents ea13991 + 58ba429 commit e212f2e

File tree

1 file changed

+67
-20
lines changed

1 file changed

+67
-20
lines changed

radix-engine/src/system/system_modules/costing/fee_table.rs

Lines changed: 67 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -387,43 +387,89 @@ impl FeeTable {
387387
// - For sizes less than 1024, instruction count remains the same.
388388
// - For greater sizes following linear equation might be applied:
389389
// (used: https://www.socscistatistics.com/tests/regression/default.aspx)
390-
// instructions_cnt = 34.55672 * size + 10577803.13
390+
// instructions_cnt = 35.83223 * size + 15563087.39
391391
// Lets round:
392-
// 34.55672 -> 35
393-
// 10577803.13 -> 10577804
392+
// 35.83223 -> 36
393+
// 15563087.39 -> 15650000 (increased slightly to get the positive difference between
394+
// calculated and measured number of instructions)
394395
let size = if size < 1024 { 1024 } else { cast(size) };
395-
let instructions_cnt = add(mul(size, 35), 10577804);
396+
let instructions_cnt = add(mul(size, 36), 15650000);
396397
// Convert to cost units
397398
instructions_cnt / CPU_INSTRUCTIONS_TO_COST_UNIT
398399
}
399400

400401
#[inline]
401402
pub fn bls12381_v1_aggregate_verify_cost(&self, sizes: &[usize]) -> u32 {
402-
// Below approach does not take aggregation into account.
403-
// Summing costs pers size gives greater values.
404-
// We've found somewhat difficult to find a proper and effective equation to estimate
405-
// the instructions count collected with `test_crypto_scrypto_verify_bls12381_v1_costing`
406-
// TODO: Find more adequate cost estimation
407-
let mut cost: u32 = 0;
408-
for size in sizes {
409-
cost += self.bls12381_v1_verify_cost(*size);
403+
// Observed that aggregated verify might be broken down into:
404+
// - steps depending on message size
405+
// - aggregation of pairings of each corresponding key and message pair
406+
// - commit each above aggregation
407+
// - steps that do not depend on message size
408+
// - read signature from bytes: 281125 instructions
409+
// - signature validation: 583573 instructions
410+
// - aggregated pairing of signature to verify and initialization point: 3027639 instructions
411+
// - final verification: 4280077 instructions
412+
//
413+
// more details and data in https://docs.google.com/spreadsheets/d/1rV0KyB7UQrg2tOenbh2MQ1fo9MXwrwPFW4l0_CVO-6o/edit?usp=sharing
414+
415+
// Pairing aggregate
416+
// Following linerar equation might be applied:
417+
// (used: https://www.socscistatistics.com/tests/regression/default.aspx)
418+
// instructions_cnt = 34.42199 * size + 2620295.64271
419+
// Lets round:
420+
// 34.42199 -> 35
421+
// 2620295.64271 -> 2620296
422+
//
423+
// Also observed that additional 16850000 instructions are performed
424+
// every multiple of 8
425+
let mut instructions_cnt = 0u32;
426+
427+
for s in sizes {
428+
instructions_cnt = add(add(instructions_cnt, mul(35, cast(*s))), 2620296);
410429
}
411-
cost
430+
let multiplier = cast(sizes.len() / 8);
431+
instructions_cnt = add(instructions_cnt, mul(multiplier, 16850000));
432+
433+
// Pairing commit
434+
// Observed that number commit instructions repeats every multiple of 8
435+
instructions_cnt = add(
436+
instructions_cnt,
437+
match sizes.len() % 8 {
438+
0 => 0,
439+
1 => 3051556,
440+
2 => 5020768,
441+
3 => 6990111,
442+
4 => 8959454,
443+
5 => 10928798,
444+
6 => 12898141,
445+
7 => 14867484,
446+
_ => unreachable!(),
447+
},
448+
);
449+
450+
// Instructions that do not depend on size
451+
instructions_cnt = add(instructions_cnt, 281125 + 583573 + 3027639 + 4280077);
452+
453+
// Observed that threaded takes ~1.21 more instructions than no threaded
454+
instructions_cnt = mul(instructions_cnt / 100, 121);
455+
// Convert to cost units
456+
instructions_cnt / CPU_INSTRUCTIONS_TO_COST_UNIT
412457
}
413458

414459
#[inline]
415460
pub fn bls12381_v1_fast_aggregate_verify_cost(&self, size: usize, keys_cnt: usize) -> u32 {
416461
// Based on `test_crypto_scrypto_bls12381_v1_fast_aggregate_verify_costing`
417462
// - For sizes less than 1024, instruction count remains the same.
418463
// - For greater sizes following linear equation might be applied:
419-
// instructions_cnt = 32.1717 * size + 624919.5254 * keys_cnt + 9058827.9112
464+
// instructions_cnt = 35.008 * size + 626055.4801 * keys_cnt + 15125588.5419
420465
// (used: https://www.socscistatistics.com/tests/multipleregression/default.aspx)
421466
// Lets round:
422-
// 32.1717 -> 33
423-
// 624919.5254 -> 624920
424-
// 10096964.55 -> 10096965
467+
// 35.008 -> 36
468+
// 626055.4801 -> 626056
469+
// 15125588.5419 -> 15200000 (increased slightly to get the positive difference between
470+
// calculated and measured number of instructions)
425471
let size = if size < 1024 { 1024 } else { cast(size) };
426-
let instructions_cnt = add(add(mul(size, 33), mul(cast(keys_cnt), 624920)), 10096965);
472+
let instructions_cnt = add(add(mul(size, 36), mul(cast(keys_cnt), 626056)), 15200000);
427473
// Convert to cost units
428474
instructions_cnt / CPU_INSTRUCTIONS_TO_COST_UNIT
429475
}
@@ -436,8 +482,9 @@ impl FeeTable {
436482
// (used: https://www.socscistatistics.com/tests/regression/default.aspx)
437483
// Lets round:
438484
// 879553.91557 -> 879554
439-
// 567872.5895 -> 567873
440-
let instructions_cnt = sub(mul(cast(signatures_cnt), 879554), 567873);
485+
// 567872.5895 -> 500000 (decreased to get more accurate difference between calculated
486+
// and measured instructions)
487+
let instructions_cnt = sub(mul(cast(signatures_cnt), 879554), 500000);
441488
// Convert to cost units
442489
instructions_cnt / CPU_INSTRUCTIONS_TO_COST_UNIT
443490
}

0 commit comments

Comments
 (0)