@@ -433,6 +433,9 @@ where
433433 GatekeeperEvent :: _RepairV
434434 | GatekeeperEvent :: _PhalaLaunched
435435 | GatekeeperEvent :: _UnrespFix => unreachable ! ( ) ,
436+ GatekeeperEvent :: SetStaticV { .. } => {
437+ // Handled by ComputingEconomics
438+ }
436439 }
437440 }
438441
@@ -1178,14 +1181,19 @@ impl<MsgChan: MessageChannel<Signer = Sr25519Signer>> ComputingEconomics<MsgChan
11781181 GatekeeperEvent :: _RepairV
11791182 | GatekeeperEvent :: _PhalaLaunched
11801183 | GatekeeperEvent :: _UnrespFix => unreachable ! ( ) ,
1184+ GatekeeperEvent :: SetStaticV { enabled } => {
1185+ if origin. is_pallet ( ) {
1186+ self . tokenomic_params . set_static_v ( enabled) ;
1187+ }
1188+ }
11811189 }
11821190 }
11831191
11841192 pub fn update_tokenomic_parameters (
11851193 & mut self ,
11861194 params : phala_types:: messaging:: TokenomicParameters ,
11871195 ) {
1188- self . tokenomic_params = params . into ( ) ;
1196+ self . tokenomic_params . update ( params ) ;
11891197 info ! (
11901198 target: "gk_computing" ,
11911199 "Tokenomic parameter updated: {:#?}" ,
@@ -1348,13 +1356,16 @@ mod tokenomic {
13481356 #[ serde( with = "serde_fp" ) ]
13491357 payout_ration : FixedPoint ,
13501358 pub heartbeat_window : u32 ,
1359+ /// The V won't increase on IDLE if set to true
1360+ #[ serde( default ) ]
1361+ static_v : bool ,
13511362 }
13521363
1353- impl From < TokenomicParameters > for Params {
1354- fn from ( params : TokenomicParameters ) -> Self {
1364+ impl Params {
1365+ pub fn update ( & mut self , params : TokenomicParameters ) {
13551366 let treasury_ration = FixedPoint :: from_bits ( params. treasury_ratio ) ;
13561367 let payout_ration = fp ! ( 1 ) - treasury_ration;
1357- Params {
1368+ * self = Params {
13581369 rho : FixedPoint :: from_bits ( params. rho ) ,
13591370 slash_rate : FixedPoint :: from_bits ( params. slash_rate ) ,
13601371 budget_per_block : FixedPoint :: from_bits ( params. budget_per_block ) ,
@@ -1364,7 +1375,12 @@ mod tokenomic {
13641375 treasury_ration,
13651376 payout_ration,
13661377 heartbeat_window : params. heartbeat_window ,
1367- }
1378+ static_v : self . static_v ,
1379+ } ;
1380+ }
1381+
1382+ pub fn set_static_v ( & mut self , enabled : bool ) {
1383+ self . static_v = enabled;
13681384 }
13691385 }
13701386
@@ -1379,6 +1395,7 @@ mod tokenomic {
13791395 treasury_ration : fp ! ( 0.2 ) ,
13801396 payout_ration : fp ! ( 0.8 ) ,
13811397 heartbeat_window : 10 ,
1398+ static_v : false ,
13821399 }
13831400 }
13841401
@@ -1393,6 +1410,9 @@ mod tokenomic {
13931410
13941411 /// case1: Idle, no event
13951412 pub fn update_v_idle ( & mut self , params : & Params ) {
1413+ if params. static_v {
1414+ return ;
1415+ }
13961416 let cost_idle = params. cost_k * self . p_bench + params. cost_b ;
13971417 let perf_multiplier = if self . p_bench == fp ! ( 0 ) {
13981418 fp ! ( 1 )
@@ -1418,7 +1438,7 @@ mod tokenomic {
14181438 if sum_share == fp ! ( 0 ) {
14191439 return NO_UPDATE ;
14201440 }
1421- if self . v_deductible == fp ! ( 0 ) {
1441+ if !params . static_v && self . v_deductible == fp ! ( 0 ) {
14221442 return NO_UPDATE ;
14231443 }
14241444 if block_number <= self . v_update_block {
@@ -1434,10 +1454,11 @@ mod tokenomic {
14341454 let actual_payout = budget * params. payout_ration ;
14351455 let actual_treasury = budget * params. treasury_ration ;
14361456
1437- let actual_v_deduct = self . v_deductible . clamp ( fp ! ( 0 ) , actual_payout) ;
1438- self . v -= actual_v_deduct;
1439-
1440- self . v_deductible = fp ! ( 0 ) ;
1457+ if !params. static_v {
1458+ let actual_v_deduct = self . v_deductible . clamp ( fp ! ( 0 ) , actual_payout) ;
1459+ self . v -= actual_v_deduct;
1460+ self . v_deductible = fp ! ( 0 ) ;
1461+ }
14411462 self . v_update_at = now_ms;
14421463 self . v_update_block = block_number;
14431464
@@ -1894,6 +1915,92 @@ pub mod tests {
18941915 ) ;
18951916 }
18961917
1918+ #[ test]
1919+ fn static_v_works ( ) {
1920+ let mut r = Roles :: test_roles ( ) ;
1921+ let mut block_number = 1 ;
1922+
1923+ r. gk . tokenomic_params . set_static_v ( true ) ;
1924+
1925+ // Register worker
1926+ with_block ( block_number, |block| {
1927+ let mut worker0 = r. for_worker ( 0 ) ;
1928+ worker0. pallet_say ( msg:: WorkerEvent :: Registered ( msg:: WorkerInfo {
1929+ confidence_level : 2 ,
1930+ } ) ) ;
1931+ r. gk . test_process_messages ( block) ;
1932+ } ) ;
1933+
1934+ // Start computing & send heartbeat challenge
1935+ block_number += 1 ;
1936+ with_block ( block_number, |block| {
1937+ let mut worker0 = r. for_worker ( 0 ) ;
1938+ worker0. pallet_say ( msg:: WorkerEvent :: Started {
1939+ session_id : 1 ,
1940+ init_v : fp ! ( 100 ) . to_bits ( ) ,
1941+ init_p : 200 ,
1942+ } ) ;
1943+ r. gk . test_process_messages ( block) ;
1944+ } ) ;
1945+
1946+ block_number += 1 ;
1947+
1948+ // Normal Idle state, no event
1949+ let v_snap = r. get_worker ( 0 ) . tokenomic . v ;
1950+ r. gk . egress . clear ( ) ;
1951+ with_block ( block_number, |block| {
1952+ r. gk . test_process_messages ( block) ;
1953+ } ) ;
1954+
1955+ assert ! ( !r. get_worker( 0 ) . unresponsive, "Worker should be online" ) ;
1956+ assert_eq ! (
1957+ r. gk. egress. drain_working_info_update_event( ) . len( ) ,
1958+ 0 ,
1959+ "Should not report any event"
1960+ ) ;
1961+
1962+ assert ! (
1963+ v_snap == r. get_worker( 0 ) . tokenomic. v,
1964+ "Worker V should not increase"
1965+ ) ;
1966+
1967+ // Once again.
1968+ let v_snap = r. get_worker ( 0 ) . tokenomic . v ;
1969+ r. gk . egress . clear ( ) ;
1970+ with_block ( block_number, |block| {
1971+ r. gk . test_process_messages ( block) ;
1972+ } ) ;
1973+
1974+ assert ! ( !r. get_worker( 0 ) . unresponsive, "Worker should be online" ) ;
1975+ assert_eq ! (
1976+ r. gk. egress. drain_working_info_update_event( ) . len( ) ,
1977+ 0 ,
1978+ "Should not report any event"
1979+ ) ;
1980+ assert ! (
1981+ v_snap == r. get_worker( 0 ) . tokenomic. v,
1982+ "Worker V should not increase"
1983+ ) ;
1984+
1985+ block_number += 1 ;
1986+ with_block ( block_number, |block| {
1987+ let mut worker0 = r. for_worker ( 0 ) ;
1988+ worker0. challenge ( ) ;
1989+ r. gk . test_process_messages ( block) ;
1990+ } ) ;
1991+
1992+ block_number += 1 ;
1993+ with_block ( block_number, |block| {
1994+ let mut worker0 = r. for_worker ( 0 ) ;
1995+ worker0. heartbeat ( 1 , block_number - 1 , 1000000000 ) ;
1996+ r. gk . test_process_messages ( block) ;
1997+ } ) ;
1998+ let egress = r. gk . egress . drain_working_info_update_event ( ) ;
1999+ assert_eq ! ( egress. len( ) , 1 , "Should payout" ) ;
2000+ let payout = FixedPoint :: from_bits ( egress[ 0 ] . settle [ 0 ] . payout ) ;
2001+ assert_eq ! ( payout, fp!( 285.4000288551775845473 ) ) ;
2002+ }
2003+
18972004 #[ test]
18982005 fn gk_should_report_payout_for_normal_heartbeats_case2 ( ) {
18992006 let mut r = Roles :: test_roles ( ) ;
0 commit comments