From 024ad312af178b7e2fbf43788089a49e129a1255 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Thu, 27 Jun 2024 03:31:51 +0000 Subject: [PATCH 01/25] gk: Support for HeartbeatV3 --- crates/phactory/src/system/gk.rs | 306 ++++++++++++++++++++++++++++--- crates/phala-types/src/lib.rs | 8 + 2 files changed, 290 insertions(+), 24 deletions(-) diff --git a/crates/phactory/src/system/gk.rs b/crates/phactory/src/system/gk.rs index a40a2c5cf..b51f6fc55 100644 --- a/crates/phactory/src/system/gk.rs +++ b/crates/phactory/src/system/gk.rs @@ -960,43 +960,100 @@ impl> ComputingEconomics { + let Some(worker_info) = self.workers.get_mut(&worker_pubkey) else { + error!( + target: "gk_computing", + "Unknown worker {} sent a {:?}", + hex::encode(worker_pubkey), + event + ); + return; + }; + if worker_info.state.working_state.is_none() { trace!( target: "gk_computing", - "[{}] heartbeat handling case5: Unresponsive, successful heartbeat.", + "[{}] Computing already stopped, ignore the heartbeat.", hex::encode(worker_info.state.pubkey) ); - worker_info - .tokenomic - .update_v_recover(block.now_ms, block.block_number); - fp!(0) - } else { + return; + }; + if worker_info.waiting_heartbeats.is_empty() { trace!( target: "gk_computing", - "[{}] heartbeat handling case2: Idle, successful heartbeat, report to pallet", + "[{}] Unexpected heartbeat response received, ignore it.", hex::encode(worker_info.state.pubkey) ); - let (payout, treasury) = worker_info.tokenomic.update_v_heartbeat( - &self.tokenomic_params, - self.eco_cache.sum_share, - block.now_ms, - block.block_number, - ); + return; + } + worker_info.waiting_heartbeats.clear(); + worker_info.heartbeat_flag = true; - // NOTE: keep the reporting order (vs the one while computing stop). - self.eco_cache.report.settle.push(SettleInfo { - pubkey: worker_pubkey, - v: worker_info.tokenomic.v.to_bits(), - payout: payout.to_bits(), - treasury: treasury.to_bits(), - }); - payout - }; - event_listener.emit_event(EconomicEvent::Heartbeat { payout }, worker_info); + let tokenomic = &mut worker_info.tokenomic; + tokenomic.update_p_instant(block.now_ms, iterations, false); + tokenomic.challenge_time_last = block.now_ms; + tokenomic.iteration_last = iterations; + + Self::update_v_and_payout( + &self.tokenomic_params, + block, + &mut self.eco_cache, + worker_info, + event_listener, + ); } } } + fn update_v_and_payout( + tokenomic_params: &tokenomic::Params, + block: &BlockInfo<'_>, + eco_cache: &mut EconomicCalcCache, + worker_info: &mut WorkerInfo, + event_listener: &mut impl EconomicEventListener, + ) { + let payout = if worker_info.unresponsive { + trace!( + target: "gk_computing", + "[{}] heartbeat handling case5: Unresponsive, successful heartbeat.", + hex::encode(worker_info.state.pubkey) + ); + worker_info + .tokenomic + .update_v_recover(block.now_ms, block.block_number); + fp!(0) + } else { + trace!( + target: "gk_computing", + "[{}] heartbeat handling case2: Idle, successful heartbeat, report to pallet", + hex::encode(worker_info.state.pubkey) + ); + let (payout, treasury) = worker_info.tokenomic.update_v_heartbeat( + tokenomic_params, + eco_cache.sum_share, + block.now_ms, + block.block_number, + ); + + eco_cache.report.settle.push(SettleInfo { + pubkey: worker_info.state.pubkey, + v: worker_info.tokenomic.v.to_bits(), + payout: payout.to_bits(), + treasury: treasury.to_bits(), + }); + payout + }; + event_listener.emit_event(EconomicEvent::Heartbeat { payout }, worker_info); + } + fn process_system_event( &mut self, origin: MessageOrigin, @@ -1614,6 +1671,15 @@ pub mod tests { }; self.say(message) } + + fn heartbeat_v3(&mut self, session_id: u32, iterations: u64) { + let message = msg::WorkingReportEvent::HeartbeatV3 { + session_id, + iterations, + p_instant: 0, + }; + self.say(message) + } } fn with_block(block_number: chain::BlockNumber, call: impl FnOnce(&BlockInfo)) { @@ -2106,6 +2172,198 @@ pub mod tests { } } + #[test] + fn heartbeat_v3_can_flush_multiple_unrespond_heartbeat() { + let mut r = Roles::test_roles(); + + with_block(1, |block| { + let mut worker0 = r.for_worker(0); + worker0.pallet_say(msg::WorkerEvent::Registered(msg::WorkerInfo { + confidence_level: 2, + })); + r.gk.test_process_messages(block); + }); + + assert_eq!(r.gk.workers.len(), 1); + + assert!(r.get_worker(0).state.registered); + + with_block(2, |block| { + let mut worker0 = r.for_worker(0); + worker0.pallet_say(msg::WorkerEvent::Started { + session_id: 1, + init_v: 1, + init_p: 100, + }); + worker0.challenge(); + r.gk.test_process_messages(block); + }); + + for i in 3..6 { + with_block(i, |block| { + let mut worker0 = r.for_worker(0); + worker0.challenge(); + r.gk.test_process_messages(block); + }); + } + + // Force enter unresponsive + with_block(100, |block| { + r.gk.test_process_messages(block); + }); + + assert_eq!( + r.get_worker(0).waiting_heartbeats.len(), + 4, + "There should be 4 waiting HBs" + ); + + assert!( + r.get_worker(0).unresponsive, + "The worker should be unresponsive now" + ); + { + let offline = [r.workers[0]].to_vec(); + let expected_message = WorkingInfoUpdateEvent { + block_number: 100, + timestamp_ms: block_ts(100), + offline, + recovered_to_online: Vec::new(), + settle: Vec::new(), + }; + let messages = r.gk.egress.drain_working_info_update_event(); + assert_eq!(messages.len(), 1, "Should report recover event"); + assert_eq!(messages[0], expected_message); + } + + with_block(101, |block| { + let mut worker = r.for_worker(0); + // Response the first challenge. + worker.heartbeat_v3(1, 10000000); + r.gk.test_process_messages(block); + }); + assert_eq!( + r.get_worker(0).waiting_heartbeats.len(), + 0, + "HBs should be cleared" + ); + + assert!( + !r.get_worker(0).unresponsive, + "The worker should be computing idle now" + ); + { + let recovered_to_online = [r.workers[0]].to_vec(); + let expected_message = WorkingInfoUpdateEvent { + block_number: 101, + timestamp_ms: block_ts(101), + offline: Vec::new(), + recovered_to_online, + settle: Vec::new(), + }; + let messages = r.gk.egress.drain_working_info_update_event(); + assert_eq!(messages.len(), 1, "Should report recover event"); + assert_eq!(messages[0], expected_message); + } + + with_block(102, |block| { + let mut worker = r.for_worker(0); + // Response the second challenge. + worker.heartbeat_v3(2, 10000000); + r.gk.test_process_messages(block); + }); + + assert!( + !r.get_worker(0).unresponsive, + "The worker should be computing idle now" + ); + { + let messages = r.gk.egress.drain_working_info_update_event(); + assert_eq!(messages.len(), 0, "Should have no report event"); + } + } + + #[test] + fn heartbeat_v3_should_be_paid_out() { + let mut r = Roles::test_roles(); + + with_block(1, |block| { + let mut worker0 = r.for_worker(0); + worker0.pallet_say(msg::WorkerEvent::Registered(msg::WorkerInfo { + confidence_level: 2, + })); + r.gk.test_process_messages(block); + }); + + assert_eq!(r.gk.workers.len(), 1); + + assert!(r.get_worker(0).state.registered); + + with_block(2, |block| { + let mut worker0 = r.for_worker(0); + worker0.pallet_say(msg::WorkerEvent::Started { + session_id: 1, + init_v: fp!(100).to_bits(), + init_p: 2500, + }); + worker0.challenge(); + r.gk.test_process_messages(block); + }); + + for i in 3..6 { + with_block(i, |block| { + let mut worker0 = r.for_worker(0); + worker0.challenge(); + r.gk.test_process_messages(block); + }); + } + assert_eq!( + r.get_worker(0).waiting_heartbeats.len(), + 4, + "There should have 4 HBs" + ); + assert_eq!(r.get_worker(0).tokenomic.v, fp!(100.00055963912991258423)); + + with_block(6, |block| { + let mut worker = r.for_worker(0); + // Response the first challenge. + worker.heartbeat_v3(1, 24000); + r.gk.test_process_messages(block); + }); + assert_eq!( + r.get_worker(0).waiting_heartbeats.len(), + 0, + "HBs should be cleared" + ); + + assert!( + !r.get_worker(0).unresponsive, + "The worker should be computing idle now" + ); + { + let expected_message = WorkingInfoUpdateEvent { + block_number: 6, + timestamp_ms: block_ts(6), + offline: Vec::new(), + recovered_to_online: Vec::new(), + settle: vec![super::SettleInfo { + pubkey: r.workers[0], + v: fp!(100).to_bits(), + payout: fp!(383.9765417372721003196).to_bits(), + treasury: fp!(95.9941354343180250734).to_bits(), + }], + }; + let messages = r.gk.egress.drain_working_info_update_event(); + assert_eq!(messages.len(), 1, "Should report recover event"); + assert_eq!(messages[0], expected_message); + assert_eq!( + r.get_worker(0).tokenomic.p_instant, + fp!(2999.9999999999999999729) + ); + assert_eq!(r.get_worker(0).tokenomic.v, fp!(100)); + } + } + #[test] fn check_tokenomic_numerics() { let mut r = Roles::test_roles(); diff --git a/crates/phala-types/src/lib.rs b/crates/phala-types/src/lib.rs index 8491c7f9e..2c9580015 100644 --- a/crates/phala-types/src/lib.rs +++ b/crates/phala-types/src/lib.rs @@ -143,6 +143,14 @@ pub mod messaging { /// Number of current deployed contracts. n_contracts: u32, }, + HeartbeatV3 { + /// The computing session id. + session_id: u32, + /// Benchmark iterations since working_start_time. + iterations: u64, + /// Number of current deployed clusters. + p_instant: u32, + }, } bind_topic!(WorkingInfoUpdateEvent, b"^phala/mining/update"); From f3c560b734623628cb24eea22d682eb7d34a53a7 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Thu, 27 Jun 2024 03:32:47 +0000 Subject: [PATCH 02/25] pallet: Support HeartbeatV3 --- pallets/phala/src/compute/computation.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/pallets/phala/src/compute/computation.rs b/pallets/phala/src/compute/computation.rs index 8be7443fe..abb9519f7 100644 --- a/pallets/phala/src/compute/computation.rs +++ b/pallets/phala/src/compute/computation.rs @@ -42,7 +42,7 @@ pub mod pallet { use fixed_sqrt::FixedSqrt; #[cfg(feature = "std")] - use serde::{Serialize, Deserialize}; + use serde::{Deserialize, Serialize}; const DEFAULT_EXPECTED_HEARTBEAT_COUNT: u32 = 20; const COMPUTING_PALLETID: PalletId = PalletId(*b"phala/pp"); @@ -718,6 +718,19 @@ pub mod pallet { }); Sessions::::insert(&session, session_info); } + WorkingReportEvent::HeartbeatV3 { p_instant, iterations, .. } => { + let session = Self::ensure_worker_bound(&worker)?; + let mut session_info = + Self::sessions(&session).expect("Bound worker; qed."); + session_info.benchmark.p_instant = p_instant; + session_info.benchmark.challenge_time_last = Self::now_sec(); + session_info.benchmark.iterations = iterations; + Sessions::::insert(&session, session_info); + Self::deposit_event(Event::::BenchmarkUpdated { + session: session.clone(), + p_instant, + }); + } }; } Ok(()) From d9e67efec2311534555f0261a861bfedd817d127 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Thu, 27 Jun 2024 09:53:33 +0000 Subject: [PATCH 03/25] Add pallet wapod-workers --- Cargo.lock | 184 ++++++---- pallets/phala/Cargo.toml | 3 + pallets/phala/src/lib.rs | 1 + pallets/phala/src/registry.rs | 46 ++- pallets/phala/src/wapod_workers/mod.rs | 3 + pallets/phala/src/wapod_workers/mq.rs | 0 pallets/phala/src/wapod_workers/tickets.rs | 387 +++++++++++++++++++++ 7 files changed, 531 insertions(+), 93 deletions(-) create mode 100644 pallets/phala/src/wapod_workers/mod.rs create mode 100644 pallets/phala/src/wapod_workers/mq.rs create mode 100644 pallets/phala/src/wapod_workers/tickets.rs diff --git a/Cargo.lock b/Cargo.lock index 318a67ec8..c7bc2f6f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -252,7 +252,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6ff94ee630eb0bf55c59821a979f486bbaa976324786efcfc9d1f93bd254426" dependencies = [ "aead 0.4.3", - "arrayvec 0.7.2", + "arrayvec 0.7.4", ] [[package]] @@ -853,9 +853,9 @@ checksum = "f52f63c5c1316a16a4b35eaac8b76a98248961a533f061684cb2a7cb0eafb6c6" [[package]] name = "array-bytes" -version = "6.1.0" +version = "6.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b1c5a481ec30a5abd8dfbd94ab5cf1bb4e9a66be7f1b3b322f2f1170c200fd" +checksum = "5d5dde061bd34119e902bbb2d9b90c5692635cf59fb91d582c2b68043f1b8293" [[package]] name = "array-init" @@ -877,9 +877,9 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "arrayvec" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "ascii-canvas" @@ -1533,7 +1533,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c2f0dc9a68c6317d884f97cc36cf5a3d20ba14ce404227df55e1af708ab04bc" dependencies = [ "arrayref", - "arrayvec 0.7.2", + "arrayvec 0.7.4", "constant_time_eq 0.2.5", ] @@ -1544,22 +1544,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db539cc2b5f6003621f1cd9ef92d7ded8ea5232c7de0f9faa2de251cd98730d4" dependencies = [ "arrayref", - "arrayvec 0.7.2", + "arrayvec 0.7.4", "constant_time_eq 0.1.5", ] [[package]] name = "blake3" -version = "1.3.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08e53fc5a564bb15bfe6fae56bd71522205f1f91893f9c0116edad6496c183f" +checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" dependencies = [ "arrayref", - "arrayvec 0.7.2", + "arrayvec 0.7.4", "cc", "cfg-if", - "constant_time_eq 0.1.5", - "digest 0.10.7", + "constant_time_eq 0.3.0", ] [[package]] @@ -2368,6 +2367,12 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13418e745008f7349ec7e449155f419a61b92b58a99cc3616942b926825ec76b" +[[package]] +name = "constant_time_eq" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" + [[package]] name = "constcat" version = "0.3.1" @@ -2491,7 +2496,7 @@ version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98b022ed2a5913a38839dfbafe6cf135342661293b08049843362df4301261dc" dependencies = [ - "arrayvec 0.7.2", + "arrayvec 0.7.4", "bumpalo", "cranelift-bforest 0.91.1", "cranelift-codegen-meta 0.91.1", @@ -3265,6 +3270,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive-syn-parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + [[package]] name = "derive_builder" version = "0.11.2" @@ -3497,7 +3513,7 @@ dependencies = [ "ark-serialize", "ark-std", "ark-transcript", - "arrayvec 0.7.2", + "arrayvec 0.7.4", "zeroize", ] @@ -3518,21 +3534,21 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "docify" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc4fd38aaa9fb98ac70794c82a00360d1e165a87fbf96a8a91f9dfc602aaee2" +checksum = "43a2f138ad521dc4a2ced1a4576148a6a610b4c5923933b062a263130a6802ce" dependencies = [ "docify_macros", ] [[package]] name = "docify_macros" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63fa215f3a0d40fb2a221b3aa90d8e1fbb8379785a990cb60d62ac71ebdc6460" +checksum = "1a081e51fb188742f5a7a1164ad752121abcb22874b21e2c3b0dd040c515fdad" dependencies = [ "common-path", - "derive-syn-parse", + "derive-syn-parse 0.2.0", "once_cell", "proc-macro2", "quote", @@ -4107,7 +4123,7 @@ version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60ca2514feb98918a0a31de7e1983c29f2267ebf61b2dc5d4294f91e5b866623" dependencies = [ - "arrayvec 0.7.2", + "arrayvec 0.7.4", "bytes", "cargo_metadata 0.15.4", "chrono", @@ -4608,7 +4624,7 @@ version = "4.0.0-dev" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#789ffb66dcfcf3b54a1e6786e928ac91c4fdb465" dependencies = [ "Inflector", - "array-bytes 6.1.0", + "array-bytes 6.2.3", "chrono", "clap 4.4.12", "comfy-table", @@ -4747,7 +4763,7 @@ version = "4.0.0-dev" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#8a98fec3e456033fdedf284e3613d5300f817085" dependencies = [ "aquamarine", - "array-bytes 6.1.0", + "array-bytes 6.2.3", "bitflags 1.3.2", "docify", "environmental", @@ -4789,7 +4805,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polk dependencies = [ "Inflector", "cfg-expr", - "derive-syn-parse", + "derive-syn-parse 0.1.5", "expander", "frame-support-procedural-tools", "itertools", @@ -6433,7 +6449,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4e70b4439a751a5de7dd5ed55eacff78ebf4ffe0fc009cb1ebb11417f5b536b" dependencies = [ "anyhow", - "arrayvec 0.7.2", + "arrayvec 0.7.4", "async-lock", "async-trait", "beef", @@ -6887,7 +6903,7 @@ version = "0.43.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39d5ef876a2b2323d63c258e63c2f8e36f205fe5a11f0b3095d59635650790ff" dependencies = [ - "arrayvec 0.7.2", + "arrayvec 0.7.4", "asynchronous-codec", "bytes", "either", @@ -7447,7 +7463,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "468155613a44cfd825f1fb0ffa532b018253920d404e6fca1e8d43155198a46d" dependencies = [ "const-random", - "derive-syn-parse", + "derive-syn-parse 0.1.5", "macro_magic_core_macros", "proc-macro2", "quote", @@ -7669,7 +7685,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daa3eb39495d8e2e2947a1d862852c90cc6a4a8845f8b41c8829cb9fcc047f4a" dependencies = [ "arrayref", - "arrayvec 0.7.2", + "arrayvec 0.7.4", "bitflags 1.3.2", "blake2 0.10.6", "c2-chacha", @@ -8225,7 +8241,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" dependencies = [ - "arrayvec 0.7.2", + "arrayvec 0.7.4", "itoa", ] @@ -8397,7 +8413,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" dependencies = [ - "arrayvec 0.7.2", + "arrayvec 0.7.4", "auto_impl", "bytes", "ethereum-types", @@ -9440,11 +9456,11 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.6.5" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dec8a8073036902368c2cdc0387e85ff9a37054d7e7c98e592145e0c92cd4fb" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" dependencies = [ - "arrayvec 0.7.2", + "arrayvec 0.7.4", "bitvec 1.0.1", "byte-slice-cast", "bytes", @@ -9455,11 +9471,11 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.5" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312270ee71e1cd70289dacf597cab7b207aa107d2f28191c2ae45b2ece18a260" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -10154,6 +10170,7 @@ dependencies = [ "sp-io", "sp-runtime", "sp-std 8.0.0", + "wapod-eco-types", ] [[package]] @@ -12280,7 +12297,7 @@ version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34a3bb58e85333f1ab191bf979104b586ebd77475bc6681882825f4532dfe87c" dependencies = [ - "arrayvec 0.7.2", + "arrayvec 0.7.4", "num-traits", "serde", ] @@ -12665,7 +12682,7 @@ name = "sc-chain-spec" version = "4.0.0-dev" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#789ffb66dcfcf3b54a1e6786e928ac91c4fdb465" dependencies = [ - "array-bytes 6.1.0", + "array-bytes 6.2.3", "docify", "log", "memmap2", @@ -12701,7 +12718,7 @@ name = "sc-cli" version = "0.10.0-dev" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#789ffb66dcfcf3b54a1e6786e928ac91c4fdb465" dependencies = [ - "array-bytes 6.1.0", + "array-bytes 6.2.3", "bip39", "chrono", "clap 4.4.12", @@ -12891,7 +12908,7 @@ version = "0.10.0-dev" source = "git+https://github.com/Phala-Network/polkadot-sdk.git?branch=phala-patch-polkadot-v1.5.0#559a9126a2aa1de47356fea36aa246eb3e27e38a" dependencies = [ "ahash 0.8.3", - "array-bytes 6.1.0", + "array-bytes 6.2.3", "async-trait", "dyn-clone", "finality-grandpa", @@ -13044,7 +13061,7 @@ name = "sc-keystore" version = "4.0.0-dev" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#789ffb66dcfcf3b54a1e6786e928ac91c4fdb465" dependencies = [ - "array-bytes 6.1.0", + "array-bytes 6.2.3", "parking_lot 0.12.1", "serde_json", "sp-application-crypto", @@ -13059,7 +13076,7 @@ version = "0.1.0-dev" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#789ffb66dcfcf3b54a1e6786e928ac91c4fdb465" dependencies = [ "array-bytes 4.2.0", - "arrayvec 0.7.2", + "arrayvec 0.7.4", "blake2 0.10.6", "bytes", "futures", @@ -13087,7 +13104,7 @@ name = "sc-network" version = "0.10.0-dev" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#789ffb66dcfcf3b54a1e6786e928ac91c4fdb465" dependencies = [ - "array-bytes 6.1.0", + "array-bytes 6.2.3", "async-channel", "async-trait", "asynchronous-codec", @@ -13186,7 +13203,7 @@ name = "sc-network-light" version = "0.10.0-dev" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#789ffb66dcfcf3b54a1e6786e928ac91c4fdb465" dependencies = [ - "array-bytes 6.1.0", + "array-bytes 6.2.3", "async-channel", "futures", "libp2p-identity", @@ -13207,7 +13224,7 @@ name = "sc-network-sync" version = "0.10.0-dev" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#789ffb66dcfcf3b54a1e6786e928ac91c4fdb465" dependencies = [ - "array-bytes 6.1.0", + "array-bytes 6.2.3", "async-channel", "async-trait", "fork-tree", @@ -13243,7 +13260,7 @@ name = "sc-network-transactions" version = "0.10.0-dev" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#789ffb66dcfcf3b54a1e6786e928ac91c4fdb465" dependencies = [ - "array-bytes 6.1.0", + "array-bytes 6.2.3", "futures", "libp2p", "log", @@ -13262,7 +13279,7 @@ name = "sc-offchain" version = "4.0.0-dev" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#789ffb66dcfcf3b54a1e6786e928ac91c4fdb465" dependencies = [ - "array-bytes 6.1.0", + "array-bytes 6.2.3", "bytes", "fnv", "futures", @@ -13372,7 +13389,7 @@ name = "sc-rpc-spec-v2" version = "0.10.0-dev" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#789ffb66dcfcf3b54a1e6786e928ac91c4fdb465" dependencies = [ - "array-bytes 6.1.0", + "array-bytes 6.2.3", "futures", "futures-util", "hex", @@ -13464,7 +13481,7 @@ name = "sc-service-test" version = "2.0.0" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#789ffb66dcfcf3b54a1e6786e928ac91c4fdb465" dependencies = [ - "array-bytes 6.1.0", + "array-bytes 6.2.3", "async-channel", "fdlimit", "futures", @@ -13795,9 +13812,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.10.0" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7d66a1128282b7ef025a8ead62a4a9fcf017382ec53b8ffbf4d7bf77bd3c60" +checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" dependencies = [ "bitvec 1.0.1", "cfg-if", @@ -13809,11 +13826,11 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.10.0" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" +checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -14858,9 +14875,9 @@ dependencies = [ [[package]] name = "sp-core" version = "21.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#8a98fec3e456033fdedf284e3613d5300f817085" +source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#a56caf11845f2118a34d9464b8e929315c12c8e3" dependencies = [ - "array-bytes 6.1.0", + "array-bytes 6.2.3", "bandersnatch_vrfs", "bip39", "bitflags 1.3.2", @@ -14907,7 +14924,7 @@ version = "25.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9ebb090ead698a6df04347c86a31ba91a387edb8a58534ec70c4f977d1e1e87" dependencies = [ - "array-bytes 6.1.0", + "array-bytes 6.2.3", "bitflags 1.3.2", "blake2 0.10.6", "bounded-collections", @@ -14988,7 +15005,7 @@ dependencies = [ [[package]] name = "sp-crypto-ec-utils" version = "0.10.0" -source = "git+https://github.com/paritytech/polkadot-sdk#305d311d5c732fcc4629f3295768f1ed44ef434c" +source = "git+https://github.com/paritytech/polkadot-sdk#63e264446f6cabff06be72912eae902662dcb699" dependencies = [ "ark-bls12-377", "ark-bls12-377-ext", @@ -15017,7 +15034,7 @@ dependencies = [ [[package]] name = "sp-debug-derive" version = "8.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#8a98fec3e456033fdedf284e3613d5300f817085" +source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#a56caf11845f2118a34d9464b8e929315c12c8e3" dependencies = [ "proc-macro2", "quote", @@ -15038,7 +15055,7 @@ dependencies = [ [[package]] name = "sp-debug-derive" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#305d311d5c732fcc4629f3295768f1ed44ef434c" +source = "git+https://github.com/paritytech/polkadot-sdk#63e264446f6cabff06be72912eae902662dcb699" dependencies = [ "proc-macro2", "quote", @@ -15048,7 +15065,7 @@ dependencies = [ [[package]] name = "sp-externalities" version = "0.19.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#8a98fec3e456033fdedf284e3613d5300f817085" +source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#a56caf11845f2118a34d9464b8e929315c12c8e3" dependencies = [ "environmental", "parity-scale-codec", @@ -15071,7 +15088,7 @@ dependencies = [ [[package]] name = "sp-externalities" version = "0.25.0" -source = "git+https://github.com/paritytech/polkadot-sdk#305d311d5c732fcc4629f3295768f1ed44ef434c" +source = "git+https://github.com/paritytech/polkadot-sdk#63e264446f6cabff06be72912eae902662dcb699" dependencies = [ "environmental", "parity-scale-codec", @@ -15253,7 +15270,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface" version = "17.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#8a98fec3e456033fdedf284e3613d5300f817085" +source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#a56caf11845f2118a34d9464b8e929315c12c8e3" dependencies = [ "bytes", "impl-trait-for-tuples", @@ -15290,7 +15307,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface" version = "24.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#305d311d5c732fcc4629f3295768f1ed44ef434c" +source = "git+https://github.com/paritytech/polkadot-sdk#63e264446f6cabff06be72912eae902662dcb699" dependencies = [ "bytes", "impl-trait-for-tuples", @@ -15309,7 +15326,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "11.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#8a98fec3e456033fdedf284e3613d5300f817085" +source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#a56caf11845f2118a34d9464b8e929315c12c8e3" dependencies = [ "Inflector", "expander", @@ -15335,7 +15352,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "17.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#305d311d5c732fcc4629f3295768f1ed44ef434c" +source = "git+https://github.com/paritytech/polkadot-sdk#63e264446f6cabff06be72912eae902662dcb699" dependencies = [ "Inflector", "expander", @@ -15422,7 +15439,7 @@ dependencies = [ [[package]] name = "sp-std" version = "8.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#8a98fec3e456033fdedf284e3613d5300f817085" +source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#a56caf11845f2118a34d9464b8e929315c12c8e3" [[package]] name = "sp-std" @@ -15433,12 +15450,12 @@ checksum = "54c78c5a66682568cc7b153603c5d01a2cc8f5c221c7b1e921517a0eef18ae05" [[package]] name = "sp-std" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#305d311d5c732fcc4629f3295768f1ed44ef434c" +source = "git+https://github.com/paritytech/polkadot-sdk#63e264446f6cabff06be72912eae902662dcb699" [[package]] name = "sp-storage" version = "13.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#8a98fec3e456033fdedf284e3613d5300f817085" +source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#a56caf11845f2118a34d9464b8e929315c12c8e3" dependencies = [ "impl-serde", "parity-scale-codec", @@ -15465,7 +15482,7 @@ dependencies = [ [[package]] name = "sp-storage" version = "19.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#305d311d5c732fcc4629f3295768f1ed44ef434c" +source = "git+https://github.com/paritytech/polkadot-sdk#63e264446f6cabff06be72912eae902662dcb699" dependencies = [ "impl-serde", "parity-scale-codec", @@ -15490,7 +15507,7 @@ dependencies = [ [[package]] name = "sp-tracing" version = "10.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#8a98fec3e456033fdedf284e3613d5300f817085" +source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#a56caf11845f2118a34d9464b8e929315c12c8e3" dependencies = [ "parity-scale-codec", "sp-std 8.0.0", @@ -15515,7 +15532,7 @@ dependencies = [ [[package]] name = "sp-tracing" version = "16.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#305d311d5c732fcc4629f3295768f1ed44ef434c" +source = "git+https://github.com/paritytech/polkadot-sdk#63e264446f6cabff06be72912eae902662dcb699" dependencies = [ "parity-scale-codec", "tracing", @@ -15603,7 +15620,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#8a98fec3e456033fdedf284e3613d5300f817085" +source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#a56caf11845f2118a34d9464b8e929315c12c8e3" dependencies = [ "anyhow", "impl-trait-for-tuples", @@ -15630,7 +15647,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" version = "20.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#305d311d5c732fcc4629f3295768f1ed44ef434c" +source = "git+https://github.com/paritytech/polkadot-sdk#63e264446f6cabff06be72912eae902662dcb699" dependencies = [ "impl-trait-for-tuples", "log", @@ -16195,7 +16212,7 @@ name = "substrate-test-client" version = "2.0.1" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#789ffb66dcfcf3b54a1e6786e928ac91c4fdb465" dependencies = [ - "array-bytes 6.1.0", + "array-bytes 6.2.3", "async-trait", "futures", "parity-scale-codec", @@ -16221,7 +16238,7 @@ name = "substrate-test-runtime" version = "2.0.0" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#789ffb66dcfcf3b54a1e6786e928ac91c4fdb465" dependencies = [ - "array-bytes 6.1.0", + "array-bytes 6.2.3", "frame-executive", "frame-support", "frame-system", @@ -17888,6 +17905,23 @@ dependencies = [ "try-lock", ] +[[package]] +name = "wapod-crypto-types" +version = "0.1.0" +dependencies = [ + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "wapod-eco-types" +version = "0.1.0" +dependencies = [ + "parity-scale-codec", + "scale-info", + "wapod-crypto-types", +] + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" diff --git a/pallets/phala/Cargo.toml b/pallets/phala/Cargo.toml index 9609a023a..f84239ff1 100644 --- a/pallets/phala/Cargo.toml +++ b/pallets/phala/Cargo.toml @@ -46,6 +46,9 @@ fixed-sqrt = { version = "0.2", default-features = false } sgx-attestation = { path = "../../crates/sgx-attestation", default-features = false, features = ["verify"] } +[dependencies.wapod-eco-types] +path = "/home/kvin/codes/chain/phala/wapo/wapod-eco-types" + [dev-dependencies] frame-support-test = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "release-polkadot-v1.5.0" } assert_matches = "1.4.0" diff --git a/pallets/phala/src/lib.rs b/pallets/phala/src/lib.rs index e3319dc3e..8dadac914 100644 --- a/pallets/phala/src/lib.rs +++ b/pallets/phala/src/lib.rs @@ -18,6 +18,7 @@ pub mod phat; pub mod puppets; pub mod registry; pub mod stake_pool; +pub mod wapod_workers; use compute::{base_pool, computation, pool_proxy, stake_pool_v2, vault, wrapped_balances}; diff --git a/pallets/phala/src/registry.rs b/pallets/phala/src/registry.rs index 3ee0bcc32..8df400a52 100644 --- a/pallets/phala/src/registry.rs +++ b/pallets/phala/src/registry.rs @@ -930,6 +930,33 @@ pub mod pallet { Ok(()) } + pub fn worker_exsists(worker_pubkey: &WorkerPublicKey) -> bool { + Workers::::contains_key(worker_pubkey) + } + + pub fn update_worker_score(worker_pubkey: &WorkerPublicKey, score: u64) -> u64 { + let now = T::UnixTime::now().as_millis().saturated_into::(); + + const MAX_SCORE: u32 = 6000; + let score = MAX_SCORE.min(score as u32); + + Workers::::mutate(worker_pubkey, |val| { + if let Some(val) = val { + val.initial_score = Some(score); + val.last_updated = now / 1000; + } + }); + Self::push_message(SystemEvent::new_worker_event( + *worker_pubkey, + WorkerEvent::BenchScore(score), + )); + Self::deposit_event(Event::::InitialScoreSet { + pubkey: *worker_pubkey, + init_score: score, + }); + score as u64 + } + pub fn on_message_received(message: DecodedMessage) -> DispatchResult { let worker_pubkey = match &message.sender { MessageOrigin::Worker(key) => key, @@ -947,26 +974,9 @@ pub mod pallet { return Err(Error::::InvalidBenchReport.into()); } - const MAX_SCORE: u32 = 6000; let score = iterations / ((now - start_time) / 1000); let score = score * 6; // iterations per 6s - let score = MAX_SCORE.min(score as u32); - - Workers::::mutate(worker_pubkey, |val| { - if let Some(val) = val { - val.initial_score = Some(score); - val.last_updated = now / 1000; - } - }); - - Self::push_message(SystemEvent::new_worker_event( - *worker_pubkey, - WorkerEvent::BenchScore(score), - )); - Self::deposit_event(Event::::InitialScoreSet { - pubkey: *worker_pubkey, - init_score: score, - }); + Self::update_worker_score(&worker_pubkey, score); } RegistryEvent::MasterPubkey { master_pubkey } => { let gatekeepers = Gatekeeper::::get(); diff --git a/pallets/phala/src/wapod_workers/mod.rs b/pallets/phala/src/wapod_workers/mod.rs new file mode 100644 index 000000000..c06ea4bf8 --- /dev/null +++ b/pallets/phala/src/wapod_workers/mod.rs @@ -0,0 +1,3 @@ + +mod tickets; +mod mq; \ No newline at end of file diff --git a/pallets/phala/src/wapod_workers/mq.rs b/pallets/phala/src/wapod_workers/mq.rs new file mode 100644 index 000000000..e69de29bb diff --git a/pallets/phala/src/wapod_workers/tickets.rs b/pallets/phala/src/wapod_workers/tickets.rs new file mode 100644 index 000000000..78fbf0376 --- /dev/null +++ b/pallets/phala/src/wapod_workers/tickets.rs @@ -0,0 +1,387 @@ +//! The Phat Contract tokenomic module + +pub use self::pallet::*; + +#[frame_support::pallet] +pub mod pallet { + use frame_support::{ + dispatch::DispatchResult, + ensure, + pallet_prelude::*, + traits::{Currency, ExistenceRequirement::*, StorageVersion}, + }; + use frame_system::pallet_prelude::*; + use phala_types::{ + messaging::{DecodedMessage, MessageOrigin, SystemEvent, WorkerEvent, WorkingReportEvent}, + WorkerPublicKey, + }; + use sp_runtime::{traits::Zero, SaturatedConversion}; + use wapod_eco_types::{ + bench_app::{SignedMessage, SigningMessage}, + crypto::CryptoProvider, + primitives::BoundedString, + ticket::{Prices, TicketDescription}, + }; + + type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; + + pub type TicketId = u32; + pub type ListId = u32; + pub type Address = [u8; 32]; + + #[derive(Encode, Decode, Debug, Clone, Copy, PartialEq, Eq, MaxEncodedLen)] + #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] + pub struct Fraction { + pub numerator: u32, + pub denominator: u32, + } + + impl Fraction { + fn saturating_mul_u64(&self, rhs: u64) -> u64 { + let numerator = self.numerator as u128; + let denominator = self.denominator as u128; + let result = (numerator * rhs as u128) / denominator; + result.saturated_into() + } + } + + #[derive(Encode, Decode, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] + #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] + pub struct BenchAppInfo { + version: u32, + ticket: TicketId, + score_ratio: Fraction, + } + + struct SpCrypto; + impl CryptoProvider for SpCrypto { + fn sr25519_verify(public_key: &[u8], message: &[u8], signature: &[u8]) -> bool { + let Ok(public_key) = public_key.try_into() else { + return false; + }; + let Ok(signature) = signature.try_into() else { + return false; + }; + sp_io::crypto::sr25519_verify(&signature, message, &public_key) + } + fn keccak_256(data: &[u8]) -> [u8; 32] { + sp_io::hashing::keccak_256(data) + } + fn blake2b_256(data: &[u8]) -> [u8; 32] { + sp_io::hashing::blake2_256(data) + } + } + + #[derive(Encode, Decode, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] + #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] + pub enum WorkerSet { + Any, + WorkerList(ListId), + } + + type AcountId32 = [u8; 32]; + + #[derive(Encode, Decode, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] + #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] + pub struct TicketInfo { + pub system: bool, + pub owner: AcountId32, + pub workers: WorkerSet, + pub app_address: [u8; 32], + pub description: TicketDescription, + } + + #[derive(Encode, Decode, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] + #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] + pub struct WorkerListInfo { + pub owner: AcountId32, + pub prices: Prices, + } + + #[derive(Encode, Decode, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] + #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] + pub struct WorkerState { + session_id: u32, + unresponsive: bool, + last_iterations: u64, + last_update_time: i64, + } + + #[derive(Encode, Decode, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] + #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] + pub struct WorkerDescription { + prices: Prices, + description: BoundedString<1024>, + } + + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + type Currency: Currency; + } + + const STORAGE_VERSION: StorageVersion = StorageVersion::new(0); + + #[pallet::pallet] + #[pallet::storage_version(STORAGE_VERSION)] + pub struct Pallet(_); + + #[pallet::storage] + pub type NextTicketId = StorageValue<_, TicketId, ValueQuery>; + + #[pallet::storage] + pub type Tickets = StorageMap<_, Twox64Concat, TicketId, TicketInfo>; + + #[pallet::storage] + pub type NextWorkerListId = StorageValue<_, ListId, ValueQuery>; + + #[pallet::storage] + pub type WorkerLists = StorageMap<_, Twox64Concat, ListId, WorkerListInfo>; + + #[pallet::storage] + pub type WorkerDescriptions = + StorageMap<_, Twox64Concat, WorkerPublicKey, WorkerDescription>; + + #[pallet::storage] + pub type WorkingWorkers = StorageMap<_, Twox64Concat, WorkerPublicKey, WorkerState>; + + #[pallet::storage] + pub type BenchmarkAddresses = StorageMap<_, Twox64Concat, Address, BenchAppInfo>; + + #[pallet::storage] + pub type PrimaryBenchmarkAddress = StorageValue<_, Address>; + + #[pallet::error] + pub enum Error { + UnsupportedManifestVersion, + NotAllowed, + WorkerListNotFound, + TicketNotFound, + SignatureVerificationFailed, + InvalidWorkerPubkey, + InvalidBenchApp, + OutdatedMessage, + InvalidMessageSender, + } + + #[pallet::event] + #[pallet::generate_deposit(fn deposit_event)] + pub enum Event {} + + const TICKET_ADDRESS_PREFIX: &[u8] = b"wapod/ticket/"; + + fn ticket_account_address(ticket_id: u32) -> [u8; 32] { + let mut address = [0u8; 32]; + let prefix = TICKET_ADDRESS_PREFIX; + address[..prefix.len()].copy_from_slice(prefix); + { + let ticket_bytes = ticket_id.to_be_bytes(); + let offset = prefix.len(); + address[offset..offset + ticket_bytes.len()].copy_from_slice(&ticket_bytes); + } + address + } + + #[pallet::call] + impl Pallet + where + T: crate::mq::Config, + T: crate::registry::Config, + T::AccountId: Into + From, + { + /// Create a new ticket + #[pallet::call_index(0)] + #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] + pub fn create_ticket( + origin: OriginFor, + deposit: BalanceOf, + description: TicketDescription, + worker_list: u32, + ) -> DispatchResult { + let owner = ensure_signed(origin)?; + ensure!( + description.manifest.version == 1, + Error::::UnsupportedManifestVersion + ); + ensure!(!description.manifest.resizable, Error::::NotAllowed); + ensure!( + WorkerLists::::contains_key(worker_list), + Error::::WorkerListNotFound + ); + let id = Self::add_ticket(TicketInfo { + system: false, + owner: owner.clone().into(), + workers: WorkerSet::WorkerList(worker_list), + app_address: description.manifest.address(sp_core::hashing::blake2_256), + description, + }); + let ticket_account = ticket_account_address(id).into(); + ::Currency::transfer(&owner, &ticket_account, deposit, KeepAlive)?; + Ok(()) + } + + /// Create a new ticket + #[pallet::call_index(1)] + #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] + pub fn create_system_ticket( + origin: OriginFor, + description: TicketDescription, + ) -> DispatchResult { + T::GovernanceOrigin::ensure_origin(origin)?; + ensure!( + description.manifest.version == 1, + Error::::UnsupportedManifestVersion + ); + Self::add_ticket(TicketInfo { + system: true, + owner: [0u8; 32].into(), + workers: WorkerSet::Any, + app_address: description.manifest.address(sp_core::hashing::blake2_256), + description, + }); + Ok(()) + } + + /// Close a ticket + #[pallet::call_index(2)] + #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] + pub fn close_ticket(origin: OriginFor, ticket_id: TicketId) -> DispatchResult { + let owner = ensure_signed(origin)?; + let info = Tickets::::get(ticket_id).ok_or(Error::::TicketNotFound)?; + ensure!(owner == info.owner.into(), Error::::NotAllowed); + + // Refund the deposit + let ticket_account = ticket_account_address(ticket_id).into(); + let deposit = ::Currency::free_balance(&ticket_account); + if !deposit.is_zero() { + ::Currency::transfer(&ticket_account, &owner, deposit, AllowDeath)?; + } + Tickets::::remove(ticket_id); + Ok(()) + } + + #[pallet::call_index(3)] + #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] + pub fn submit_bench_message( + origin: OriginFor, + message: SignedMessage, + ) -> DispatchResult { + let _ = ensure_signed(origin)?; + ensure!( + message.verify::(), + Error::::SignatureVerificationFailed + ); + let worker_pubkey = WorkerPublicKey(message.worker_pubkey); + ensure!( + crate::registry::Pallet::::worker_exsists(&worker_pubkey), + Error::::InvalidWorkerPubkey + ); + let bench_app_info = BenchmarkAddresses::::get(&message.app_address) + .ok_or(Error::::InvalidBenchApp)?; + match message.message { + SigningMessage::BenchScore { + gas_per_second, + gas_consumed, + timestamp_secs, + } => { + use frame_support::traits::UnixTime; + + let now = T::UnixTime::now().as_secs() as i64; + let diff = (now - timestamp_secs as i64).abs(); + ensure!(diff < 600, Error::::OutdatedMessage); + + // Update the worker init score + let gas_6secs = gas_per_second.saturating_mul(6); + let score = bench_app_info.score_ratio.saturating_mul_u64(gas_6secs); + let p_init = + crate::registry::Pallet::::update_worker_score(&worker_pubkey, score); + // If the worker is scheduled working by the chain, simulate a heartbeat message. + if let Some(mut working_state) = WorkingWorkers::::get(&worker_pubkey) { + let delta_time = now - working_state.last_update_time; + if delta_time <= 0 { + return Ok(()); + } + let iterations = + bench_app_info.score_ratio.saturating_mul_u64(gas_consumed); + let delta_iterations = iterations - working_state.last_iterations; + let p_instant = delta_iterations / delta_time as u64 * 6; + let p_max = p_init * 120 / 100; + let p_instant = p_instant.min(p_max) as u32; + let worker = MessageOrigin::Worker(worker_pubkey.into()); + + let worker_report = WorkingReportEvent::HeartbeatV3 { + iterations, + session_id: working_state.session_id, + p_instant, + }; + crate::mq::Pallet::::push_bound_message(worker, worker_report); + + working_state.last_iterations = iterations; + working_state.last_update_time = now; + WorkingWorkers::::insert(&worker_pubkey, working_state); + } + } + }; + Ok(()) + } + } + + impl Pallet + where + T: crate::mq::Config, + T::AccountId: Into + From, + { + fn add_ticket(info: TicketInfo) -> TicketId { + let id = { + let id = NextTicketId::::get(); + NextTicketId::::put(id.wrapping_add(1)); + id + }; + Tickets::::insert(id, info); + id + } + + pub fn on_worker_event_received(message: DecodedMessage) -> DispatchResult { + ensure!(message.sender.is_pallet(), Error::::InvalidMessageSender); + let SystemEvent::WorkerEvent(event) = message.payload else { + return Ok(()); + }; + let worker_pubkey = event.pubkey; + match event.event { + WorkerEvent::Registered(_) => (), + WorkerEvent::BenchStart { duration: _ } => (), + WorkerEvent::BenchScore(_) => (), + WorkerEvent::Started { session_id, .. } => { + WorkingWorkers::::insert( + &worker_pubkey, + WorkerState { + session_id, + unresponsive: false, + last_iterations: 0, + last_update_time: 0, + }, + ); + } + WorkerEvent::Stopped => { + WorkingWorkers::::remove(&worker_pubkey); + } + WorkerEvent::EnterUnresponsive => { + WorkingWorkers::::mutate(&worker_pubkey, |state| { + if let Some(state) = state { + state.unresponsive = true; + } + }); + } + WorkerEvent::ExitUnresponsive => { + WorkingWorkers::::mutate(&worker_pubkey, |state| { + if let Some(state) = state { + state.unresponsive = false; + } + }); + } + } + Ok(()) + } + } +} From 8e3b559eb9688fd36e4f23b3d2c7c53a6fd5205c Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Thu, 27 Jun 2024 18:02:15 +0800 Subject: [PATCH 04/25] Update dep url --- pallets/phala/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/phala/Cargo.toml b/pallets/phala/Cargo.toml index f84239ff1..b4fb6ff3b 100644 --- a/pallets/phala/Cargo.toml +++ b/pallets/phala/Cargo.toml @@ -47,7 +47,7 @@ fixed-sqrt = { version = "0.2", default-features = false } sgx-attestation = { path = "../../crates/sgx-attestation", default-features = false, features = ["verify"] } [dependencies.wapod-eco-types] -path = "/home/kvin/codes/chain/phala/wapo/wapod-eco-types" +path = "../../../wapo/wapod-eco-types/" [dev-dependencies] frame-support-test = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "release-polkadot-v1.5.0" } From 3ddb5e8eb3ccb7579f978862aac02c393fba488b Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Thu, 27 Jun 2024 10:23:23 +0000 Subject: [PATCH 05/25] Rearrange files --- .../src/{wapod_workers/tickets.rs => wapod_workers.rs} | 8 ++++++-- pallets/phala/src/wapod_workers/mod.rs | 3 --- pallets/phala/src/wapod_workers/mq.rs | 0 3 files changed, 6 insertions(+), 5 deletions(-) rename pallets/phala/src/{wapod_workers/tickets.rs => wapod_workers.rs} (98%) delete mode 100644 pallets/phala/src/wapod_workers/mod.rs delete mode 100644 pallets/phala/src/wapod_workers/mq.rs diff --git a/pallets/phala/src/wapod_workers/tickets.rs b/pallets/phala/src/wapod_workers.rs similarity index 98% rename from pallets/phala/src/wapod_workers/tickets.rs rename to pallets/phala/src/wapod_workers.rs index 78fbf0376..7d4acdd9a 100644 --- a/pallets/phala/src/wapod_workers/tickets.rs +++ b/pallets/phala/src/wapod_workers.rs @@ -1,4 +1,4 @@ -//! The Phat Contract tokenomic module +//! The pallet managing the wapod workers. pub use self::pallet::*; @@ -139,6 +139,10 @@ pub mod pallet { #[pallet::storage] pub type WorkerLists = StorageMap<_, Twox64Concat, ListId, WorkerListInfo>; + #[pallet::storage] + pub type WorkerListWorkers = + StorageDoubleMap<_, Twox64Concat, ListId, Twox64Concat, WorkerPublicKey, ()>; + #[pallet::storage] pub type WorkerDescriptions = StorageMap<_, Twox64Concat, WorkerPublicKey, WorkerDescription>; @@ -384,4 +388,4 @@ pub mod pallet { Ok(()) } } -} +} \ No newline at end of file diff --git a/pallets/phala/src/wapod_workers/mod.rs b/pallets/phala/src/wapod_workers/mod.rs deleted file mode 100644 index c06ea4bf8..000000000 --- a/pallets/phala/src/wapod_workers/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ - -mod tickets; -mod mq; \ No newline at end of file diff --git a/pallets/phala/src/wapod_workers/mq.rs b/pallets/phala/src/wapod_workers/mq.rs deleted file mode 100644 index e69de29bb..000000000 From 538f7d59fe4ceeebc1bb1278ec092a1937095e5a Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Fri, 28 Jun 2024 12:39:03 +0800 Subject: [PATCH 06/25] Add extrinsics to manipulate worker register infomations --- pallets/phala/src/lib.rs | 3 +- pallets/phala/src/wapod_workers.rs | 268 ++++++++++++++++++++++++++--- standalone/runtime/src/lib.rs | 34 ++-- 3 files changed, 265 insertions(+), 40 deletions(-) diff --git a/pallets/phala/src/lib.rs b/pallets/phala/src/lib.rs index 8dadac914..b8bc6475b 100644 --- a/pallets/phala/src/lib.rs +++ b/pallets/phala/src/lib.rs @@ -18,6 +18,7 @@ pub mod phat; pub mod puppets; pub mod registry; pub mod stake_pool; +pub mod phat_tokenomic; pub mod wapod_workers; use compute::{base_pool, computation, pool_proxy, stake_pool_v2, vault, wrapped_balances}; @@ -49,7 +50,7 @@ pub use phat as pallet_phat; pub use phat_tokenomic as pallet_phat_tokenomic; pub use registry as pallet_registry; pub use stake_pool as pallet_stake_pool; -pub mod phat_tokenomic; +pub use wapod_workers as pallet_wapod_workers; #[cfg(feature = "native")] use sp_core::hashing; diff --git a/pallets/phala/src/wapod_workers.rs b/pallets/phala/src/wapod_workers.rs index 7d4acdd9a..e5fdecf43 100644 --- a/pallets/phala/src/wapod_workers.rs +++ b/pallets/phala/src/wapod_workers.rs @@ -4,6 +4,7 @@ pub use self::pallet::*; #[frame_support::pallet] pub mod pallet { + use crate::{mq, registry}; use frame_support::{ dispatch::DispatchResult, ensure, @@ -17,10 +18,10 @@ pub mod pallet { }; use sp_runtime::{traits::Zero, SaturatedConversion}; use wapod_eco_types::{ - bench_app::{SignedMessage, SigningMessage}, + bench_app::{MetricsToken, SignedMessage, SigningMessage}, crypto::CryptoProvider, - primitives::BoundedString, - ticket::{Prices, TicketDescription}, + primitives::{BoundedString, BoundedVec}, + ticket::{Prices, SignedWorkerDescription, TicketDescription, WorkerDescription}, }; type BalanceOf = @@ -39,9 +40,10 @@ pub mod pallet { impl Fraction { fn saturating_mul_u64(&self, rhs: u64) -> u64 { + let rhs = rhs as u128; let numerator = self.numerator as u128; let denominator = self.denominator as u128; - let result = (numerator * rhs as u128) / denominator; + let result = (numerator * rhs) / u128::max(denominator, 1); result.saturated_into() } } @@ -54,6 +56,14 @@ pub mod pallet { score_ratio: Fraction, } + #[derive(Encode, Decode, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] + #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] + pub struct WorkerSession { + pub session_id: [u8; 32], + pub last_nonce: [u8; 32], + pub last_metrics_sn: u64, + } + struct SpCrypto; impl CryptoProvider for SpCrypto { fn sr25519_verify(public_key: &[u8], message: &[u8], signature: &[u8]) -> bool { @@ -97,24 +107,18 @@ pub mod pallet { pub struct WorkerListInfo { pub owner: AcountId32, pub prices: Prices, + pub description: BoundedString<1024>, } #[derive(Encode, Decode, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] - pub struct WorkerState { + pub struct WorkingState { session_id: u32, unresponsive: bool, last_iterations: u64, last_update_time: i64, } - #[derive(Encode, Decode, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] - #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] - pub struct WorkerDescription { - prices: Prices, - description: BoundedString<1024>, - } - #[pallet::config] pub trait Config: frame_system::Config { type RuntimeEvent: From> + IsType<::RuntimeEvent>; @@ -130,36 +134,51 @@ pub mod pallet { #[pallet::storage] pub type NextTicketId = StorageValue<_, TicketId, ValueQuery>; + /// Active tickets. + /// Each ticket holds a payment infomation to a target app address. Multiple ticket can pay for a same app at the sametime. #[pallet::storage] pub type Tickets = StorageMap<_, Twox64Concat, TicketId, TicketInfo>; #[pallet::storage] pub type NextWorkerListId = StorageValue<_, ListId, ValueQuery>; + /// Worker lists. + /// + /// A worker list is a collection of workers that with the same price. #[pallet::storage] pub type WorkerLists = StorageMap<_, Twox64Concat, ListId, WorkerListInfo>; + /// Concrete workers associated to worker list. #[pallet::storage] pub type WorkerListWorkers = StorageDoubleMap<_, Twox64Concat, ListId, Twox64Concat, WorkerPublicKey, ()>; + /// Information about workers. #[pallet::storage] pub type WorkerDescriptions = StorageMap<_, Twox64Concat, WorkerPublicKey, WorkerDescription>; + /// V3 information about workers. #[pallet::storage] - pub type WorkingWorkers = StorageMap<_, Twox64Concat, WorkerPublicKey, WorkerState>; + pub type WorkerSessions = StorageMap<_, Twox64Concat, WorkerPublicKey, WorkerSession>; + /// Working state of wapod workers. V2 compatible. #[pallet::storage] - pub type BenchmarkAddresses = StorageMap<_, Twox64Concat, Address, BenchAppInfo>; + pub type WorkingWorkers = StorageMap<_, Twox64Concat, WorkerPublicKey, WorkingState>; + /// Allowed app addresses that used to benchmark workers. #[pallet::storage] - pub type PrimaryBenchmarkAddress = StorageValue<_, Address>; + pub type BenchmarkApps = StorageMap<_, Twox64Concat, Address, BenchAppInfo>; + + /// Current recommended app address used to benchmark workers. + #[pallet::storage] + pub type RecommendedBenchmarkApp = StorageValue<_, Address>; #[pallet::error] pub enum Error { UnsupportedManifestVersion, NotAllowed, + WorkerNotFound, WorkerListNotFound, TicketNotFound, SignatureVerificationFailed, @@ -167,11 +186,40 @@ pub mod pallet { InvalidBenchApp, OutdatedMessage, InvalidMessageSender, + PriceMismatch, + SessionMismatch, } #[pallet::event] #[pallet::generate_deposit(fn deposit_event)] - pub enum Event {} + pub enum Event { + TicketCreated { + id: TicketId, + }, + TicketClosed { + id: TicketId, + }, + WorkerListCreated { + id: ListId, + }, + WorkersAddedToList { + list_id: ListId, + workers: Vec, + }, + WorkerRemovedFromList { + list_id: ListId, + worker: WorkerPublicKey, + }, + WorkerDescriptionSet { + worker: WorkerPublicKey, + }, + BenchmarkAppAdded { + address: Address, + }, + RecommendedBenchmarkAppChanged { + address: Address, + }, + } const TICKET_ADDRESS_PREFIX: &[u8] = b"wapod/ticket/"; @@ -190,8 +238,8 @@ pub mod pallet { #[pallet::call] impl Pallet where - T: crate::mq::Config, - T: crate::registry::Config, + T: mq::Config, + T: registry::Config, T::AccountId: Into + From, { /// Create a new ticket @@ -262,6 +310,7 @@ pub mod pallet { ::Currency::transfer(&ticket_account, &owner, deposit, AllowDeath)?; } Tickets::::remove(ticket_id); + Self::deposit_event(Event::TicketClosed { id: ticket_id }); Ok(()) } @@ -278,16 +327,17 @@ pub mod pallet { ); let worker_pubkey = WorkerPublicKey(message.worker_pubkey); ensure!( - crate::registry::Pallet::::worker_exsists(&worker_pubkey), + registry::Pallet::::worker_exsists(&worker_pubkey), Error::::InvalidWorkerPubkey ); - let bench_app_info = BenchmarkAddresses::::get(&message.app_address) - .ok_or(Error::::InvalidBenchApp)?; + let bench_app_info = + BenchmarkApps::::get(&message.app_address).ok_or(Error::::InvalidBenchApp)?; match message.message { SigningMessage::BenchScore { gas_per_second, gas_consumed, timestamp_secs, + matrics_token, } => { use frame_support::traits::UnixTime; @@ -295,11 +345,12 @@ pub mod pallet { let diff = (now - timestamp_secs as i64).abs(); ensure!(diff < 600, Error::::OutdatedMessage); + Self::update_metrics_token(&worker_pubkey, &matrics_token)?; + // Update the worker init score let gas_6secs = gas_per_second.saturating_mul(6); let score = bench_app_info.score_ratio.saturating_mul_u64(gas_6secs); - let p_init = - crate::registry::Pallet::::update_worker_score(&worker_pubkey, score); + let p_init = registry::Pallet::::update_worker_score(&worker_pubkey, score); // If the worker is scheduled working by the chain, simulate a heartbeat message. if let Some(mut working_state) = WorkingWorkers::::get(&worker_pubkey) { let delta_time = now - working_state.last_update_time; @@ -314,12 +365,13 @@ pub mod pallet { let p_instant = p_instant.min(p_max) as u32; let worker = MessageOrigin::Worker(worker_pubkey.into()); + // Minic the worker heartbeat message let worker_report = WorkingReportEvent::HeartbeatV3 { iterations, session_id: working_state.session_id, p_instant, }; - crate::mq::Pallet::::push_bound_message(worker, worker_report); + mq::Pallet::::push_bound_message(worker, worker_report); working_state.last_iterations = iterations; working_state.last_update_time = now; @@ -329,11 +381,140 @@ pub mod pallet { }; Ok(()) } + + /// Create a new worker list + #[pallet::call_index(4)] + #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] + pub fn create_worker_list( + origin: OriginFor, + prices: Prices, + description: BoundedString<1024>, + ) -> DispatchResult { + let owner = ensure_signed(origin)?; + Self::add_worker_list(WorkerListInfo { + owner: owner.into(), + prices, + description, + }); + Ok(()) + } + + /// Add a worker to a worker list + #[pallet::call_index(5)] + #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] + pub fn add_workers_to_list( + origin: OriginFor, + list_id: ListId, + workers: BoundedVec, + ) -> DispatchResult { + let owner = ensure_signed(origin)?; + let list_info = WorkerLists::::get(list_id).ok_or(Error::::WorkerListNotFound)?; + ensure!(owner == list_info.owner.into(), Error::::NotAllowed); + for worker in workers.iter() { + let Some(worker_info) = WorkerDescriptions::::get(worker) else { + return Err(Error::::WorkerNotFound.into()); + }; + ensure!( + worker_info.prices == Default::default() + || worker_info.prices == list_info.prices, + Error::::PriceMismatch + ); + WorkerListWorkers::::insert(list_id, worker, ()); + } + Self::deposit_event(Event::WorkersAddedToList { + list_id, + workers: workers.into(), + }); + Ok(()) + } + + /// Remove a worker from a worker list + #[pallet::call_index(6)] + #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] + pub fn remove_worker_from_list( + origin: OriginFor, + list_id: ListId, + worker: WorkerPublicKey, + ) -> DispatchResult { + let owner = ensure_signed(origin)?; + let list_info = WorkerLists::::get(list_id).ok_or(Error::::WorkerListNotFound)?; + ensure!(owner == list_info.owner.into(), Error::::NotAllowed); + WorkerListWorkers::::remove(list_id, worker); + Self::deposit_event(Event::WorkerRemovedFromList { list_id, worker }); + Ok(()) + } + + /// Set worker description + #[pallet::call_index(7)] + #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] + pub fn set_worker_description( + origin: OriginFor, + signed_description: SignedWorkerDescription, + ) -> DispatchResult { + let _ = ensure_signed(origin)?; + let worker_pubkey = WorkerPublicKey(signed_description.worker_pubkey); + // Worker price can only be set once + ensure!( + !WorkerDescriptions::::contains_key(&worker_pubkey), + Error::::NotAllowed + ); + ensure!( + registry::Pallet::::worker_exsists(&worker_pubkey), + Error::::InvalidWorkerPubkey + ); + ensure!( + signed_description.verify::(), + Error::::SignatureVerificationFailed + ); + WorkerDescriptions::::insert(&worker_pubkey, signed_description.worker_description); + Self::deposit_event(Event::WorkerDescriptionSet { + worker: worker_pubkey, + }); + Ok(()) + } + + /// Add a benchmark app (governance only) + #[pallet::call_index(8)] + #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] + pub fn add_benchmark_app( + origin: OriginFor, + ticket: TicketId, + version: u32, + score_ratio: Fraction, + ) -> DispatchResult { + T::GovernanceOrigin::ensure_origin(origin)?; + let address = Tickets::::get(ticket) + .ok_or(Error::::TicketNotFound)? + .app_address; + BenchmarkApps::::insert( + address, + BenchAppInfo { + version, + ticket, + score_ratio, + }, + ); + Self::deposit_event(Event::BenchmarkAppAdded { address }); + Ok(()) + } + + /// Set recommended benchmark app (governance only) + #[pallet::call_index(9)] + #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] + pub fn set_recommended_benchmark_app( + origin: OriginFor, + address: Address, + ) -> DispatchResult { + T::GovernanceOrigin::ensure_origin(origin)?; + RecommendedBenchmarkApp::::set(Some(address)); + Self::deposit_event(Event::RecommendedBenchmarkAppChanged { address }); + Ok(()) + } } impl Pallet where - T: crate::mq::Config, + T: mq::Config, T::AccountId: Into + From, { fn add_ticket(info: TicketInfo) -> TicketId { @@ -343,9 +524,42 @@ pub mod pallet { id }; Tickets::::insert(id, info); + Self::deposit_event(Event::TicketCreated { id }); + id + } + + fn add_worker_list(info: WorkerListInfo) -> ListId { + let id = { + let id = NextWorkerListId::::get(); + NextWorkerListId::::put(id.wrapping_add(1)); + id + }; + WorkerLists::::insert(id, info); + Self::deposit_event(Event::WorkerListCreated { id }); id } + fn update_metrics_token( + worker_pubkey: &WorkerPublicKey, + matrics_token: &MetricsToken, + ) -> DispatchResult { + let Some(mut worker_session) = WorkerSessions::::get(worker_pubkey) else { + return Err(Error::::WorkerNotFound.into()); + }; + ensure!( + worker_session.last_metrics_sn < matrics_token.metrics_sn, + Error::::SessionMismatch + ); + ensure!( + worker_session.session_id == matrics_token.worker_session, + Error::::OutdatedMessage + ); + worker_session.last_metrics_sn = matrics_token.metrics_sn; + worker_session.last_nonce = matrics_token.nonce; + WorkerSessions::::insert(worker_pubkey, worker_session); + Ok(()) + } + pub fn on_worker_event_received(message: DecodedMessage) -> DispatchResult { ensure!(message.sender.is_pallet(), Error::::InvalidMessageSender); let SystemEvent::WorkerEvent(event) = message.payload else { @@ -359,7 +573,7 @@ pub mod pallet { WorkerEvent::Started { session_id, .. } => { WorkingWorkers::::insert( &worker_pubkey, - WorkerState { + WorkingState { session_id, unresponsive: false, last_iterations: 0, @@ -388,4 +602,4 @@ pub mod pallet { Ok(()) } } -} \ No newline at end of file +} diff --git a/standalone/runtime/src/lib.rs b/standalone/runtime/src/lib.rs index 1c2d16167..2aa8dc102 100644 --- a/standalone/runtime/src/lib.rs +++ b/standalone/runtime/src/lib.rs @@ -39,8 +39,8 @@ use frame_support::{ fungible::HoldConsideration, tokens::{PayFromAccount, UnityAssetBalanceConversion}, AsEnsureOriginWithArg, ConstU128, ConstU32, Currency, EitherOfDiverse, EqualPrivilegeOnly, - Everything, Imbalance, InstanceFilter, KeyOwnerProofSystem, LockIdentifier, OnUnbalanced, - SortedMembers, WithdrawReasons, LinearStoragePrice, + Everything, Imbalance, InstanceFilter, KeyOwnerProofSystem, LinearStoragePrice, + LockIdentifier, OnUnbalanced, SortedMembers, WithdrawReasons, }, weights::{ constants::{ @@ -110,7 +110,7 @@ mod voter_bags; pub use phala_pallets::{ pallet_base_pool, pallet_computation, pallet_mq, pallet_phat, pallet_phat_tokenomic, - pallet_registry, pallet_stake_pool, pallet_stake_pool_v2, pallet_vault, + pallet_registry, pallet_stake_pool, pallet_stake_pool_v2, pallet_vault, pallet_wapod_workers, pallet_wrapped_balances, puppets, }; use phat_offchain_rollup::{anchor as pallet_anchor, oracle as pallet_oracle}; @@ -337,8 +337,9 @@ impl InstanceFilter for ProxyType { | RuntimeCall::Elections(..) | RuntimeCall::Treasury(..) ), - ProxyType::Staking => - matches!(c, RuntimeCall::Staking(..) | RuntimeCall::FastUnstake(..)), + ProxyType::Staking => { + matches!(c, RuntimeCall::Staking(..) | RuntimeCall::FastUnstake(..)) + } ProxyType::StakePoolManager => matches!( c, RuntimeCall::Utility { .. } @@ -450,7 +451,7 @@ impl pallet_babe::Config for Runtime { type KeyOwnerProof = >::Proof; type EquivocationReportSystem = - pallet_babe::EquivocationReportSystem; + pallet_babe::EquivocationReportSystem; } parameter_types! { @@ -713,13 +714,16 @@ impl Get> for OffchainRandomBalancing { max => { let seed = sp_io::offchain::random_seed(); let random = ::decode(&mut TrailingZeroInput::new(&seed)) - .expect("input is padded with zeroes; qed") % - max.saturating_add(1); + .expect("input is padded with zeroes; qed") + % max.saturating_add(1); random as usize - }, + } }; - let config = BalancingConfig { iterations, tolerance: 0 }; + let config = BalancingConfig { + iterations, + tolerance: 0, + }; Some(config) } } @@ -1212,7 +1216,7 @@ impl pallet_grandpa::Config for Runtime { type MaxSetIdSessionEntries = MaxSetIdSessionEntries; type KeyOwnerProof = >::Proof; type EquivocationReportSystem = - pallet_grandpa::EquivocationReportSystem; + pallet_grandpa::EquivocationReportSystem; } parameter_types! { @@ -1280,7 +1284,7 @@ impl pallet_society::Config for Runtime { type ClaimPeriod = ClaimPeriod; type MaxLockDuration = MaxLockDuration; type FounderSetOrigin = - pallet_collective::EnsureProportionMoreThan; + pallet_collective::EnsureProportionMoreThan; type ChallengePeriod = ChallengePeriod; type MaxPayouts = MaxPayouts; type MaxBids = MaxBids; @@ -1526,6 +1530,11 @@ impl pallet_phat_tokenomic::Config for Runtime { type Currency = Balances; } +impl pallet_wapod_workers::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; +} + parameter_types! { pub const QueuePrefix: &'static [u8] = b"_queue/"; pub const QueueCapacity: u32 = 128; @@ -1626,6 +1635,7 @@ construct_runtime!( PhalaBasePool: pallet_base_pool, PhalaPhatContracts: pallet_phat, PhalaPhatTokenomic: pallet_phat_tokenomic, + PhalaWapodWorkers: pallet_wapod_workers, // Rollup and Oracles PhatRollupAnchor: pallet_anchor = 100, From fd418b5a2b0b3d9372176f0eeb943b76c3488f89 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Tue, 2 Jul 2024 08:32:01 +0800 Subject: [PATCH 07/25] Add option to disable V increasing --- crates/phactory/src/system/gk.rs | 127 +++++++++++++++++++++-- crates/phala-types/src/lib.rs | 1 + pallets/phala/src/compute/computation.rs | 15 +++ 3 files changed, 133 insertions(+), 10 deletions(-) diff --git a/crates/phactory/src/system/gk.rs b/crates/phactory/src/system/gk.rs index b51f6fc55..c168f4261 100644 --- a/crates/phactory/src/system/gk.rs +++ b/crates/phactory/src/system/gk.rs @@ -433,6 +433,9 @@ where GatekeeperEvent::_RepairV | GatekeeperEvent::_PhalaLaunched | GatekeeperEvent::_UnrespFix => unreachable!(), + GatekeeperEvent::SetStaticV { .. } => { + // Handled by ComputingEconomics + } } } @@ -1178,6 +1181,11 @@ impl> ComputingEconomics unreachable!(), + GatekeeperEvent::SetStaticV { enabled } => { + if origin.is_pallet() { + self.tokenomic_params.set_static_v(enabled); + } + } } } @@ -1185,7 +1193,7 @@ impl> ComputingEconomics for Params { - fn from(params: TokenomicParameters) -> Self { + impl Params { + pub fn update(&mut self, params: TokenomicParameters) { let treasury_ration = FixedPoint::from_bits(params.treasury_ratio); let payout_ration = fp!(1) - treasury_ration; - Params { + *self = Params { rho: FixedPoint::from_bits(params.rho), slash_rate: FixedPoint::from_bits(params.slash_rate), budget_per_block: FixedPoint::from_bits(params.budget_per_block), @@ -1364,7 +1375,12 @@ mod tokenomic { treasury_ration, payout_ration, heartbeat_window: params.heartbeat_window, - } + static_v: self.static_v, + }; + } + + pub fn set_static_v(&mut self, enabled: bool) { + self.static_v = enabled; } } @@ -1379,6 +1395,7 @@ mod tokenomic { treasury_ration: fp!(0.2), payout_ration: fp!(0.8), heartbeat_window: 10, + static_v: false, } } @@ -1393,6 +1410,9 @@ mod tokenomic { /// case1: Idle, no event pub fn update_v_idle(&mut self, params: &Params) { + if params.static_v { + return; + } let cost_idle = params.cost_k * self.p_bench + params.cost_b; let perf_multiplier = if self.p_bench == fp!(0) { fp!(1) @@ -1418,7 +1438,7 @@ mod tokenomic { if sum_share == fp!(0) { return NO_UPDATE; } - if self.v_deductible == fp!(0) { + if !params.static_v && self.v_deductible == fp!(0) { return NO_UPDATE; } if block_number <= self.v_update_block { @@ -1434,10 +1454,11 @@ mod tokenomic { let actual_payout = budget * params.payout_ration; let actual_treasury = budget * params.treasury_ration; - let actual_v_deduct = self.v_deductible.clamp(fp!(0), actual_payout); - self.v -= actual_v_deduct; - - self.v_deductible = fp!(0); + if !params.static_v { + let actual_v_deduct = self.v_deductible.clamp(fp!(0), actual_payout); + self.v -= actual_v_deduct; + self.v_deductible = fp!(0); + } self.v_update_at = now_ms; self.v_update_block = block_number; @@ -1894,6 +1915,92 @@ pub mod tests { ); } + #[test] + fn static_v_works() { + let mut r = Roles::test_roles(); + let mut block_number = 1; + + r.gk.tokenomic_params.set_static_v(true); + + // Register worker + with_block(block_number, |block| { + let mut worker0 = r.for_worker(0); + worker0.pallet_say(msg::WorkerEvent::Registered(msg::WorkerInfo { + confidence_level: 2, + })); + r.gk.test_process_messages(block); + }); + + // Start computing & send heartbeat challenge + block_number += 1; + with_block(block_number, |block| { + let mut worker0 = r.for_worker(0); + worker0.pallet_say(msg::WorkerEvent::Started { + session_id: 1, + init_v: fp!(100).to_bits(), + init_p: 200, + }); + r.gk.test_process_messages(block); + }); + + block_number += 1; + + // Normal Idle state, no event + let v_snap = r.get_worker(0).tokenomic.v; + r.gk.egress.clear(); + with_block(block_number, |block| { + r.gk.test_process_messages(block); + }); + + assert!(!r.get_worker(0).unresponsive, "Worker should be online"); + assert_eq!( + r.gk.egress.drain_working_info_update_event().len(), + 0, + "Should not report any event" + ); + + assert!( + v_snap == r.get_worker(0).tokenomic.v, + "Worker V should not increase" + ); + + // Once again. + let v_snap = r.get_worker(0).tokenomic.v; + r.gk.egress.clear(); + with_block(block_number, |block| { + r.gk.test_process_messages(block); + }); + + assert!(!r.get_worker(0).unresponsive, "Worker should be online"); + assert_eq!( + r.gk.egress.drain_working_info_update_event().len(), + 0, + "Should not report any event" + ); + assert!( + v_snap == r.get_worker(0).tokenomic.v, + "Worker V should not increase" + ); + + block_number += 1; + with_block(block_number, |block| { + let mut worker0 = r.for_worker(0); + worker0.challenge(); + r.gk.test_process_messages(block); + }); + + block_number += 1; + with_block(block_number, |block| { + let mut worker0 = r.for_worker(0); + worker0.heartbeat(1, block_number - 1, 1000000000); + r.gk.test_process_messages(block); + }); + let egress = r.gk.egress.drain_working_info_update_event(); + assert_eq!(egress.len(), 1, "Should payout"); + let payout = FixedPoint::from_bits(egress[0].settle[0].payout); + assert_eq!(payout, fp!(285.4000288551775845473)); + } + #[test] fn gk_should_report_payout_for_normal_heartbeats_case2() { let mut r = Roles::test_roles(); diff --git a/crates/phala-types/src/lib.rs b/crates/phala-types/src/lib.rs index 2c9580015..0bd43eb5e 100644 --- a/crates/phala-types/src/lib.rs +++ b/crates/phala-types/src/lib.rs @@ -392,6 +392,7 @@ pub mod messaging { /// Fix the payout duration problem in unresponsive state. /// Dropped in Phala. The index is reserved here for Khala+pruntime-v0 compatibility. _UnrespFix, + SetStaticV { enabled: bool }, } impl GatekeeperEvent { diff --git a/pallets/phala/src/compute/computation.rs b/pallets/phala/src/compute/computation.rs index abb9519f7..f7b1758f4 100644 --- a/pallets/phala/src/compute/computation.rs +++ b/pallets/phala/src/compute/computation.rs @@ -436,6 +436,9 @@ pub mod pallet { nonce: u64, budget: u128, }, + StaticVChanged { + enabled: bool, + }, } #[pallet::error] @@ -632,6 +635,18 @@ pub mod pallet { ContractAccount::::put(account_id); Ok(()) } + + /// Enable static V. + /// + /// When enabled, the V of a worker doesn't increase on IDLE. + #[pallet::call_index(9)] + #[pallet::weight(Weight::from_parts(1, 0))] + pub fn set_static_v(origin: OriginFor, enabled: bool) -> DispatchResult { + T::GovernanceOrigin::ensure_origin(origin)?; + Self::push_message(GatekeeperEvent::SetStaticV { enabled }); + Self::deposit_event(Event::::StaticVChanged { enabled }); + Ok(()) + } } #[pallet::hooks] From db9e12e517e9da04f9f16f98cb1b39fab53f4d3e Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Wed, 3 Jul 2024 01:30:09 +0000 Subject: [PATCH 08/25] Fix compilation issues --- pallets/phala/Cargo.toml | 2 + pallets/phala/src/wapod_workers.rs | 58 ++++++++++++--------------- standalone/runtime/src/msg_routing.rs | 1 + 3 files changed, 28 insertions(+), 33 deletions(-) diff --git a/pallets/phala/Cargo.toml b/pallets/phala/Cargo.toml index b4fb6ff3b..d41617ff4 100644 --- a/pallets/phala/Cargo.toml +++ b/pallets/phala/Cargo.toml @@ -48,6 +48,7 @@ sgx-attestation = { path = "../../crates/sgx-attestation", default-features = fa [dependencies.wapod-eco-types] path = "../../../wapo/wapod-eco-types/" +default-features = false [dev-dependencies] frame-support-test = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "release-polkadot-v1.5.0" } @@ -84,6 +85,7 @@ std = [ "serde/derive", "serde/alloc", "sgx-attestation/std", + "wapod-eco-types/std", ] runtime-benchmarks = [ ] diff --git a/pallets/phala/src/wapod_workers.rs b/pallets/phala/src/wapod_workers.rs index e5fdecf43..9cb15d3d3 100644 --- a/pallets/phala/src/wapod_workers.rs +++ b/pallets/phala/src/wapod_workers.rs @@ -5,6 +5,7 @@ pub use self::pallet::*; #[frame_support::pallet] pub mod pallet { use crate::{mq, registry}; + use alloc::vec::Vec; use frame_support::{ dispatch::DispatchResult, ensure, @@ -16,12 +17,13 @@ pub mod pallet { messaging::{DecodedMessage, MessageOrigin, SystemEvent, WorkerEvent, WorkingReportEvent}, WorkerPublicKey, }; + use scale_info::TypeInfo; use sp_runtime::{traits::Zero, SaturatedConversion}; use wapod_eco_types::{ bench_app::{MetricsToken, SignedMessage, SigningMessage}, crypto::CryptoProvider, primitives::{BoundedString, BoundedVec}, - ticket::{Prices, SignedWorkerDescription, TicketDescription, WorkerDescription}, + ticket::{Prices, SignedWorkerDescription, WorkerDescription}, }; type BalanceOf = @@ -31,8 +33,7 @@ pub mod pallet { pub type ListId = u32; pub type Address = [u8; 32]; - #[derive(Encode, Decode, Debug, Clone, Copy, PartialEq, Eq, MaxEncodedLen)] - #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] + #[derive(Encode, Decode, TypeInfo, Debug, Clone, Copy, PartialEq, Eq, MaxEncodedLen)] pub struct Fraction { pub numerator: u32, pub denominator: u32, @@ -48,16 +49,14 @@ pub mod pallet { } } - #[derive(Encode, Decode, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] - #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] + #[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] pub struct BenchAppInfo { version: u32, ticket: TicketId, score_ratio: Fraction, } - #[derive(Encode, Decode, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] - #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] + #[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] pub struct WorkerSession { pub session_id: [u8; 32], pub last_nonce: [u8; 32], @@ -83,8 +82,7 @@ pub mod pallet { } } - #[derive(Encode, Decode, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] - #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] + #[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] pub enum WorkerSet { Any, WorkerList(ListId), @@ -92,26 +90,24 @@ pub mod pallet { type AcountId32 = [u8; 32]; - #[derive(Encode, Decode, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] - #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] + #[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] pub struct TicketInfo { pub system: bool, pub owner: AcountId32, pub workers: WorkerSet, - pub app_address: [u8; 32], - pub description: TicketDescription, + pub address: [u8; 32], + pub prices: Prices, + pub content_cid: BoundedString<128>, } - #[derive(Encode, Decode, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] - #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] + #[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] pub struct WorkerListInfo { pub owner: AcountId32, pub prices: Prices, pub description: BoundedString<1024>, } - #[derive(Encode, Decode, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] - #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] + #[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] pub struct WorkingState { session_id: u32, unresponsive: bool, @@ -248,15 +244,12 @@ pub mod pallet { pub fn create_ticket( origin: OriginFor, deposit: BalanceOf, - description: TicketDescription, + address: Address, + content_cid: BoundedString<128>, worker_list: u32, + prices: Prices, ) -> DispatchResult { let owner = ensure_signed(origin)?; - ensure!( - description.manifest.version == 1, - Error::::UnsupportedManifestVersion - ); - ensure!(!description.manifest.resizable, Error::::NotAllowed); ensure!( WorkerLists::::contains_key(worker_list), Error::::WorkerListNotFound @@ -265,8 +258,9 @@ pub mod pallet { system: false, owner: owner.clone().into(), workers: WorkerSet::WorkerList(worker_list), - app_address: description.manifest.address(sp_core::hashing::blake2_256), - description, + address, + content_cid, + prices, }); let ticket_account = ticket_account_address(id).into(); ::Currency::transfer(&owner, &ticket_account, deposit, KeepAlive)?; @@ -278,19 +272,17 @@ pub mod pallet { #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] pub fn create_system_ticket( origin: OriginFor, - description: TicketDescription, + address: Address, + content_cid: BoundedString<128>, ) -> DispatchResult { T::GovernanceOrigin::ensure_origin(origin)?; - ensure!( - description.manifest.version == 1, - Error::::UnsupportedManifestVersion - ); Self::add_ticket(TicketInfo { system: true, owner: [0u8; 32].into(), workers: WorkerSet::Any, - app_address: description.manifest.address(sp_core::hashing::blake2_256), - description, + address, + content_cid, + prices: Default::default(), }); Ok(()) } @@ -485,7 +477,7 @@ pub mod pallet { T::GovernanceOrigin::ensure_origin(origin)?; let address = Tickets::::get(ticket) .ok_or(Error::::TicketNotFound)? - .app_address; + .address; BenchmarkApps::::insert( address, BenchAppInfo { diff --git a/standalone/runtime/src/msg_routing.rs b/standalone/runtime/src/msg_routing.rs index 2c351665d..27e13bbf7 100644 --- a/standalone/runtime/src/msg_routing.rs +++ b/standalone/runtime/src/msg_routing.rs @@ -38,6 +38,7 @@ impl pallet_mq::QueueNotifyConfig for MessageRouteConfig { PhalaPhatContracts::on_worker_cluster_message_received, PhalaPhatContracts::on_cluster_message_received, PhalaPhatContracts::on_contract_message_received, + PhalaWapodWorkers::on_worker_event_received, // BridgeTransfer::on_message_received, }; Ok(()) From 61726c7942e19c225c3438fe669f31651878bef1 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Wed, 3 Jul 2024 04:44:51 +0000 Subject: [PATCH 09/25] Minor refactor --- pallets/phala/src/wapod_workers.rs | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/pallets/phala/src/wapod_workers.rs b/pallets/phala/src/wapod_workers.rs index 9cb15d3d3..4ec066522 100644 --- a/pallets/phala/src/wapod_workers.rs +++ b/pallets/phala/src/wapod_workers.rs @@ -29,8 +29,8 @@ pub mod pallet { type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; - pub type TicketId = u32; - pub type ListId = u32; + pub type TicketId = u64; + pub type ListId = u64; pub type Address = [u8; 32]; #[derive(Encode, Decode, TypeInfo, Debug, Clone, Copy, PartialEq, Eq, MaxEncodedLen)] @@ -219,14 +219,14 @@ pub mod pallet { const TICKET_ADDRESS_PREFIX: &[u8] = b"wapod/ticket/"; - fn ticket_account_address(ticket_id: u32) -> [u8; 32] { + fn ticket_account_address(ticket_id: TicketId) -> [u8; 32] { let mut address = [0u8; 32]; let prefix = TICKET_ADDRESS_PREFIX; address[..prefix.len()].copy_from_slice(prefix); { - let ticket_bytes = ticket_id.to_be_bytes(); + let ticket_id_bytes = ticket_id.to_be_bytes(); let offset = prefix.len(); - address[offset..offset + ticket_bytes.len()].copy_from_slice(&ticket_bytes); + address[offset..offset + ticket_id_bytes.len()].copy_from_slice(&ticket_id_bytes); } address } @@ -246,7 +246,7 @@ pub mod pallet { deposit: BalanceOf, address: Address, content_cid: BoundedString<128>, - worker_list: u32, + worker_list: ListId, prices: Prices, ) -> DispatchResult { let owner = ensure_signed(origin)?; @@ -379,15 +379,19 @@ pub mod pallet { #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] pub fn create_worker_list( origin: OriginFor, - prices: Prices, description: BoundedString<1024>, + prices: Prices, + init_workers: BoundedVec, ) -> DispatchResult { - let owner = ensure_signed(origin)?; - Self::add_worker_list(WorkerListInfo { + let owner = ensure_signed(origin.clone())?; + let id = Self::add_worker_list(WorkerListInfo { owner: owner.into(), prices, description, }); + if init_workers.len() > 0 { + Self::add_workers_to_list(origin, id, init_workers)?; + } Ok(()) } From 13ebf561f8ab4b15d906ec2a049f36e78eb11d8a Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Mon, 8 Jul 2024 12:44:40 +0000 Subject: [PATCH 10/25] Update Cargo.toml --- Cargo.lock | 44 ++++++++++++++++------------------------ pallets/phala/Cargo.toml | 6 +++--- 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c7bc2f6f0..d7458a0e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2265,7 +2265,7 @@ dependencies = [ [[package]] name = "common" version = "0.1.0" -source = "git+https://github.com/w3f/ring-proof#b273d33f9981e2bb3375ab45faeb537f7ee35224" +source = "git+https://github.com/w3f/ring-proof#96137b150288a66bc9e4df495efc64769b5d1321" dependencies = [ "ark-ec", "ark-ff", @@ -10170,7 +10170,7 @@ dependencies = [ "sp-io", "sp-runtime", "sp-std 8.0.0", - "wapod-eco-types", + "wapod-types", ] [[package]] @@ -11968,7 +11968,7 @@ dependencies = [ [[package]] name = "ring" version = "0.1.0" -source = "git+https://github.com/w3f/ring-proof#b273d33f9981e2bb3375ab45faeb537f7ee35224" +source = "git+https://github.com/w3f/ring-proof#96137b150288a66bc9e4df495efc64769b5d1321" dependencies = [ "ark-ec", "ark-ff", @@ -14124,9 +14124,9 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] @@ -14154,9 +14154,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", @@ -15005,7 +15005,7 @@ dependencies = [ [[package]] name = "sp-crypto-ec-utils" version = "0.10.0" -source = "git+https://github.com/paritytech/polkadot-sdk#63e264446f6cabff06be72912eae902662dcb699" +source = "git+https://github.com/paritytech/polkadot-sdk#924728cf19523f826a08e1c0eeee711ca3bb8ee7" dependencies = [ "ark-bls12-377", "ark-bls12-377-ext", @@ -15055,7 +15055,7 @@ dependencies = [ [[package]] name = "sp-debug-derive" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#63e264446f6cabff06be72912eae902662dcb699" +source = "git+https://github.com/paritytech/polkadot-sdk#924728cf19523f826a08e1c0eeee711ca3bb8ee7" dependencies = [ "proc-macro2", "quote", @@ -15088,7 +15088,7 @@ dependencies = [ [[package]] name = "sp-externalities" version = "0.25.0" -source = "git+https://github.com/paritytech/polkadot-sdk#63e264446f6cabff06be72912eae902662dcb699" +source = "git+https://github.com/paritytech/polkadot-sdk#924728cf19523f826a08e1c0eeee711ca3bb8ee7" dependencies = [ "environmental", "parity-scale-codec", @@ -15307,7 +15307,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface" version = "24.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#63e264446f6cabff06be72912eae902662dcb699" +source = "git+https://github.com/paritytech/polkadot-sdk#924728cf19523f826a08e1c0eeee711ca3bb8ee7" dependencies = [ "bytes", "impl-trait-for-tuples", @@ -15352,7 +15352,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "17.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#63e264446f6cabff06be72912eae902662dcb699" +source = "git+https://github.com/paritytech/polkadot-sdk#924728cf19523f826a08e1c0eeee711ca3bb8ee7" dependencies = [ "Inflector", "expander", @@ -15450,7 +15450,7 @@ checksum = "54c78c5a66682568cc7b153603c5d01a2cc8f5c221c7b1e921517a0eef18ae05" [[package]] name = "sp-std" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#63e264446f6cabff06be72912eae902662dcb699" +source = "git+https://github.com/paritytech/polkadot-sdk#924728cf19523f826a08e1c0eeee711ca3bb8ee7" [[package]] name = "sp-storage" @@ -15482,7 +15482,7 @@ dependencies = [ [[package]] name = "sp-storage" version = "19.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#63e264446f6cabff06be72912eae902662dcb699" +source = "git+https://github.com/paritytech/polkadot-sdk#924728cf19523f826a08e1c0eeee711ca3bb8ee7" dependencies = [ "impl-serde", "parity-scale-codec", @@ -15532,7 +15532,7 @@ dependencies = [ [[package]] name = "sp-tracing" version = "16.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#63e264446f6cabff06be72912eae902662dcb699" +source = "git+https://github.com/paritytech/polkadot-sdk#924728cf19523f826a08e1c0eeee711ca3bb8ee7" dependencies = [ "parity-scale-codec", "tracing", @@ -15647,7 +15647,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" version = "20.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#63e264446f6cabff06be72912eae902662dcb699" +source = "git+https://github.com/paritytech/polkadot-sdk#924728cf19523f826a08e1c0eeee711ca3bb8ee7" dependencies = [ "impl-trait-for-tuples", "log", @@ -17906,20 +17906,12 @@ dependencies = [ ] [[package]] -name = "wapod-crypto-types" +name = "wapod-types" version = "0.1.0" dependencies = [ "parity-scale-codec", "scale-info", -] - -[[package]] -name = "wapod-eco-types" -version = "0.1.0" -dependencies = [ - "parity-scale-codec", - "scale-info", - "wapod-crypto-types", + "serde", ] [[package]] diff --git a/pallets/phala/Cargo.toml b/pallets/phala/Cargo.toml index d41617ff4..2d3cd19f3 100644 --- a/pallets/phala/Cargo.toml +++ b/pallets/phala/Cargo.toml @@ -46,8 +46,8 @@ fixed-sqrt = { version = "0.2", default-features = false } sgx-attestation = { path = "../../crates/sgx-attestation", default-features = false, features = ["verify"] } -[dependencies.wapod-eco-types] -path = "../../../wapo/wapod-eco-types/" +[dependencies.wapod-types] +path = "../../../wapo/wapod-types/" default-features = false [dev-dependencies] @@ -85,7 +85,7 @@ std = [ "serde/derive", "serde/alloc", "sgx-attestation/std", - "wapod-eco-types/std", + "wapod-types/std", ] runtime-benchmarks = [ ] From 40b74626b16cd640af50fd73018656fe28a1a007 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Mon, 8 Jul 2024 12:45:19 +0000 Subject: [PATCH 11/25] pallet: Add event HeartbeatChallenge --- pallets/phala/src/compute/computation.rs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/pallets/phala/src/compute/computation.rs b/pallets/phala/src/compute/computation.rs index f7b1758f4..72acd4e4f 100644 --- a/pallets/phala/src/compute/computation.rs +++ b/pallets/phala/src/compute/computation.rs @@ -436,9 +436,15 @@ pub mod pallet { nonce: u64, budget: u128, }, + /// A signal is sent to enable/disable static V in GK. StaticVChanged { enabled: bool, }, + /// A heartbeat challenge is sent to workers. + HeartbeatChallenge { + seed: U256, + online_target: U256, + }, } #[pallet::error] @@ -534,6 +540,10 @@ pub mod pallet { seed: U256::zero(), online_target: U256::MAX, })); + Self::deposit_event(Event::::HeartbeatChallenge { + seed: U256::zero(), + online_target: U256::MAX, + }); Ok(()) } @@ -688,6 +698,10 @@ pub mod pallet { online_target, }; Self::push_message(SystemEvent::HeartbeatChallenge(seed_info)); + Self::deposit_event(Event::::HeartbeatChallenge { + seed, + online_target, + }); } pub fn on_working_message_received( @@ -733,7 +747,11 @@ pub mod pallet { }); Sessions::::insert(&session, session_info); } - WorkingReportEvent::HeartbeatV3 { p_instant, iterations, .. } => { + WorkingReportEvent::HeartbeatV3 { + p_instant, + iterations, + .. + } => { let session = Self::ensure_worker_bound(&worker)?; let mut session_info = Self::sessions(&session).expect("Bound worker; qed."); From 8dc88b8617b9e13f13d7baabccc9552af02079c1 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Mon, 8 Jul 2024 12:45:37 +0000 Subject: [PATCH 12/25] Minor renaming --- pallets/phala/src/wapod_workers.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/pallets/phala/src/wapod_workers.rs b/pallets/phala/src/wapod_workers.rs index 4ec066522..c678171dc 100644 --- a/pallets/phala/src/wapod_workers.rs +++ b/pallets/phala/src/wapod_workers.rs @@ -19,10 +19,11 @@ pub mod pallet { }; use scale_info::TypeInfo; use sp_runtime::{traits::Zero, SaturatedConversion}; - use wapod_eco_types::{ + use wapod_types::{ bench_app::{MetricsToken, SignedMessage, SigningMessage}, crypto::CryptoProvider, primitives::{BoundedString, BoundedVec}, + session::{SessionUpdate, SignedSessionUpdate}, ticket::{Prices, SignedWorkerDescription, WorkerDescription}, }; @@ -97,7 +98,7 @@ pub mod pallet { pub workers: WorkerSet, pub address: [u8; 32], pub prices: Prices, - pub content_cid: BoundedString<128>, + pub manifest_cid: BoundedString<128>, } #[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] @@ -245,7 +246,7 @@ pub mod pallet { origin: OriginFor, deposit: BalanceOf, address: Address, - content_cid: BoundedString<128>, + manifest_cid: BoundedString<128>, worker_list: ListId, prices: Prices, ) -> DispatchResult { @@ -259,7 +260,7 @@ pub mod pallet { owner: owner.clone().into(), workers: WorkerSet::WorkerList(worker_list), address, - content_cid, + manifest_cid, prices, }); let ticket_account = ticket_account_address(id).into(); @@ -273,7 +274,7 @@ pub mod pallet { pub fn create_system_ticket( origin: OriginFor, address: Address, - content_cid: BoundedString<128>, + manifest_cid: BoundedString<128>, ) -> DispatchResult { T::GovernanceOrigin::ensure_origin(origin)?; Self::add_ticket(TicketInfo { @@ -281,7 +282,7 @@ pub mod pallet { owner: [0u8; 32].into(), workers: WorkerSet::Any, address, - content_cid, + manifest_cid, prices: Default::default(), }); Ok(()) From 4e65dcff59b66e9cdf82f993945f682614cbb838 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Mon, 8 Jul 2024 12:45:52 +0000 Subject: [PATCH 13/25] Add update_session --- pallets/phala/src/wapod_workers.rs | 40 ++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/pallets/phala/src/wapod_workers.rs b/pallets/phala/src/wapod_workers.rs index c678171dc..c99089781 100644 --- a/pallets/phala/src/wapod_workers.rs +++ b/pallets/phala/src/wapod_workers.rs @@ -507,6 +507,46 @@ pub mod pallet { Self::deposit_event(Event::RecommendedBenchmarkAppChanged { address }); Ok(()) } + + /// + #[pallet::call_index(10)] + #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] + pub fn update_session( + origin: OriginFor, + worker: Address, + update: SessionUpdate, + signature: BoundedVec, + ) -> DispatchResult { + let _ = ensure_signed(origin)?; + let worker_pubkey = WorkerPublicKey(worker); + + let signed_update = SignedSessionUpdate { + update: update.clone(), + signature: signature.into(), + }; + ensure!( + signed_update.verify::(&worker_pubkey), + Error::::SignatureVerificationFailed + ); + ensure!( + registry::Pallet::::worker_exsists(&worker_pubkey), + Error::::InvalidWorkerPubkey + ); + if let Some(session) = WorkerSessions::::get(&worker_pubkey) { + let computed_update = + SessionUpdate::from_seed::(update.seed, &session.last_nonce); + ensure!(computed_update == update, Error::::OutdatedMessage); + }; + WorkerSessions::::insert( + worker_pubkey, + WorkerSession { + session_id: update.session, + last_nonce: update.seed, + last_metrics_sn: 0, + }, + ); + return Ok(()); + } } impl Pallet From a71ea32444a8741d3ca4ad3ca3a9a980eb710164 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Tue, 9 Jul 2024 08:10:28 +0000 Subject: [PATCH 14/25] Add WapodWorkersApi --- Cargo.lock | 38 +++++++++++++++++++++++------- pallets/phala/Cargo.toml | 2 ++ pallets/phala/src/wapod_workers.rs | 20 ++++++++++++++++ standalone/runtime/src/lib.rs | 6 +++++ 4 files changed, 58 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d7458a0e6..2276f4000 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -379,14 +379,15 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.3" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", "getrandom 0.2.12", "once_cell", "version_check", + "zerocopy", ] [[package]] @@ -5431,7 +5432,7 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "ahash 0.8.3", + "ahash 0.8.11", ] [[package]] @@ -5440,7 +5441,7 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" dependencies = [ - "ahash 0.8.3", + "ahash 0.8.11", "allocator-api2", ] @@ -10166,6 +10167,7 @@ dependencies = [ "serde", "serde_json", "sgx-attestation", + "sp-api", "sp-core 21.0.0", "sp-io", "sp-runtime", @@ -12907,7 +12909,7 @@ name = "sc-consensus-grandpa" version = "0.10.0-dev" source = "git+https://github.com/Phala-Network/polkadot-sdk.git?branch=phala-patch-polkadot-v1.5.0#559a9126a2aa1de47356fea36aa246eb3e27e38a" dependencies = [ - "ahash 0.8.3", + "ahash 0.8.11", "array-bytes 6.2.3", "async-trait", "dyn-clone", @@ -13184,7 +13186,7 @@ name = "sc-network-gossip" version = "0.10.0-dev" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#789ffb66dcfcf3b54a1e6786e928ac91c4fdb465" dependencies = [ - "ahash 0.8.3", + "ahash 0.8.11", "futures", "futures-timer", "libp2p", @@ -13872,7 +13874,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "772575a524feeb803e5b0fcbc6dd9f367e579488197c94c6e4023aad2305774d" dependencies = [ - "ahash 0.8.3", + "ahash 0.8.11", "cfg-if", "hashbrown 0.13.2", ] @@ -15569,7 +15571,7 @@ name = "sp-trie" version = "22.0.0" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#8a98fec3e456033fdedf284e3613d5300f817085" dependencies = [ - "ahash 0.8.3", + "ahash 0.8.11", "hash-db", "hashbrown 0.13.2", "lazy_static", @@ -19516,6 +19518,26 @@ dependencies = [ "time 0.3.11", ] +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + [[package]] name = "zeroize" version = "1.6.0" diff --git a/pallets/phala/Cargo.toml b/pallets/phala/Cargo.toml index 2d3cd19f3..53d3ac08d 100644 --- a/pallets/phala/Cargo.toml +++ b/pallets/phala/Cargo.toml @@ -30,6 +30,7 @@ sp-runtime = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = sp-std = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "release-polkadot-v1.5.0", default-features = false } sp-io = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "release-polkadot-v1.5.0", default-features = false } sp-core = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "release-polkadot-v1.5.0", default-features = false } +sp-api = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "release-polkadot-v1.5.0", default-features = false } log = { version = "0.4.14", default-features = false } pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "release-polkadot-v1.5.0", default-features = false } @@ -72,6 +73,7 @@ std = [ "sp-io/std", "sp-std/std", "sp-core/std", + "sp-api/std", "frame-support/std", "frame-system/std", "pallet-balances/std", diff --git a/pallets/phala/src/wapod_workers.rs b/pallets/phala/src/wapod_workers.rs index c99089781..e63e1c0c4 100644 --- a/pallets/phala/src/wapod_workers.rs +++ b/pallets/phala/src/wapod_workers.rs @@ -639,4 +639,24 @@ pub mod pallet { Ok(()) } } + + // For runtime api + impl Pallet + where + T: mq::Config, + T::AccountId: Into + From, + { + pub fn balance_of_ticket(ticket_id: TicketId) -> BalanceOf { + let account = ticket_account_address(ticket_id).into(); + ::Currency::free_balance(&account) + } + } +} + +sp_api::decl_runtime_apis! { + /// The API of the wapod workers pallet. + pub trait WapodWorkersApi where Balance: codec::Codec { + /// Get balance of given ticket. + fn balance_of_ticket(ticket_id: TicketId) -> Balance; + } } diff --git a/standalone/runtime/src/lib.rs b/standalone/runtime/src/lib.rs index 2aa8dc102..119e4d243 100644 --- a/standalone/runtime/src/lib.rs +++ b/standalone/runtime/src/lib.rs @@ -1925,6 +1925,12 @@ impl_runtime_apis! { } } + impl pallet_wapod_workers::WapodWorkersApi for Runtime { + fn balance_of_ticket(ticket_id: pallet_wapod_workers::TicketId) -> Balance { + PhalaWapodWorkers::balance_of_ticket(ticket_id) + } + } + impl sp_session::SessionKeys for Runtime { fn generate_session_keys(seed: Option>) -> Vec { SessionKeys::generate(seed) From a12397d897b12820efd5d006fe7eeefeef891579 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Thu, 11 Jul 2024 23:41:04 +0800 Subject: [PATCH 15/25] pallet wapod: Implement settlement --- pallets/phala/src/compute/stake_pool_v2.rs | 3 +- pallets/phala/src/wapod_workers.rs | 301 +++++++++++++++++---- 2 files changed, 246 insertions(+), 58 deletions(-) diff --git a/pallets/phala/src/compute/stake_pool_v2.rs b/pallets/phala/src/compute/stake_pool_v2.rs index f0e4fbbae..32c580c51 100644 --- a/pallets/phala/src/compute/stake_pool_v2.rs +++ b/pallets/phala/src/compute/stake_pool_v2.rs @@ -422,8 +422,7 @@ pub mod pallet { let session: T::AccountId = pool_sub_account(pid, &pubkey); // bind worker with worker - computation::pallet::Pallet::::bind(session.clone(), pubkey) - .or(Err(Error::::FailedToBindSessionAndWorker))?; + computation::pallet::Pallet::::bind(session.clone(), pubkey)?; // Save the preimage of the sub-account, // the lifecycle of the preimage should be the same with the worker record, diff --git a/pallets/phala/src/wapod_workers.rs b/pallets/phala/src/wapod_workers.rs index e63e1c0c4..f15dff955 100644 --- a/pallets/phala/src/wapod_workers.rs +++ b/pallets/phala/src/wapod_workers.rs @@ -5,6 +5,7 @@ pub use self::pallet::*; #[frame_support::pallet] pub mod pallet { use crate::{mq, registry}; + use alloc::collections::BTreeMap; use alloc::vec::Vec; use frame_support::{ dispatch::DispatchResult, @@ -20,8 +21,9 @@ pub mod pallet { use scale_info::TypeInfo; use sp_runtime::{traits::Zero, SaturatedConversion}; use wapod_types::{ - bench_app::{MetricsToken, SignedMessage, SigningMessage}, + bench_app::{BenchScore, SignedMessage, SigningMessage}, crypto::CryptoProvider, + metrics::{MetricsToken, SignedAppsMetrics, VersionedAppsMetrics}, primitives::{BoundedString, BoundedVec}, session::{SessionUpdate, SignedSessionUpdate}, ticket::{Prices, SignedWorkerDescription, WorkerDescription}, @@ -33,6 +35,8 @@ pub mod pallet { pub type TicketId = u64; pub type ListId = u64; pub type Address = [u8; 32]; + pub type Balance = u128; + type AcountId32 = [u8; 32]; #[derive(Encode, Decode, TypeInfo, Debug, Clone, Copy, PartialEq, Eq, MaxEncodedLen)] pub struct Fraction { @@ -52,7 +56,6 @@ pub mod pallet { #[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] pub struct BenchAppInfo { - version: u32, ticket: TicketId, score_ratio: Fraction, } @@ -62,6 +65,7 @@ pub mod pallet { pub session_id: [u8; 32], pub last_nonce: [u8; 32], pub last_metrics_sn: u64, + pub reward_receiver: AcountId32, } struct SpCrypto; @@ -89,8 +93,6 @@ pub mod pallet { WorkerList(ListId), } - type AcountId32 = [u8; 32]; - #[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] pub struct TicketInfo { pub system: bool, @@ -108,6 +110,13 @@ pub mod pallet { pub description: BoundedString<1024>, } + #[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq, MaxEncodedLen, Default)] + pub struct SettlementInfo { + pub current_session_id: [u8; 32], + pub current_session_paid: Balance, + pub hist_paid: Balance, + } + #[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] pub struct WorkingState { session_id: u32, @@ -136,6 +145,18 @@ pub mod pallet { #[pallet::storage] pub type Tickets = StorageMap<_, Twox64Concat, TicketId, TicketInfo>; + /// Settlement information for each ticket. + #[pallet::storage] + pub type TicketSettlementInfo = StorageDoubleMap< + _, + Twox64Concat, + TicketId, + Twox64Concat, + WorkerPublicKey, + SettlementInfo, + ValueQuery, + >; + #[pallet::storage] pub type NextWorkerListId = StorageValue<_, ListId, ValueQuery>; @@ -216,6 +237,23 @@ pub mod pallet { RecommendedBenchmarkAppChanged { address: Address, }, + Settled { + ticket_id: TicketId, + worker: WorkerPublicKey, + paid: Balance, + session_cost: Balance, + paid_to: T::AccountId, + }, + SettleFailed { + ticket_id: TicketId, + worker: WorkerPublicKey, + paid: Balance, + session_cost: Balance, + }, + WorkerSessionUpdated { + worker: WorkerPublicKey, + session: [u8; 32], + }, } const TICKET_ADDRESS_PREFIX: &[u8] = b"wapod/ticket/"; @@ -238,8 +276,15 @@ pub mod pallet { T: mq::Config, T: registry::Config, T::AccountId: Into + From, + BalanceOf: From, { /// Create a new ticket + /// + /// deposit: the deposit to be paid to the ticket account + /// address: the address of the target app. It must match the address of the manifest, otherwise the ticket will be rejected by workers. + /// manifest_cid: the IPFS CID of the manifest of the target app + /// worker_list: the worker list that the ticket is allowed to be settled by. + /// prices: the resource prices of the ticket. If is recommended to use the prices of the worker list or else the ticket may be rejected by workers. #[pallet::call_index(0)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] pub fn create_ticket( @@ -251,44 +296,25 @@ pub mod pallet { prices: Prices, ) -> DispatchResult { let owner = ensure_signed(origin)?; - ensure!( - WorkerLists::::contains_key(worker_list), - Error::::WorkerListNotFound - ); + let Some(list_info) = WorkerLists::::get(worker_list) else { + return Err(Error::::WorkerListNotFound.into()); + }; let id = Self::add_ticket(TicketInfo { system: false, owner: owner.clone().into(), workers: WorkerSet::WorkerList(worker_list), address, manifest_cid, - prices, + prices: prices.merge(&list_info.prices), }); let ticket_account = ticket_account_address(id).into(); ::Currency::transfer(&owner, &ticket_account, deposit, KeepAlive)?; Ok(()) } - /// Create a new ticket - #[pallet::call_index(1)] - #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] - pub fn create_system_ticket( - origin: OriginFor, - address: Address, - manifest_cid: BoundedString<128>, - ) -> DispatchResult { - T::GovernanceOrigin::ensure_origin(origin)?; - Self::add_ticket(TicketInfo { - system: true, - owner: [0u8; 32].into(), - workers: WorkerSet::Any, - address, - manifest_cid, - prices: Default::default(), - }); - Ok(()) - } - /// Close a ticket + /// + /// The state of the ticket will be removed and the deposit will be refunded to the owner. #[pallet::call_index(2)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] pub fn close_ticket(origin: OriginFor, ticket_id: TicketId) -> DispatchResult { @@ -307,8 +333,138 @@ pub mod pallet { Ok(()) } + /// Submit app metrics + /// + /// message: a worker signed message that contains the metrics of apps. + /// The message will be verified and the metrics will be used to settle the corresponding tickets. #[pallet::call_index(3)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] + pub fn submit_app_metrics( + origin: OriginFor, + message: SignedAppsMetrics, + ) -> DispatchResult { + let _ = ensure_signed(origin)?; + let worker_pubkey = { + // signature verification + ensure!( + message.verify::(), + Error::::SignatureVerificationFailed + ); + let worker_pubkey = WorkerPublicKey(message.worker_pubkey); + ensure!( + registry::Pallet::::worker_exsists(&worker_pubkey), + Error::::InvalidWorkerPubkey + ); + worker_pubkey + }; + + let VersionedAppsMetrics::V0(all_metrics) = message.metrics; + + let worker_session = { + // ensure the session matches + let MetricsToken { session, sn, nonce } = all_metrics.token; + let Some(mut session_info) = WorkerSessions::::get(&worker_pubkey) else { + return Err(Error::::WorkerNotFound.into()); + }; + ensure!( + session_info.session_id == session, + Error::::SessionMismatch + ); + ensure!( + session_info.last_metrics_sn < sn, + Error::::OutdatedMessage + ); + session_info.last_nonce = nonce; + session_info.last_metrics_sn = sn; + WorkerSessions::::insert(&worker_pubkey, &session_info); + session_info + }; + + { + // update metrics for each ticket + + // Max of 64 entries + let claim_map: BTreeMap<_, _> = message.claim_map.into_iter().collect(); + + // Max of 64 entries + for m in all_metrics.apps { + let ticket_ids = claim_map.get(&m.address).ok_or(Error::::NotAllowed)?; + // Max of 3 entries + for ticket_id in ticket_ids.iter() { + let ticket = + Tickets::::get(ticket_id).ok_or(Error::::TicketNotFound)?; + + ensure!(ticket.address == m.address, Error::::NotAllowed); + match ticket.workers { + WorkerSet::Any => (), + WorkerSet::WorkerList(list_id) => { + ensure!( + WorkerListWorkers::::contains_key(list_id, &worker_pubkey), + Error::::NotAllowed + ); + } + } + + let mut settlement = + TicketSettlementInfo::::get(ticket_id, &worker_pubkey); + + // Pay out and update the settlement infomation + let cost = ticket.prices.cost_of(&m); + let pay_out; + if settlement.current_session_id != m.session { + settlement.hist_paid += settlement.current_session_paid; + settlement.current_session_paid = cost; + settlement.current_session_id = m.session; + pay_out = 0_u128; + } else { + pay_out = cost.saturating_sub(settlement.current_session_paid); + }; + if pay_out > 0 { + let ticket_account = ticket_account_address(*ticket_id).into(); + let reward_account = worker_session.reward_receiver.into(); + let transfer_result = ::Currency::transfer( + &ticket_account, + &reward_account, + pay_out.into(), + KeepAlive, + ); + match transfer_result { + Ok(_) => { + settlement.current_session_paid = cost; + Self::deposit_event(Event::Settled { + ticket_id: *ticket_id, + worker: worker_pubkey, + paid: pay_out.into(), + session_cost: cost.into(), + paid_to: reward_account, + }); + } + Err(_) => { + Self::deposit_event(Event::SettleFailed { + ticket_id: *ticket_id, + worker: worker_pubkey, + paid: pay_out.into(), + session_cost: cost.into(), + }); + } + } + } + TicketSettlementInfo::::insert(ticket_id, &worker_pubkey, settlement); + } + } + } + let todo = "reorder the pallet calls"; + Ok(()) + } + + /// Submit benchmark score + /// + /// This call is used to submit the benchmark app score of a worker. The score is used to simulate pruntime v2 worker heartbeat. + /// The init_score of the worker will also be updated according to the score. + /// + /// message: a worker signed message that contains the benchmark score. + #[pallet::call_index(4)] + #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] pub fn submit_bench_message( origin: OriginFor, message: SignedMessage, @@ -326,19 +482,19 @@ pub mod pallet { let bench_app_info = BenchmarkApps::::get(&message.app_address).ok_or(Error::::InvalidBenchApp)?; match message.message { - SigningMessage::BenchScore { + SigningMessage::BenchScore(BenchScore { gas_per_second, gas_consumed, timestamp_secs, - matrics_token, - } => { + metrics_token, + }) => { use frame_support::traits::UnixTime; let now = T::UnixTime::now().as_secs() as i64; let diff = (now - timestamp_secs as i64).abs(); ensure!(diff < 600, Error::::OutdatedMessage); - Self::update_metrics_token(&worker_pubkey, &matrics_token)?; + Self::update_metrics_token(&worker_pubkey, &metrics_token)?; // Update the worker init score let gas_6secs = gas_per_second.saturating_mul(6); @@ -376,7 +532,7 @@ pub mod pallet { } /// Create a new worker list - #[pallet::call_index(4)] + #[pallet::call_index(5)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] pub fn create_worker_list( origin: OriginFor, @@ -397,7 +553,7 @@ pub mod pallet { } /// Add a worker to a worker list - #[pallet::call_index(5)] + #[pallet::call_index(6)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] pub fn add_workers_to_list( origin: OriginFor, @@ -426,7 +582,7 @@ pub mod pallet { } /// Remove a worker from a worker list - #[pallet::call_index(6)] + #[pallet::call_index(7)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] pub fn remove_worker_from_list( origin: OriginFor, @@ -442,7 +598,7 @@ pub mod pallet { } /// Set worker description - #[pallet::call_index(7)] + #[pallet::call_index(8)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] pub fn set_worker_description( origin: OriginFor, @@ -471,22 +627,30 @@ pub mod pallet { } /// Add a benchmark app (governance only) - #[pallet::call_index(8)] + /// + /// address: the address of the benchmark app + /// manifest_cid: the IPFS CID of the manifest of the benchmark app + /// score_ratio: the ratio of mapping gas to score + #[pallet::call_index(9)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] pub fn add_benchmark_app( origin: OriginFor, - ticket: TicketId, - version: u32, + address: Address, + manifest_cid: BoundedString<128>, score_ratio: Fraction, ) -> DispatchResult { T::GovernanceOrigin::ensure_origin(origin)?; - let address = Tickets::::get(ticket) - .ok_or(Error::::TicketNotFound)? - .address; + let ticket = Self::add_ticket(TicketInfo { + system: true, + owner: [0u8; 32].into(), + workers: WorkerSet::Any, + address, + manifest_cid, + prices: Default::default(), + }); BenchmarkApps::::insert( address, BenchAppInfo { - version, ticket, score_ratio, }, @@ -496,7 +660,9 @@ pub mod pallet { } /// Set recommended benchmark app (governance only) - #[pallet::call_index(9)] + /// + /// address: the address of the recommended benchmark app + #[pallet::call_index(10)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] pub fn set_recommended_benchmark_app( origin: OriginFor, @@ -508,8 +674,23 @@ pub mod pallet { Ok(()) } + /// Combine add_benchmark_app and set_recommended_benchmark_app + #[pallet::call_index(11)] + #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] + pub fn set_benchmark_app( + origin: OriginFor, + address: Address, + manifest_cid: BoundedString<128>, + score_ratio: Fraction, + ) -> DispatchResult { + Self::add_benchmark_app(origin.clone(), address, manifest_cid, score_ratio)?; + Self::set_recommended_benchmark_app(origin, address) + } + + /// Update worker session /// - #[pallet::call_index(10)] + /// When a worker restarts or resets, it should update the session with the new session id. + #[pallet::call_index(12)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] pub fn update_session( origin: OriginFor, @@ -533,9 +714,12 @@ pub mod pallet { Error::::InvalidWorkerPubkey ); if let Some(session) = WorkerSessions::::get(&worker_pubkey) { - let computed_update = - SessionUpdate::from_seed::(update.seed, &session.last_nonce); - ensure!(computed_update == update, Error::::OutdatedMessage); + let computed_session = + SessionUpdate::session_from_seed::(update.seed, &session.last_nonce); + ensure!( + computed_session == update.session, + Error::::OutdatedMessage + ); }; WorkerSessions::::insert( worker_pubkey, @@ -543,8 +727,13 @@ pub mod pallet { session_id: update.session, last_nonce: update.seed, last_metrics_sn: 0, + reward_receiver: update.reward_receiver, }, ); + Self::deposit_event(Event::WorkerSessionUpdated { + worker: worker_pubkey, + session: update.session, + }); return Ok(()); } } @@ -578,21 +767,21 @@ pub mod pallet { fn update_metrics_token( worker_pubkey: &WorkerPublicKey, - matrics_token: &MetricsToken, + metrics_token: &MetricsToken, ) -> DispatchResult { let Some(mut worker_session) = WorkerSessions::::get(worker_pubkey) else { return Err(Error::::WorkerNotFound.into()); }; ensure!( - worker_session.last_metrics_sn < matrics_token.metrics_sn, - Error::::SessionMismatch + worker_session.last_metrics_sn < metrics_token.sn, + Error::::OutdatedMessage ); ensure!( - worker_session.session_id == matrics_token.worker_session, - Error::::OutdatedMessage + worker_session.session_id == metrics_token.session, + Error::::SessionMismatch ); - worker_session.last_metrics_sn = matrics_token.metrics_sn; - worker_session.last_nonce = matrics_token.nonce; + worker_session.last_metrics_sn = metrics_token.sn; + worker_session.last_nonce = metrics_token.nonce; WorkerSessions::::insert(worker_pubkey, worker_session); Ok(()) } From 80d03ae0a40725bf861dda4210612d832351c6f9 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Fri, 12 Jul 2024 10:17:34 +0800 Subject: [PATCH 16/25] pallet wapod: introduce total_paid instead of hist_paid --- pallets/phala/src/wapod_workers.rs | 44 +++++++++++++++++------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/pallets/phala/src/wapod_workers.rs b/pallets/phala/src/wapod_workers.rs index f15dff955..de033e1d2 100644 --- a/pallets/phala/src/wapod_workers.rs +++ b/pallets/phala/src/wapod_workers.rs @@ -114,7 +114,7 @@ pub mod pallet { pub struct SettlementInfo { pub current_session_id: [u8; 32], pub current_session_paid: Balance, - pub hist_paid: Balance, + pub total_paid: Balance, } #[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] @@ -145,7 +145,7 @@ pub mod pallet { #[pallet::storage] pub type Tickets = StorageMap<_, Twox64Concat, TicketId, TicketInfo>; - /// Settlement information for each ticket. + /// Settlement information for each (ticket, worker) pair. #[pallet::storage] pub type TicketSettlementInfo = StorageDoubleMap< _, @@ -329,6 +329,8 @@ pub mod pallet { ::Currency::transfer(&ticket_account, &owner, deposit, AllowDeath)?; } Tickets::::remove(ticket_id); + // TODO: remove the remaining entries + _ = TicketSettlementInfo::::clear_prefix(ticket_id, 64, None); Self::deposit_event(Event::TicketClosed { id: ticket_id }); Ok(()) } @@ -360,7 +362,7 @@ pub mod pallet { let VersionedAppsMetrics::V0(all_metrics) = message.metrics; - let worker_session = { + let worker_info = { // ensure the session matches let MetricsToken { session, sn, nonce } = all_metrics.token; let Some(mut session_info) = WorkerSessions::::get(&worker_pubkey) else { @@ -383,18 +385,24 @@ pub mod pallet { { // update metrics for each ticket - // Max of 64 entries + // Up to 64 entries let claim_map: BTreeMap<_, _> = message.claim_map.into_iter().collect(); - // Max of 64 entries - for m in all_metrics.apps { - let ticket_ids = claim_map.get(&m.address).ok_or(Error::::NotAllowed)?; - // Max of 3 entries + // Up to 64 entries + for metrics in all_metrics.apps { + let ticket_ids = claim_map + .get(&metrics.address) + .ok_or(Error::::NotAllowed)?; + // Up to 5 entries for ticket_id in ticket_ids.iter() { let ticket = Tickets::::get(ticket_id).ok_or(Error::::TicketNotFound)?; - ensure!(ticket.address == m.address, Error::::NotAllowed); + if ticket.prices.is_empty() { + continue; + } + + ensure!(ticket.address == metrics.address, Error::::NotAllowed); match ticket.workers { WorkerSet::Any => (), WorkerSet::WorkerList(list_id) => { @@ -409,19 +417,15 @@ pub mod pallet { TicketSettlementInfo::::get(ticket_id, &worker_pubkey); // Pay out and update the settlement infomation - let cost = ticket.prices.cost_of(&m); - let pay_out; - if settlement.current_session_id != m.session { - settlement.hist_paid += settlement.current_session_paid; + let cost = ticket.prices.cost_of(&metrics); + if settlement.current_session_id != metrics.session { + settlement.current_session_id = metrics.session; settlement.current_session_paid = cost; - settlement.current_session_id = m.session; - pay_out = 0_u128; - } else { - pay_out = cost.saturating_sub(settlement.current_session_paid); - }; + } + let pay_out = cost.saturating_sub(settlement.current_session_paid); if pay_out > 0 { let ticket_account = ticket_account_address(*ticket_id).into(); - let reward_account = worker_session.reward_receiver.into(); + let reward_account = worker_info.reward_receiver.into(); let transfer_result = ::Currency::transfer( &ticket_account, &reward_account, @@ -431,6 +435,8 @@ pub mod pallet { match transfer_result { Ok(_) => { settlement.current_session_paid = cost; + settlement.total_paid = + settlement.total_paid.saturating_add(pay_out); Self::deposit_event(Event::Settled { ticket_id: *ticket_id, worker: worker_pubkey, From fc99d0f92f21a46fda118e6efa4182e07471034b Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Tue, 16 Jul 2024 00:14:47 +0800 Subject: [PATCH 17/25] pallet-wapod: use generic types and reorder pallet calls --- pallets/phala/src/mock.rs | 7 +- pallets/phala/src/registry.rs | 11 +- pallets/phala/src/wapod_workers.rs | 489 +++++++++++++++-------------- standalone/runtime/src/lib.rs | 1 - 4 files changed, 270 insertions(+), 238 deletions(-) diff --git a/pallets/phala/src/mock.rs b/pallets/phala/src/mock.rs index 1df247822..b4f192b2d 100644 --- a/pallets/phala/src/mock.rs +++ b/pallets/phala/src/mock.rs @@ -3,7 +3,7 @@ use crate::{ utils::attestation_legacy::{ Attestation, AttestationValidator, Error as AttestationError, IasFields, }, - vault, wrapped_balances, + vault, wapod_workers, wrapped_balances, }; use frame_support::{ @@ -46,6 +46,7 @@ frame_support::construct_runtime!( PhalaWrappedBalances: wrapped_balances::{Pallet, Event}, PhalaBasePool: base_pool::{Pallet, Event}, PhalaStakePool: stake_pool::{Event}, + PhalaWapodWorkers: wapod_workers::{Pallet, Call, Storage, Event}, Preimage: pallet_preimage::{Event}, } ); @@ -394,6 +395,10 @@ impl stake_pool::Config for Test { type Currency = Balances; } +impl wapod_workers::Config for Test { + type RuntimeEvent = RuntimeEvent; +} + pub struct MockValidator; impl AttestationValidator for MockValidator { fn validate( diff --git a/pallets/phala/src/registry.rs b/pallets/phala/src/registry.rs index 8df400a52..f818f9456 100644 --- a/pallets/phala/src/registry.rs +++ b/pallets/phala/src/registry.rs @@ -934,7 +934,7 @@ pub mod pallet { Workers::::contains_key(worker_pubkey) } - pub fn update_worker_score(worker_pubkey: &WorkerPublicKey, score: u64) -> u64 { + pub fn update_worker_init_score(worker_pubkey: &WorkerPublicKey, score: u64) { let now = T::UnixTime::now().as_millis().saturated_into::(); const MAX_SCORE: u32 = 6000; @@ -954,7 +954,12 @@ pub mod pallet { pubkey: *worker_pubkey, init_score: score, }); - score as u64 + } + + pub fn worker_init_score(worker_pubkey: &WorkerPublicKey) -> Option { + Workers::::get(worker_pubkey)? + .initial_score + .map(|s| s as u64) } pub fn on_message_received(message: DecodedMessage) -> DispatchResult { @@ -976,7 +981,7 @@ pub mod pallet { let score = iterations / ((now - start_time) / 1000); let score = score * 6; // iterations per 6s - Self::update_worker_score(&worker_pubkey, score); + Self::update_worker_init_score(&worker_pubkey, score); } RegistryEvent::MasterPubkey { master_pubkey } => { let gatekeepers = Gatekeeper::::get(); diff --git a/pallets/phala/src/wapod_workers.rs b/pallets/phala/src/wapod_workers.rs index de033e1d2..b47859df6 100644 --- a/pallets/phala/src/wapod_workers.rs +++ b/pallets/phala/src/wapod_workers.rs @@ -4,7 +4,8 @@ pub use self::pallet::*; #[frame_support::pallet] pub mod pallet { - use crate::{mq, registry}; + // MARK: - Imports + use crate::{mq, registry, PhalaConfig}; use alloc::collections::BTreeMap; use alloc::vec::Vec; use frame_support::{ @@ -19,24 +20,23 @@ pub mod pallet { WorkerPublicKey, }; use scale_info::TypeInfo; - use sp_runtime::{traits::Zero, SaturatedConversion}; + use sp_runtime::{traits::Zero, SaturatedConversion, Saturating}; use wapod_types::{ bench_app::{BenchScore, SignedMessage, SigningMessage}, - crypto::CryptoProvider, + crypto::{verify::Verifiable, CryptoProvider}, metrics::{MetricsToken, SignedAppsMetrics, VersionedAppsMetrics}, primitives::{BoundedString, BoundedVec}, session::{SessionUpdate, SignedSessionUpdate}, - ticket::{Prices, SignedWorkerDescription, WorkerDescription}, + ticket::{Balance, Prices, SignedWorkerDescription, WorkerDescription}, }; + // MARK: - Types type BalanceOf = - <::Currency as Currency<::AccountId>>::Balance; + <::Currency as Currency<::AccountId>>::Balance; pub type TicketId = u64; pub type ListId = u64; pub type Address = [u8; 32]; - pub type Balance = u128; - type AcountId32 = [u8; 32]; #[derive(Encode, Decode, TypeInfo, Debug, Clone, Copy, PartialEq, Eq, MaxEncodedLen)] pub struct Fraction { @@ -61,11 +61,11 @@ pub mod pallet { } #[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] - pub struct WorkerSession { + pub struct WorkerSession { pub session_id: [u8; 32], pub last_nonce: [u8; 32], pub last_metrics_sn: u64, - pub reward_receiver: AcountId32, + pub reward_receiver: AccountId, } struct SpCrypto; @@ -94,24 +94,24 @@ pub mod pallet { } #[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] - pub struct TicketInfo { + pub struct TicketInfo { pub system: bool, - pub owner: AcountId32, + pub owner: Option, pub workers: WorkerSet, - pub address: [u8; 32], + pub address: Address, pub prices: Prices, pub manifest_cid: BoundedString<128>, } #[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] - pub struct WorkerListInfo { - pub owner: AcountId32, + pub struct WorkerListInfo { + pub owner: AccountId, pub prices: Prices, pub description: BoundedString<1024>, } #[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq, MaxEncodedLen, Default)] - pub struct SettlementInfo { + pub struct SettlementInfo { pub current_session_id: [u8; 32], pub current_session_paid: Balance, pub total_paid: Balance, @@ -125,12 +125,14 @@ pub mod pallet { last_update_time: i64, } + // MARK: - Pallet config #[pallet::config] - pub trait Config: frame_system::Config { + pub trait Config: frame_system::Config + PhalaConfig { type RuntimeEvent: From> + IsType<::RuntimeEvent>; - type Currency: Currency; } + // MARK: - Pallet storage + const STORAGE_VERSION: StorageVersion = StorageVersion::new(0); #[pallet::pallet] @@ -143,7 +145,7 @@ pub mod pallet { /// Active tickets. /// Each ticket holds a payment infomation to a target app address. Multiple ticket can pay for a same app at the sametime. #[pallet::storage] - pub type Tickets = StorageMap<_, Twox64Concat, TicketId, TicketInfo>; + pub type Tickets = StorageMap<_, Twox64Concat, TicketId, TicketInfo>; /// Settlement information for each (ticket, worker) pair. #[pallet::storage] @@ -153,18 +155,19 @@ pub mod pallet { TicketId, Twox64Concat, WorkerPublicKey, - SettlementInfo, + SettlementInfo>, ValueQuery, >; #[pallet::storage] - pub type NextWorkerListId = StorageValue<_, ListId, ValueQuery>; + pub type NextWorkerListId = StorageValue<_, ListId, ValueQuery>; /// Worker lists. /// /// A worker list is a collection of workers that with the same price. #[pallet::storage] - pub type WorkerLists = StorageMap<_, Twox64Concat, ListId, WorkerListInfo>; + pub type WorkerLists = + StorageMap<_, Twox64Concat, ListId, WorkerListInfo>; /// Concrete workers associated to worker list. #[pallet::storage] @@ -178,7 +181,8 @@ pub mod pallet { /// V3 information about workers. #[pallet::storage] - pub type WorkerSessions = StorageMap<_, Twox64Concat, WorkerPublicKey, WorkerSession>; + pub type WorkerSessions = + StorageMap<_, Twox64Concat, WorkerPublicKey, WorkerSession>; /// Working state of wapod workers. V2 compatible. #[pallet::storage] @@ -192,6 +196,7 @@ pub mod pallet { #[pallet::storage] pub type RecommendedBenchmarkApp = StorageValue<_, Address>; + // MARK: - Pallet error #[pallet::error] pub enum Error { UnsupportedManifestVersion, @@ -206,8 +211,11 @@ pub mod pallet { InvalidMessageSender, PriceMismatch, SessionMismatch, + InvalidRewardReceiver, + InvalidParameter, } + // MARK: - Pallet events #[pallet::event] #[pallet::generate_deposit(fn deposit_event)] pub enum Event { @@ -240,44 +248,189 @@ pub mod pallet { Settled { ticket_id: TicketId, worker: WorkerPublicKey, - paid: Balance, - session_cost: Balance, + paid: BalanceOf, + session_cost: BalanceOf, paid_to: T::AccountId, }, SettleFailed { ticket_id: TicketId, worker: WorkerPublicKey, - paid: Balance, - session_cost: Balance, + paid: BalanceOf, + session_cost: BalanceOf, }, WorkerSessionUpdated { worker: WorkerPublicKey, session: [u8; 32], }, + HeartbeatV3 { + worker: WorkerPublicKey, + session_id: u32, + iterations: u64, + p_instant: u32, + }, } - const TICKET_ADDRESS_PREFIX: &[u8] = b"wapod/ticket/"; - - fn ticket_account_address(ticket_id: TicketId) -> [u8; 32] { - let mut address = [0u8; 32]; - let prefix = TICKET_ADDRESS_PREFIX; - address[..prefix.len()].copy_from_slice(prefix); - { - let ticket_id_bytes = ticket_id.to_be_bytes(); - let offset = prefix.len(); - address[offset..offset + ticket_id_bytes.len()].copy_from_slice(&ticket_id_bytes); - } - address + pub fn ticket_account_address(ticket_id: TicketId) -> T + where + T: Encode + Decode, + { + wapod_types::ticket::ticket_account_address(ticket_id, crate::hashing::blake2_256) } + // MARK: - Pallet calls #[pallet::call] impl Pallet where T: mq::Config, T: registry::Config, - T::AccountId: Into + From, BalanceOf: From, { + // MARK: - Worker management + + /// Set worker description + #[pallet::call_index(0)] + #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] + pub fn worker_set_description( + origin: OriginFor, + signed_description: SignedWorkerDescription, + ) -> DispatchResult { + let _ = ensure_signed(origin)?; + let worker_pubkey = WorkerPublicKey(signed_description.worker_pubkey); + // Worker price can only be set once + ensure!( + !WorkerDescriptions::::contains_key(&worker_pubkey), + Error::::NotAllowed + ); + ensure!( + registry::Pallet::::worker_exsists(&worker_pubkey), + Error::::InvalidWorkerPubkey + ); + ensure!( + signed_description.verify::(), + Error::::SignatureVerificationFailed + ); + WorkerDescriptions::::insert(&worker_pubkey, signed_description.worker_description); + Self::deposit_event(Event::WorkerDescriptionSet { + worker: worker_pubkey, + }); + Ok(()) + } + + /// Update worker session + /// + /// When a worker restarts or resets, it should update the session with the new session id. + #[pallet::call_index(1)] + #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] + pub fn worker_update_session( + origin: OriginFor, + update: SignedSessionUpdate, + ) -> DispatchResult { + let _ = ensure_signed(origin)?; + ensure!( + update.verify::(), + Error::::SignatureVerificationFailed + ); + let worker_pubkey = WorkerPublicKey(update.public_key); + ensure!( + registry::Pallet::::worker_exsists(&worker_pubkey), + Error::::InvalidWorkerPubkey + ); + let update = update.update; + if let Some(session) = WorkerSessions::::get(&worker_pubkey) { + let computed_session = + SessionUpdate::session_from_seed::(update.seed, &session.last_nonce); + ensure!( + computed_session == update.session, + Error::::OutdatedMessage + ); + }; + let Ok(reward_receiver) = Decode::decode(&mut &update.reward_receiver[..]) else { + return Err(Error::::InvalidRewardReceiver.into()); + }; + WorkerSessions::::insert( + worker_pubkey, + WorkerSession { + session_id: update.session, + last_nonce: update.seed, + last_metrics_sn: 0, + reward_receiver, + }, + ); + Self::deposit_event(Event::WorkerSessionUpdated { + worker: worker_pubkey, + session: update.session, + }); + return Ok(()); + } + + /// Create a new worker list + #[pallet::call_index(2)] + #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] + pub fn worker_list_create( + origin: OriginFor, + description: BoundedString<1024>, + prices: Prices, + init_workers: BoundedVec, + ) -> DispatchResult { + let owner = ensure_signed(origin.clone())?; + let id = Self::add_worker_list(WorkerListInfo { + owner: owner.into(), + prices, + description, + }); + if init_workers.len() > 0 { + Self::worker_list_add_workers(origin, id, init_workers)?; + } + Ok(()) + } + + /// Add a worker to a worker list + #[pallet::call_index(3)] + #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] + pub fn worker_list_add_workers( + origin: OriginFor, + list_id: ListId, + workers: BoundedVec, + ) -> DispatchResult { + let owner = ensure_signed(origin)?; + let list_info = WorkerLists::::get(list_id).ok_or(Error::::WorkerListNotFound)?; + ensure!(owner == list_info.owner.into(), Error::::NotAllowed); + for worker in workers.iter() { + let Some(worker_info) = WorkerDescriptions::::get(worker) else { + return Err(Error::::WorkerNotFound.into()); + }; + ensure!( + worker_info.prices == Default::default() + || worker_info.prices == list_info.prices, + Error::::PriceMismatch + ); + WorkerListWorkers::::insert(list_id, worker, ()); + } + Self::deposit_event(Event::WorkersAddedToList { + list_id, + workers: workers.into(), + }); + Ok(()) + } + + /// Remove a worker from a worker list + #[pallet::call_index(4)] + #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] + pub fn worker_list_remove_worker( + origin: OriginFor, + list_id: ListId, + worker: WorkerPublicKey, + ) -> DispatchResult { + let owner = ensure_signed(origin)?; + let list_info = WorkerLists::::get(list_id).ok_or(Error::::WorkerListNotFound)?; + ensure!(owner == list_info.owner.into(), Error::::NotAllowed); + WorkerListWorkers::::remove(list_id, worker); + Self::deposit_event(Event::WorkerRemovedFromList { list_id, worker }); + Ok(()) + } + + // MARK: - Tickets + /// Create a new ticket /// /// deposit: the deposit to be paid to the ticket account @@ -285,9 +438,9 @@ pub mod pallet { /// manifest_cid: the IPFS CID of the manifest of the target app /// worker_list: the worker list that the ticket is allowed to be settled by. /// prices: the resource prices of the ticket. If is recommended to use the prices of the worker list or else the ticket may be rejected by workers. - #[pallet::call_index(0)] + #[pallet::call_index(5)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] - pub fn create_ticket( + pub fn ticket_create( origin: OriginFor, deposit: BalanceOf, address: Address, @@ -301,32 +454,37 @@ pub mod pallet { }; let id = Self::add_ticket(TicketInfo { system: false, - owner: owner.clone().into(), + owner: Some(owner.clone()), workers: WorkerSet::WorkerList(worker_list), address, manifest_cid, prices: prices.merge(&list_info.prices), }); - let ticket_account = ticket_account_address(id).into(); - ::Currency::transfer(&owner, &ticket_account, deposit, KeepAlive)?; + let ticket_account = ticket_account_address(id); + ::Currency::transfer(&owner, &ticket_account, deposit, KeepAlive)?; Ok(()) } /// Close a ticket /// /// The state of the ticket will be removed and the deposit will be refunded to the owner. - #[pallet::call_index(2)] + #[pallet::call_index(6)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] - pub fn close_ticket(origin: OriginFor, ticket_id: TicketId) -> DispatchResult { + pub fn ticket_close(origin: OriginFor, ticket_id: TicketId) -> DispatchResult { let owner = ensure_signed(origin)?; let info = Tickets::::get(ticket_id).ok_or(Error::::TicketNotFound)?; - ensure!(owner == info.owner.into(), Error::::NotAllowed); + ensure!(Some(&owner) == info.owner.as_ref(), Error::::NotAllowed); // Refund the deposit - let ticket_account = ticket_account_address(ticket_id).into(); - let deposit = ::Currency::free_balance(&ticket_account); + let ticket_account = ticket_account_address(ticket_id); + let deposit = ::Currency::free_balance(&ticket_account); if !deposit.is_zero() { - ::Currency::transfer(&ticket_account, &owner, deposit, AllowDeath)?; + ::Currency::transfer( + &ticket_account, + &owner, + deposit, + AllowDeath, + )?; } Tickets::::remove(ticket_id); // TODO: remove the remaining entries @@ -339,12 +497,9 @@ pub mod pallet { /// /// message: a worker signed message that contains the metrics of apps. /// The message will be verified and the metrics will be used to settle the corresponding tickets. - #[pallet::call_index(3)] + #[pallet::call_index(7)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] - pub fn submit_app_metrics( - origin: OriginFor, - message: SignedAppsMetrics, - ) -> DispatchResult { + pub fn ticket_settle(origin: OriginFor, message: SignedAppsMetrics) -> DispatchResult { let _ = ensure_signed(origin)?; let worker_pubkey = { // signature verification @@ -417,18 +572,17 @@ pub mod pallet { TicketSettlementInfo::::get(ticket_id, &worker_pubkey); // Pay out and update the settlement infomation - let cost = ticket.prices.cost_of(&metrics); + let cost = ticket.prices.cost_of(&metrics).into(); if settlement.current_session_id != metrics.session { settlement.current_session_id = metrics.session; settlement.current_session_paid = cost; } let pay_out = cost.saturating_sub(settlement.current_session_paid); - if pay_out > 0 { - let ticket_account = ticket_account_address(*ticket_id).into(); - let reward_account = worker_info.reward_receiver.into(); - let transfer_result = ::Currency::transfer( + if !pay_out.is_zero() { + let ticket_account = ticket_account_address(*ticket_id); + let transfer_result = ::Currency::transfer( &ticket_account, - &reward_account, + &worker_info.reward_receiver, pay_out.into(), KeepAlive, ); @@ -442,7 +596,7 @@ pub mod pallet { worker: worker_pubkey, paid: pay_out.into(), session_cost: cost.into(), - paid_to: reward_account, + paid_to: worker_info.reward_receiver.clone(), }); } Err(_) => { @@ -459,20 +613,24 @@ pub mod pallet { } } } - let todo = "reorder the pallet calls"; Ok(()) } + // MARK: - Benchmark + /// Submit benchmark score /// - /// This call is used to submit the benchmark app score of a worker. The score is used to simulate pruntime v2 worker heartbeat. - /// The init_score of the worker will also be updated according to the score. + /// This call is used to submit the benchmark app score of a worker. + /// if as_init_score == ture, the score will be used to update the worker init score. + /// else the score will be used to simulate the worker's v2 heartbeat. /// /// message: a worker signed message that contains the benchmark score. - #[pallet::call_index(4)] + /// + #[pallet::call_index(8)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] - pub fn submit_bench_message( + pub fn benchmark_submit_score( origin: OriginFor, + as_init_score: bool, message: SignedMessage, ) -> DispatchResult { let _ = ensure_signed(origin)?; @@ -503,11 +661,15 @@ pub mod pallet { Self::update_metrics_token(&worker_pubkey, &metrics_token)?; // Update the worker init score - let gas_6secs = gas_per_second.saturating_mul(6); - let score = bench_app_info.score_ratio.saturating_mul_u64(gas_6secs); - let p_init = registry::Pallet::::update_worker_score(&worker_pubkey, score); - // If the worker is scheduled working by the chain, simulate a heartbeat message. - if let Some(mut working_state) = WorkingWorkers::::get(&worker_pubkey) { + if as_init_score { + let gas_6secs = gas_per_second.saturating_mul(6); + let score = bench_app_info.score_ratio.saturating_mul_u64(gas_6secs); + registry::Pallet::::update_worker_init_score(&worker_pubkey, score); + } else if let Some(mut working_state) = WorkingWorkers::::get(&worker_pubkey) + { + let p_init = + registry::Pallet::::worker_init_score(&worker_pubkey).unwrap_or(0); + // If the worker is scheduled working by the chain, simulate a heartbeat message. let delta_time = now - working_state.last_update_time; if delta_time <= 0 { return Ok(()); @@ -527,6 +689,12 @@ pub mod pallet { p_instant, }; mq::Pallet::::push_bound_message(worker, worker_report); + Self::deposit_event(Event::HeartbeatV3 { + worker: worker_pubkey, + session_id: working_state.session_id, + iterations, + p_instant, + }); working_state.last_iterations = iterations; working_state.last_update_time = now; @@ -537,101 +705,6 @@ pub mod pallet { Ok(()) } - /// Create a new worker list - #[pallet::call_index(5)] - #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] - pub fn create_worker_list( - origin: OriginFor, - description: BoundedString<1024>, - prices: Prices, - init_workers: BoundedVec, - ) -> DispatchResult { - let owner = ensure_signed(origin.clone())?; - let id = Self::add_worker_list(WorkerListInfo { - owner: owner.into(), - prices, - description, - }); - if init_workers.len() > 0 { - Self::add_workers_to_list(origin, id, init_workers)?; - } - Ok(()) - } - - /// Add a worker to a worker list - #[pallet::call_index(6)] - #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] - pub fn add_workers_to_list( - origin: OriginFor, - list_id: ListId, - workers: BoundedVec, - ) -> DispatchResult { - let owner = ensure_signed(origin)?; - let list_info = WorkerLists::::get(list_id).ok_or(Error::::WorkerListNotFound)?; - ensure!(owner == list_info.owner.into(), Error::::NotAllowed); - for worker in workers.iter() { - let Some(worker_info) = WorkerDescriptions::::get(worker) else { - return Err(Error::::WorkerNotFound.into()); - }; - ensure!( - worker_info.prices == Default::default() - || worker_info.prices == list_info.prices, - Error::::PriceMismatch - ); - WorkerListWorkers::::insert(list_id, worker, ()); - } - Self::deposit_event(Event::WorkersAddedToList { - list_id, - workers: workers.into(), - }); - Ok(()) - } - - /// Remove a worker from a worker list - #[pallet::call_index(7)] - #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] - pub fn remove_worker_from_list( - origin: OriginFor, - list_id: ListId, - worker: WorkerPublicKey, - ) -> DispatchResult { - let owner = ensure_signed(origin)?; - let list_info = WorkerLists::::get(list_id).ok_or(Error::::WorkerListNotFound)?; - ensure!(owner == list_info.owner.into(), Error::::NotAllowed); - WorkerListWorkers::::remove(list_id, worker); - Self::deposit_event(Event::WorkerRemovedFromList { list_id, worker }); - Ok(()) - } - - /// Set worker description - #[pallet::call_index(8)] - #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] - pub fn set_worker_description( - origin: OriginFor, - signed_description: SignedWorkerDescription, - ) -> DispatchResult { - let _ = ensure_signed(origin)?; - let worker_pubkey = WorkerPublicKey(signed_description.worker_pubkey); - // Worker price can only be set once - ensure!( - !WorkerDescriptions::::contains_key(&worker_pubkey), - Error::::NotAllowed - ); - ensure!( - registry::Pallet::::worker_exsists(&worker_pubkey), - Error::::InvalidWorkerPubkey - ); - ensure!( - signed_description.verify::(), - Error::::SignatureVerificationFailed - ); - WorkerDescriptions::::insert(&worker_pubkey, signed_description.worker_description); - Self::deposit_event(Event::WorkerDescriptionSet { - worker: worker_pubkey, - }); - Ok(()) - } - /// Add a benchmark app (governance only) /// /// address: the address of the benchmark app @@ -639,16 +712,19 @@ pub mod pallet { /// score_ratio: the ratio of mapping gas to score #[pallet::call_index(9)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] - pub fn add_benchmark_app( + pub fn benchmark_add_app( origin: OriginFor, address: Address, manifest_cid: BoundedString<128>, score_ratio: Fraction, ) -> DispatchResult { T::GovernanceOrigin::ensure_origin(origin)?; + + ensure!(score_ratio.denominator > 0, Error::::InvalidParameter); + let ticket = Self::add_ticket(TicketInfo { system: true, - owner: [0u8; 32].into(), + owner: None, workers: WorkerSet::Any, address, manifest_cid, @@ -670,10 +746,7 @@ pub mod pallet { /// address: the address of the recommended benchmark app #[pallet::call_index(10)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] - pub fn set_recommended_benchmark_app( - origin: OriginFor, - address: Address, - ) -> DispatchResult { + pub fn benchmark_set_recommended(origin: OriginFor, address: Address) -> DispatchResult { T::GovernanceOrigin::ensure_origin(origin)?; RecommendedBenchmarkApp::::set(Some(address)); Self::deposit_event(Event::RecommendedBenchmarkAppChanged { address }); @@ -683,73 +756,24 @@ pub mod pallet { /// Combine add_benchmark_app and set_recommended_benchmark_app #[pallet::call_index(11)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] - pub fn set_benchmark_app( + pub fn benchmark_set_app( origin: OriginFor, address: Address, manifest_cid: BoundedString<128>, score_ratio: Fraction, ) -> DispatchResult { - Self::add_benchmark_app(origin.clone(), address, manifest_cid, score_ratio)?; - Self::set_recommended_benchmark_app(origin, address) - } - - /// Update worker session - /// - /// When a worker restarts or resets, it should update the session with the new session id. - #[pallet::call_index(12)] - #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] - pub fn update_session( - origin: OriginFor, - worker: Address, - update: SessionUpdate, - signature: BoundedVec, - ) -> DispatchResult { - let _ = ensure_signed(origin)?; - let worker_pubkey = WorkerPublicKey(worker); - - let signed_update = SignedSessionUpdate { - update: update.clone(), - signature: signature.into(), - }; - ensure!( - signed_update.verify::(&worker_pubkey), - Error::::SignatureVerificationFailed - ); - ensure!( - registry::Pallet::::worker_exsists(&worker_pubkey), - Error::::InvalidWorkerPubkey - ); - if let Some(session) = WorkerSessions::::get(&worker_pubkey) { - let computed_session = - SessionUpdate::session_from_seed::(update.seed, &session.last_nonce); - ensure!( - computed_session == update.session, - Error::::OutdatedMessage - ); - }; - WorkerSessions::::insert( - worker_pubkey, - WorkerSession { - session_id: update.session, - last_nonce: update.seed, - last_metrics_sn: 0, - reward_receiver: update.reward_receiver, - }, - ); - Self::deposit_event(Event::WorkerSessionUpdated { - worker: worker_pubkey, - session: update.session, - }); - return Ok(()); + Self::benchmark_add_app(origin.clone(), address, manifest_cid, score_ratio)?; + Self::benchmark_set_recommended(origin, address) } } + // MARK: Support functions + impl Pallet where T: mq::Config, - T::AccountId: Into + From, { - fn add_ticket(info: TicketInfo) -> TicketId { + fn add_ticket(info: TicketInfo) -> TicketId { let id = { let id = NextTicketId::::get(); NextTicketId::::put(id.wrapping_add(1)); @@ -760,7 +784,7 @@ pub mod pallet { id } - fn add_worker_list(info: WorkerListInfo) -> ListId { + fn add_worker_list(info: WorkerListInfo) -> ListId { let id = { let id = NextWorkerListId::::get(); NextWorkerListId::::put(id.wrapping_add(1)); @@ -835,15 +859,14 @@ pub mod pallet { } } - // For runtime api + // MARK: Runtime api impl Pallet where T: mq::Config, - T::AccountId: Into + From, { pub fn balance_of_ticket(ticket_id: TicketId) -> BalanceOf { - let account = ticket_account_address(ticket_id).into(); - ::Currency::free_balance(&account) + let account = ticket_account_address(ticket_id); + ::Currency::free_balance(&account) } } } diff --git a/standalone/runtime/src/lib.rs b/standalone/runtime/src/lib.rs index 119e4d243..7ecceb987 100644 --- a/standalone/runtime/src/lib.rs +++ b/standalone/runtime/src/lib.rs @@ -1532,7 +1532,6 @@ impl pallet_phat_tokenomic::Config for Runtime { impl pallet_wapod_workers::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type Currency = Balances; } parameter_types! { From c8ff562274fe8d398e7cf49104e36e9757d04edf Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Tue, 16 Jul 2024 00:16:26 +0800 Subject: [PATCH 18/25] patch proc-macro-crate --- standalone/pruntime/Cargo.lock | 195 +++++++++++++++++++-------------- standalone/pruntime/Cargo.toml | 2 + 2 files changed, 114 insertions(+), 83 deletions(-) diff --git a/standalone/pruntime/Cargo.lock b/standalone/pruntime/Cargo.lock index 6775ea875..20ee4aec3 100644 --- a/standalone/pruntime/Cargo.lock +++ b/standalone/pruntime/Cargo.lock @@ -611,7 +611,7 @@ checksum = "7b2d0f03b3640e3a630367e40c468cb7f309529c708ed1d88597047b0e7c6ef7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -1183,7 +1183,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -1666,7 +1666,7 @@ checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -1786,7 +1786,7 @@ checksum = "5fe87ce4529967e0ba1dcf8450bab64d97dfd5010a6256187ffe2e43e6f0e049" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -1860,7 +1860,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics 0.10.0", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -1963,7 +1963,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.43", + "syn 2.0.70", "termcolor", "toml 0.8.2", "walkdir", @@ -2154,7 +2154,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -2194,7 +2194,7 @@ checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -2412,7 +2412,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "syn 2.0.43", + "syn 2.0.70", "toml 0.7.6", "walkdir", ] @@ -2430,7 +2430,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -2456,7 +2456,7 @@ dependencies = [ "serde", "serde_json", "strum 0.25.0", - "syn 2.0.43", + "syn 2.0.70", "tempfile", "thiserror", "tiny-keccak", @@ -2601,7 +2601,7 @@ dependencies = [ "fs-err", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -2831,10 +2831,10 @@ name = "frame-election-provider-solution-type" version = "4.0.0-dev" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#789ffb66dcfcf3b54a1e6786e928ac91c4fdb465" dependencies = [ - "proc-macro-crate 2.0.1", + "proc-macro-crate 2.0.2", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -2941,7 +2941,7 @@ dependencies = [ "proc-macro2", "quote", "sp-core-hashing", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -2950,10 +2950,10 @@ version = "4.0.0-dev" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#789ffb66dcfcf3b54a1e6786e928ac91c4fdb465" dependencies = [ "frame-support-procedural-tools-derive", - "proc-macro-crate 2.0.1", + "proc-macro-crate 2.0.2", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -2963,7 +2963,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polk dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -3117,7 +3117,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -3836,7 +3836,7 @@ dependencies = [ "quote", "serde", "serde_json", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -3893,7 +3893,7 @@ dependencies = [ "itertools", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -3908,7 +3908,7 @@ dependencies = [ "parity-scale-codec", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", "synstructure", ] @@ -4339,7 +4339,7 @@ dependencies = [ "macro_magic_core", "macro_magic_macros", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -4353,7 +4353,7 @@ dependencies = [ "macro_magic_core_macros", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -4364,7 +4364,7 @@ checksum = "9ea73aa640dc01d62a590d48c0c3521ed739d53b27f919b25c3551e233481654" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -4375,7 +4375,7 @@ checksum = "ef9d79ae96aaba821963320eb2b6e34d17df1e5a83d8a1985c29cc5be59577b3" dependencies = [ "macro_magic_core", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -4748,7 +4748,7 @@ dependencies = [ "proc-macro-crate 1.2.1", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -5030,7 +5030,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polk dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -5559,10 +5559,10 @@ name = "pallet-staking-reward-curve" version = "4.0.0-dev" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#789ffb66dcfcf3b54a1e6786e928ac91c4fdb465" dependencies = [ - "proc-macro-crate 2.0.1", + "proc-macro-crate 2.0.2", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -5715,9 +5715,9 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.6.5" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dec8a8073036902368c2cdc0387e85ff9a37054d7e7c98e592145e0c92cd4fb" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" dependencies = [ "arrayvec 0.7.2", "bitvec 1.0.1", @@ -5730,11 +5730,11 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.5" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312270ee71e1cd70289dacf597cab7b207aa107d2f28191c2ae45b2ece18a260" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate 1.2.1", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -6217,15 +6217,17 @@ dependencies = [ "serde", "serde_json", "sgx-attestation", + "sp-api", "sp-core", "sp-io", "sp-runtime", "sp-std 8.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0)", + "wapod-types", ] [[package]] name = "phala-rocket-middleware" -version = "0.1.0" +version = "0.1.1" dependencies = [ "log", "rocket", @@ -6419,7 +6421,7 @@ checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -6516,7 +6518,7 @@ dependencies = [ "proc-macro-crate 1.2.1", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", "unzip3", ] @@ -6650,7 +6652,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9825a04601d60621feed79c4e6b56d65db77cdca55cef43b46b0de1096d1c282" dependencies = [ "proc-macro2", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -6680,14 +6682,21 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a" +version = "2.0.2" +source = "git+https://github.com/kvinwang/proc-macro-crate?branch=update-toml#758987cc8f582405f07364dd536142abd5f4da55" dependencies = [ - "toml_datetime", "toml_edit 0.20.2", ] +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit 0.21.1", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -6726,14 +6735,14 @@ checksum = "834da187cfe638ae8abb0203f0b33e5ccdb02a28e7199f2f47b3e2754f50edca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -6759,7 +6768,7 @@ checksum = "606c4ba35817e2922a308af55ad51bab3645b59eae5c570d4a6cf07e36bd493b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", "version_check", "yansi 0.5.1", ] @@ -7011,9 +7020,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.33" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -7563,7 +7572,7 @@ dependencies = [ "proc-macro2", "quote", "rocket_http", - "syn 2.0.43", + "syn 2.0.70", "unicode-xid", "version_check", ] @@ -7887,9 +7896,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.10.0" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7d66a1128282b7ef025a8ead62a4a9fcf017382ec53b8ffbf4d7bf77bd3c60" +checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" dependencies = [ "bitvec 1.0.1", "cfg-if", @@ -7901,11 +7910,11 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.10.0" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" +checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" dependencies = [ - "proc-macro-crate 1.2.1", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -8077,9 +8086,9 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] @@ -8107,13 +8116,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -8497,10 +8506,10 @@ dependencies = [ "Inflector", "blake2", "expander", - "proc-macro-crate 2.0.1", + "proc-macro-crate 2.0.2", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -8687,7 +8696,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polk dependencies = [ "quote", "sp-core-hashing", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -8718,7 +8727,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polk dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -8728,7 +8737,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk#b4c816665bd094b6ad703f1 dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -8937,10 +8946,10 @@ source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polk dependencies = [ "Inflector", "expander", - "proc-macro-crate 2.0.1", + "proc-macro-crate 2.0.2", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -8950,10 +8959,10 @@ source = "git+https://github.com/paritytech/polkadot-sdk#b4c816665bd094b6ad703f1 dependencies = [ "Inflector", "expander", - "proc-macro-crate 2.0.1", + "proc-macro-crate 2.0.2", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -9138,7 +9147,7 @@ dependencies = [ "parity-scale-codec", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -9427,7 +9436,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -9482,9 +9491,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.43" +version = "2.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53" +checksum = "2f0209b68b3613b093e0ec905354eccaedcfe83b8cb37cbdeae64026c3064c16" dependencies = [ "proc-macro2", "quote", @@ -9505,7 +9514,7 @@ checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", "unicode-xid", ] @@ -9660,7 +9669,7 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -9789,7 +9798,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -9911,9 +9920,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" dependencies = [ "serde", ] @@ -9944,6 +9953,17 @@ dependencies = [ "winnow", ] +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap 2.0.0", + "toml_datetime", + "winnow", +] + [[package]] name = "tower-service" version = "0.3.2" @@ -9970,7 +9990,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -10549,6 +10569,15 @@ dependencies = [ "try-lock", ] +[[package]] +name = "wapod-types" +version = "0.1.0" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", +] + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" @@ -10582,7 +10611,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", "wasm-bindgen-shared", ] @@ -10639,7 +10668,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -11511,7 +11540,7 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] @@ -11552,7 +11581,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.70", ] [[package]] diff --git a/standalone/pruntime/Cargo.toml b/standalone/pruntime/Cargo.toml index 4f74d9c8b..9d06842d4 100644 --- a/standalone/pruntime/Cargo.toml +++ b/standalone/pruntime/Cargo.toml @@ -55,3 +55,5 @@ derive_more = { version = "0.99.17", git = "https://github.com/JelteF/derive_mor # For pink-chain-extension, it will introduce Substrate from crates-io which usually different with polkadot-branch sp-core = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "release-polkadot-v1.5.0" } sp-runtime-interface = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "release-polkadot-v1.5.0" } + +proc-macro-crate = { git = "https://github.com/kvinwang/proc-macro-crate", branch = "update-toml" } From ce2f7c259be12c53e58bd8b41183025265e07b9c Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Tue, 16 Jul 2024 19:05:56 +0800 Subject: [PATCH 19/25] Add unit tests --- pallets/phala/src/mock.rs | 18 + pallets/phala/src/wapod_workers.rs | 1035 +++++++++++++++++++++++++--- 2 files changed, 955 insertions(+), 98 deletions(-) diff --git a/pallets/phala/src/mock.rs b/pallets/phala/src/mock.rs index b4f192b2d..6b3983f6e 100644 --- a/pallets/phala/src/mock.rs +++ b/pallets/phala/src/mock.rs @@ -20,12 +20,29 @@ use sp_runtime::{ traits::{BlakeTwo256, IdentityLookup}, BuildStorage, }; +use wapod_types::crypto::CryptoProvider; pub(crate) type Balance = u128; type Block = frame_system::mocking::MockBlock; pub(crate) type BlockNumber = u64; +pub struct MockCrypto; +impl CryptoProvider for MockCrypto { + fn sr25519_verify(_public_key: &[u8], _message: &[u8], signature: &[u8]) -> bool { + if signature.starts_with(b"valid") { + return true; + } + false + } + fn keccak_256(data: &[u8]) -> [u8; 32] { + sp_io::hashing::keccak_256(data) + } + fn blake2b_256(data: &[u8]) -> [u8; 32] { + sp_io::hashing::blake2_256(data) + } +} + // Configure a mock runtime to test the pallet. frame_support::construct_runtime!( pub struct Test { @@ -397,6 +414,7 @@ impl stake_pool::Config for Test { impl wapod_workers::Config for Test { type RuntimeEvent = RuntimeEvent; + type Crypto = MockCrypto; } pub struct MockValidator; diff --git a/pallets/phala/src/wapod_workers.rs b/pallets/phala/src/wapod_workers.rs index b47859df6..32302b20d 100644 --- a/pallets/phala/src/wapod_workers.rs +++ b/pallets/phala/src/wapod_workers.rs @@ -1,4 +1,7 @@ //! The pallet managing the wapod workers. +//! +//! This pallet is responsible for managing worker descriptions, sessions, and tickets. +//! It also handles worker lists, benchmarking, and settlement of tickets. pub use self::pallet::*; @@ -24,7 +27,10 @@ pub mod pallet { use wapod_types::{ bench_app::{BenchScore, SignedMessage, SigningMessage}, crypto::{verify::Verifiable, CryptoProvider}, - metrics::{MetricsToken, SignedAppsMetrics, VersionedAppsMetrics}, + metrics::{ + AppMetrics, AppsMetrics, ClaimMap, MetricsToken, SignedAppsMetrics, + VersionedAppsMetrics, + }, primitives::{BoundedString, BoundedVec}, session::{SessionUpdate, SignedSessionUpdate}, ticket::{Balance, Prices, SignedWorkerDescription, WorkerDescription}, @@ -36,6 +42,7 @@ pub mod pallet { pub type TicketId = u64; pub type ListId = u64; + /// Address type used for apps and workers. pub type Address = [u8; 32]; #[derive(Encode, Decode, TypeInfo, Debug, Clone, Copy, PartialEq, Eq, MaxEncodedLen)] @@ -45,6 +52,7 @@ pub mod pallet { } impl Fraction { + /// Performs a saturating multiplication of the fraction with a u64 value. fn saturating_mul_u64(&self, rhs: u64) -> u64 { let rhs = rhs as u128; let numerator = self.numerator as u128; @@ -54,21 +62,30 @@ pub mod pallet { } } + /// Information about a benchmark app. #[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] pub struct BenchAppInfo { + /// The ticket id used to deploy the benchmark app. ticket: TicketId, + /// The ratio of mapping gas to score. score_ratio: Fraction, } + /// Represents a worker's session information. When a worker restarts, it creates a new session. #[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] pub struct WorkerSession { + /// The session id of the worker. pub session_id: [u8; 32], + /// The nonce that last used in metrics report. pub last_nonce: [u8; 32], + /// The last metrics sequence number. pub last_metrics_sn: u64, + /// The account id that receives the ticket reward. pub reward_receiver: AccountId, } - struct SpCrypto; + /// Cryptographic provider for signature verification. + pub struct SpCrypto; impl CryptoProvider for SpCrypto { fn sr25519_verify(public_key: &[u8], message: &[u8], signature: &[u8]) -> bool { let Ok(public_key) = public_key.try_into() else { @@ -87,41 +104,67 @@ pub mod pallet { } } + /// Defines the set of workers that a ticket can be deployed to. #[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] pub enum WorkerSet { + /// The ticket can be deployed to any worker. Any, + /// The ticket can be deployed to workers in the specified list. WorkerList(ListId), } + /// Information about a ticket. #[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] pub struct TicketInfo { + /// If true, the ticket is a system (benchmark) ticket. pub system: bool, + /// The account id of the ticket owner. + /// None if the ticket is a system ticket. pub owner: Option, + /// The set of workers that the ticket can be deployed to. pub workers: WorkerSet, + /// The address of the target app. pub address: Address, + /// The resource prices of the ticket. pub prices: Prices, + /// The IPFS CID of the target app's manifest. pub manifest_cid: BoundedString<128>, } + /// Information about a worker list. #[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] pub struct WorkerListInfo { + /// The account id of the list owner. pub owner: AccountId, + /// The resource prices of the workers in the list. pub prices: Prices, + /// The description of the list. pub description: BoundedString<1024>, } + /// Settlement information for a ticket and worker pair. #[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq, MaxEncodedLen, Default)] pub struct SettlementInfo { + /// The current session id of the App. pub current_session_id: [u8; 32], + /// The total amount paid in the current App session. + /// If the ticket is created after the worker's session, this value will be initialized + /// to the cost calculated from the first metrics report but without actual payment. pub current_session_paid: Balance, + /// The total amount paid to the worker. pub total_paid: Balance, } + /// Represents the computation state of a worker. V2 compatible. #[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] - pub struct WorkingState { + pub struct ComputationState { + /// The id of the current computation session. session_id: u32, + /// Whether the worker is unresponsive. unresponsive: bool, + /// The number of iterations in the last heartbeat. last_iterations: u64, + /// The time of the last heartbeat. last_update_time: i64, } @@ -129,6 +172,7 @@ pub mod pallet { #[pallet::config] pub trait Config: frame_system::Config + PhalaConfig { type RuntimeEvent: From> + IsType<::RuntimeEvent>; + type Crypto: CryptoProvider; } // MARK: - Pallet storage @@ -139,11 +183,13 @@ pub mod pallet { #[pallet::storage_version(STORAGE_VERSION)] pub struct Pallet(_); + /// The next ticket ID to use. #[pallet::storage] pub type NextTicketId = StorageValue<_, TicketId, ValueQuery>; /// Active tickets. - /// Each ticket holds a payment infomation to a target app address. Multiple ticket can pay for a same app at the sametime. + /// Each ticket holds payment information for a target app address. + /// Multiple tickets can pay for the same app at the same time. #[pallet::storage] pub type Tickets = StorageMap<_, Twox64Concat, TicketId, TicketInfo>; @@ -159,6 +205,7 @@ pub mod pallet { ValueQuery, >; + /// The next worker list ID to use. #[pallet::storage] pub type NextWorkerListId = StorageValue<_, ListId, ValueQuery>; @@ -169,7 +216,7 @@ pub mod pallet { pub type WorkerLists = StorageMap<_, Twox64Concat, ListId, WorkerListInfo>; - /// Concrete workers associated to worker list. + /// Workers associated to worker list. #[pallet::storage] pub type WorkerListWorkers = StorageDoubleMap<_, Twox64Concat, ListId, Twox64Concat, WorkerPublicKey, ()>; @@ -186,7 +233,7 @@ pub mod pallet { /// Working state of wapod workers. V2 compatible. #[pallet::storage] - pub type WorkingWorkers = StorageMap<_, Twox64Concat, WorkerPublicKey, WorkingState>; + pub type ComputationWorkers = StorageMap<_, Twox64Concat, WorkerPublicKey, ComputationState>; /// Allowed app addresses that used to benchmark workers. #[pallet::storage] @@ -197,9 +244,10 @@ pub mod pallet { pub type RecommendedBenchmarkApp = StorageValue<_, Address>; // MARK: - Pallet error + + /// Errors that can occur in this pallet. #[pallet::error] pub enum Error { - UnsupportedManifestVersion, NotAllowed, WorkerNotFound, WorkerListNotFound, @@ -216,35 +264,34 @@ pub mod pallet { } // MARK: - Pallet events + + /// Events emitted by this pallet. #[pallet::event] #[pallet::generate_deposit(fn deposit_event)] pub enum Event { - TicketCreated { - id: TicketId, - }, - TicketClosed { - id: TicketId, - }, - WorkerListCreated { - id: ListId, - }, + /// A new ticket was created. + TicketCreated { id: TicketId }, + /// A ticket was closed. + TicketClosed { id: TicketId }, + /// A new worker list was created. + WorkerListCreated { id: ListId }, + /// Some workers were added to a list. WorkersAddedToList { list_id: ListId, workers: Vec, }, + /// A worker was removed from a list. WorkerRemovedFromList { list_id: ListId, worker: WorkerPublicKey, }, - WorkerDescriptionSet { - worker: WorkerPublicKey, - }, - BenchmarkAppAdded { - address: Address, - }, - RecommendedBenchmarkAppChanged { - address: Address, - }, + /// A worker's description was set. + WorkerDescriptionSet { worker: WorkerPublicKey }, + /// A benchmark app was added. + BenchmarkAppAdded { address: Address }, + /// The recommended benchmark app was changed. + RecommendedBenchmarkAppChanged { address: Address }, + /// A ticket was settled. Settled { ticket_id: TicketId, worker: WorkerPublicKey, @@ -252,25 +299,31 @@ pub mod pallet { session_cost: BalanceOf, paid_to: T::AccountId, }, + /// A settlement failed. SettleFailed { ticket_id: TicketId, worker: WorkerPublicKey, paid: BalanceOf, session_cost: BalanceOf, }, + /// A worker's session was updated. WorkerSessionUpdated { worker: WorkerPublicKey, session: [u8; 32], }, + /// A simulated heartbeat was emitted (V3). HeartbeatV3 { worker: WorkerPublicKey, + /// The computation session id. session_id: u32, + /// The v2 iterations converted from gas consumed. iterations: u64, + /// The p_instant is estimated by the pallet, might not be the same as the GK state. p_instant: u32, }, } - pub fn ticket_account_address(ticket_id: TicketId) -> T + fn ticket_account_address(ticket_id: TicketId) -> T where T: Encode + Decode, { @@ -287,10 +340,16 @@ pub mod pallet { { // MARK: - Worker management - /// Set worker description + /// Sets the description and price for a worker. + /// + /// This function allows setting the description for a worker, which can only be done once. + /// The description must be signed by the worker via its RPC. + /// + /// # Parameters + /// - `signed_description`: A signed description of the worker. #[pallet::call_index(0)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] - pub fn worker_set_description( + pub fn worker_description_set( origin: OriginFor, signed_description: SignedWorkerDescription, ) -> DispatchResult { @@ -306,7 +365,7 @@ pub mod pallet { Error::::InvalidWorkerPubkey ); ensure!( - signed_description.verify::(), + signed_description.verify::(), Error::::SignatureVerificationFailed ); WorkerDescriptions::::insert(&worker_pubkey, signed_description.worker_description); @@ -316,18 +375,22 @@ pub mod pallet { Ok(()) } - /// Update worker session + /// Updates the session for a worker. + /// + /// This function should be called when a worker restarts or resets to update its session with a new session ID. + /// The new session must be initiated with the last nonce on-chain to ensure the session is not lanched before the last metrics report. /// - /// When a worker restarts or resets, it should update the session with the new session id. + /// # Parameters + /// - `update`: A signed session update containing the new session information. #[pallet::call_index(1)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] - pub fn worker_update_session( + pub fn worker_session_update( origin: OriginFor, update: SignedSessionUpdate, ) -> DispatchResult { let _ = ensure_signed(origin)?; ensure!( - update.verify::(), + update.verify::(), Error::::SignatureVerificationFailed ); let worker_pubkey = WorkerPublicKey(update.public_key); @@ -338,7 +401,7 @@ pub mod pallet { let update = update.update; if let Some(session) = WorkerSessions::::get(&worker_pubkey) { let computed_session = - SessionUpdate::session_from_seed::(update.seed, &session.last_nonce); + SessionUpdate::session_from_seed::(update.seed, &session.last_nonce); ensure!( computed_session == update.session, Error::::OutdatedMessage @@ -363,7 +426,14 @@ pub mod pallet { return Ok(()); } - /// Create a new worker list + /// Creates a new worker list. + /// + /// This function creates a new worker list with specified description, prices, and initial workers. + /// + /// # Parameters + /// - `description`: A string describing the worker list. + /// - `prices`: The resource prices for each worker in the list. + /// - `init_workers`: An optional list of initial workers to add to the list. #[pallet::call_index(2)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] pub fn worker_list_create( @@ -384,7 +454,11 @@ pub mod pallet { Ok(()) } - /// Add a worker to a worker list + /// Adds workers to an existing worker list. + /// + /// # Parameters + /// - `list_id`: The ID of the worker list to add workers to. + /// - `workers`: A vector of worker public keys to add to the list. #[pallet::call_index(3)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] pub fn worker_list_add_workers( @@ -413,7 +487,7 @@ pub mod pallet { Ok(()) } - /// Remove a worker from a worker list + /// Removes a worker from a worker list. #[pallet::call_index(4)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] pub fn worker_list_remove_worker( @@ -431,13 +505,19 @@ pub mod pallet { // MARK: - Tickets - /// Create a new ticket + /// Creates a new ticket for an application. /// - /// deposit: the deposit to be paid to the ticket account - /// address: the address of the target app. It must match the address of the manifest, otherwise the ticket will be rejected by workers. - /// manifest_cid: the IPFS CID of the manifest of the target app - /// worker_list: the worker list that the ticket is allowed to be settled by. - /// prices: the resource prices of the ticket. If is recommended to use the prices of the worker list or else the ticket may be rejected by workers. + /// The address must match the address of the target application. Otherwise, this call will not fail but the ticket will not be settled, + /// and the worker will likely reject the ticket. + /// + /// # Parameters + /// - `deposit`: The amount to be deposited into the ticket account. + /// - `address`: The address of the target application. + /// - `manifest_cid`: The IPFS CID of the application manifest. + /// - `worker_list`: The ID of the worker list allowed to settle this ticket. + /// - `prices`: + /// The resource prices for the ticket. This will be merged with the prices of the worker list while settling the ticket. + /// Leave None for the field to use the prices of the worker list. #[pallet::call_index(5)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] pub fn ticket_create( @@ -465,9 +545,10 @@ pub mod pallet { Ok(()) } - /// Close a ticket + /// Closes an ticket. /// - /// The state of the ticket will be removed and the deposit will be refunded to the owner. + /// # Parameters + /// - `ticket_id`: The ID of the ticket to be closed. #[pallet::call_index(6)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] pub fn ticket_close(origin: OriginFor, ticket_id: TicketId) -> DispatchResult { @@ -493,18 +574,24 @@ pub mod pallet { Ok(()) } - /// Submit app metrics + /// Submits application metrics for settlement. + /// + /// This function allows workers to submit signed metrics for applications, which are used to settle tickets. /// - /// message: a worker signed message that contains the metrics of apps. - /// The message will be verified and the metrics will be used to settle the corresponding tickets. + /// # Parameters + /// - `message`: A signed message containing the application metrics. #[pallet::call_index(7)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] - pub fn ticket_settle(origin: OriginFor, message: SignedAppsMetrics) -> DispatchResult { + pub fn ticket_settle( + origin: OriginFor, + message: SignedAppsMetrics, + claim_map: ClaimMap, + ) -> DispatchResult { let _ = ensure_signed(origin)?; let worker_pubkey = { // signature verification ensure!( - message.verify::(), + message.verify::(), Error::::SignatureVerificationFailed ); let worker_pubkey = WorkerPublicKey(message.worker_pubkey); @@ -541,13 +628,13 @@ pub mod pallet { // update metrics for each ticket // Up to 64 entries - let claim_map: BTreeMap<_, _> = message.claim_map.into_iter().collect(); + let claim_map: BTreeMap<_, _> = claim_map.into_iter().collect(); // Up to 64 entries for metrics in all_metrics.apps { - let ticket_ids = claim_map - .get(&metrics.address) - .ok_or(Error::::NotAllowed)?; + let Some(ticket_ids) = claim_map.get(&metrics.address) else { + continue; + }; // Up to 5 entries for ticket_id in ticket_ids.iter() { let ticket = @@ -618,24 +705,23 @@ pub mod pallet { // MARK: - Benchmark - /// Submit benchmark score - /// - /// This call is used to submit the benchmark app score of a worker. - /// if as_init_score == ture, the score will be used to update the worker init score. - /// else the score will be used to simulate the worker's v2 heartbeat. + /// Submits a benchmark score for a worker. /// - /// message: a worker signed message that contains the benchmark score. + /// This function allows submitting a benchmark score for a worker, which can be used to update the worker's initial score or simulate a V2 heartbeat. /// + /// # Parameters + /// - `as_init_score`: If true, the score will update the worker's initial score; otherwise, it will simulate a V2 heartbeat. + /// - `message`: A signed message containing the benchmark score. #[pallet::call_index(8)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] - pub fn benchmark_submit_score( + pub fn benchmark_score_submit( origin: OriginFor, as_init_score: bool, message: SignedMessage, ) -> DispatchResult { let _ = ensure_signed(origin)?; ensure!( - message.verify::(), + message.verify::(), Error::::SignatureVerificationFailed ); let worker_pubkey = WorkerPublicKey(message.worker_pubkey); @@ -662,21 +748,27 @@ pub mod pallet { // Update the worker init score if as_init_score { - let gas_6secs = gas_per_second.saturating_mul(6); - let score = bench_app_info.score_ratio.saturating_mul_u64(gas_6secs); + let iterations_per_sec = bench_app_info + .score_ratio + .saturating_mul_u64(gas_per_second); + let score = iterations_per_sec.saturating_mul(6); registry::Pallet::::update_worker_init_score(&worker_pubkey, score); - } else if let Some(mut working_state) = WorkingWorkers::::get(&worker_pubkey) + } else if let Some(mut computation_state) = + ComputationWorkers::::get(&worker_pubkey) { + // If the worker is scheduled computing by the chain, simulate a heartbeat message. let p_init = registry::Pallet::::worker_init_score(&worker_pubkey).unwrap_or(0); - // If the worker is scheduled working by the chain, simulate a heartbeat message. - let delta_time = now - working_state.last_update_time; + let iterations = + bench_app_info.score_ratio.saturating_mul_u64(gas_consumed); + let delta_time = now - computation_state.last_update_time; if delta_time <= 0 { + computation_state.last_iterations = iterations; + ComputationWorkers::::insert(&worker_pubkey, computation_state); return Ok(()); } - let iterations = - bench_app_info.score_ratio.saturating_mul_u64(gas_consumed); - let delta_iterations = iterations - working_state.last_iterations; + let delta_iterations = iterations - computation_state.last_iterations; + let iter_per_sec = delta_iterations / delta_time as u64; let p_instant = delta_iterations / delta_time as u64 * 6; let p_max = p_init * 120 / 100; let p_instant = p_instant.min(p_max) as u32; @@ -685,34 +777,37 @@ pub mod pallet { // Minic the worker heartbeat message let worker_report = WorkingReportEvent::HeartbeatV3 { iterations, - session_id: working_state.session_id, + session_id: computation_state.session_id, p_instant, }; mq::Pallet::::push_bound_message(worker, worker_report); Self::deposit_event(Event::HeartbeatV3 { worker: worker_pubkey, - session_id: working_state.session_id, + session_id: computation_state.session_id, iterations, p_instant, }); - working_state.last_iterations = iterations; - working_state.last_update_time = now; - WorkingWorkers::::insert(&worker_pubkey, working_state); + computation_state.last_iterations = iterations; + computation_state.last_update_time = now; + ComputationWorkers::::insert(&worker_pubkey, computation_state); } } }; Ok(()) } - /// Add a benchmark app (governance only) + /// Adds a new benchmark application (governance only). + /// + /// This function allows the governance to add a new benchmark application to the whitelist. /// - /// address: the address of the benchmark app - /// manifest_cid: the IPFS CID of the manifest of the benchmark app - /// score_ratio: the ratio of mapping gas to score + /// # Parameters + /// - `address`: The address of the benchmark application. + /// - `manifest_cid`: The IPFS CID of the application manifest. + /// - `score_ratio`: The ratio for mapping gas to score. #[pallet::call_index(9)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] - pub fn benchmark_add_app( + pub fn benchmark_app_add( origin: OriginFor, address: Address, manifest_cid: BoundedString<128>, @@ -741,29 +836,42 @@ pub mod pallet { Ok(()) } - /// Set recommended benchmark app (governance only) + /// Sets the recommended benchmark application (governance only). /// - /// address: the address of the recommended benchmark app + /// # Parameters + /// - `address`: The address of the recommended benchmark application. #[pallet::call_index(10)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] - pub fn benchmark_set_recommended(origin: OriginFor, address: Address) -> DispatchResult { + pub fn benchmark_app_set_recommended( + origin: OriginFor, + address: Address, + ) -> DispatchResult { T::GovernanceOrigin::ensure_origin(origin)?; RecommendedBenchmarkApp::::set(Some(address)); Self::deposit_event(Event::RecommendedBenchmarkAppChanged { address }); Ok(()) } - /// Combine add_benchmark_app and set_recommended_benchmark_app + /// Combine benchmark_app_add and benchmark_app_set_recommended #[pallet::call_index(11)] #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] - pub fn benchmark_set_app( + pub fn benchmark_app_set( origin: OriginFor, address: Address, manifest_cid: BoundedString<128>, score_ratio: Fraction, ) -> DispatchResult { - Self::benchmark_add_app(origin.clone(), address, manifest_cid, score_ratio)?; - Self::benchmark_set_recommended(origin, address) + Self::benchmark_app_add(origin.clone(), address, manifest_cid, score_ratio)?; + Self::benchmark_app_set_recommended(origin, address) + } + + /// Remove a benchmark application from the whitelist (governance only). + #[pallet::call_index(12)] + #[pallet::weight(Weight::from_parts(10_000u64, 0) + T::DbWeight::get().writes(1u64))] + pub fn benchmark_app_remove(origin: OriginFor, address: Address) -> DispatchResult { + T::GovernanceOrigin::ensure_origin(origin)?; + BenchmarkApps::::remove(address); + Ok(()) } } @@ -827,9 +935,9 @@ pub mod pallet { WorkerEvent::BenchStart { duration: _ } => (), WorkerEvent::BenchScore(_) => (), WorkerEvent::Started { session_id, .. } => { - WorkingWorkers::::insert( + ComputationWorkers::::insert( &worker_pubkey, - WorkingState { + ComputationState { session_id, unresponsive: false, last_iterations: 0, @@ -838,17 +946,17 @@ pub mod pallet { ); } WorkerEvent::Stopped => { - WorkingWorkers::::remove(&worker_pubkey); + ComputationWorkers::::remove(&worker_pubkey); } WorkerEvent::EnterUnresponsive => { - WorkingWorkers::::mutate(&worker_pubkey, |state| { + ComputationWorkers::::mutate(&worker_pubkey, |state| { if let Some(state) = state { state.unresponsive = true; } }); } WorkerEvent::ExitUnresponsive => { - WorkingWorkers::::mutate(&worker_pubkey, |state| { + ComputationWorkers::::mutate(&worker_pubkey, |state| { if let Some(state) = state { state.unresponsive = false; } @@ -869,12 +977,743 @@ pub mod pallet { ::Currency::free_balance(&account) } } -} -sp_api::decl_runtime_apis! { - /// The API of the wapod workers pallet. - pub trait WapodWorkersApi where Balance: codec::Codec { - /// Get balance of given ticket. - fn balance_of_ticket(ticket_id: TicketId) -> Balance; + sp_api::decl_runtime_apis! { + /// The API of the wapod workers pallet. + pub trait WapodWorkersApi where Balance: codec::Codec { + /// Get balance of given ticket. + fn balance_of_ticket(ticket_id: TicketId) -> Balance; + } + } + + // MARK: - Tests + + #[cfg(test)] + mod tests { + use super::*; + use crate::mock::{ + ecdh_pubkey, elapse_seconds, new_test_ext, set_block_1, take_events, take_messages, + worker_pubkey, BlockNumber, MockCrypto, RuntimeEvent as TestEvent, + RuntimeOrigin as Origin, Test, + }; + // Pallets + use crate::mock::{PhalaComputation, PhalaRegistry, PhalaWapodWorkers, System}; + use frame_support::{assert_err, assert_ok}; + use phala_types::messaging::WorkerEventWithKey; + use wapod_types::{ + bench_app::{BenchScore, SignedMessage, SigningMessage}, + crypto::{verify::Verifiable, CryptoProvider}, + metrics::{ + AppMetrics, AppsMetrics, ClaimMap, MetricsToken, SignedAppsMetrics, + VersionedAppsMetrics, + }, + primitives::{BoundedString, BoundedVec}, + session::{SessionUpdate, SignedSessionUpdate}, + ticket::{Balance, Prices, SignedWorkerDescription, WorkerDescription}, + }; + + fn setup_workers(n: u8) { + for i in 1..=n { + let worker = worker_pubkey(i); + assert_ok!(PhalaRegistry::force_register_worker( + Origin::root(), + worker, + ecdh_pubkey(1), + Some(1) + )); + } + } + + struct Events(Vec); + + impl Events { + fn take() -> Self { + Self(take_events()) + } + fn has(&self, event: impl Into) -> bool { + let event = event.into(); + self.0.iter().any(|x| x == &event) + } + fn find_settlement_for( + &self, + ticket: TicketId, + worker: WorkerPublicKey, + ) -> Option { + for event in self.0.iter() { + if let TestEvent::PhalaWapodWorkers(Event::::Settled { + ticket_id, + worker: worker_id, + paid, + .. + }) = event + { + if ticket_id == &ticket && worker_id == &worker { + return Some(*paid); + } + } + } + None + } + fn find_heartbeat_v3(&self, worker: WorkerPublicKey) -> Option<(u64, u32)> { + for event in self.0.iter() { + if let TestEvent::PhalaWapodWorkers(Event::::HeartbeatV3 { + worker: worker_id, + session_id: _, + iterations, + p_instant, + }) = event + { + if worker_id == &worker { + return Some((*iterations, *p_instant)); + } + } + } + None + } + } + + fn create_worker_list() -> ListId { + create_worker_list_with_price(Prices::default()) + } + + fn create_worker_list_with_price(prices: Prices) -> ListId { + let result = PhalaWapodWorkers::worker_list_create( + Origin::signed(1), + "my list".to_string().into(), + prices, + vec![].into(), + ); + assert_ok!(result); + + let mut list_id = None; + for event in take_events() { + if let TestEvent::PhalaWapodWorkers(Event::::WorkerListCreated { id }) = event + { + list_id = Some(id); + } + } + list_id.expect("No WorkerListCreated event emitted") + } + + fn setup_worker_list(n: u8, prices: Prices) -> ListId { + for id in 1..=n { + let result = PhalaWapodWorkers::worker_description_set( + Origin::signed(1), + SignedWorkerDescription { + worker_pubkey: worker_pubkey(id).0, + worker_description: WorkerDescription { + prices: prices.clone(), + description: "my worker".to_string().into(), + }, + signature: b"valid".to_vec().into(), + }, + ); + assert_ok!(result); + } + + let list_id = create_worker_list_with_price(prices); + let result = PhalaWapodWorkers::worker_list_add_workers( + Origin::signed(1), + list_id, + (1..=n) + .into_iter() + .map(worker_pubkey) + .collect::>() + .into(), + ); + assert_ok!(result); + for id in 1..=n { + assert!(WorkerListWorkers::::contains_key( + list_id, + &worker_pubkey(id) + )) + } + list_id + } + + #[test] + fn can_not_set_worker_description_without_register() { + new_test_ext().execute_with(|| { + set_block_1(); + + let result = PhalaWapodWorkers::worker_description_set( + Origin::signed(1), + SignedWorkerDescription { + worker_pubkey: worker_pubkey(0).0, + worker_description: WorkerDescription { + prices: Prices::default(), + description: "my worker".to_string().into(), + }, + signature: b"valid".to_vec().into(), + }, + ); + + assert_err!(result, Error::::InvalidWorkerPubkey); + }); + } + + #[test] + fn can_set_worker_description() { + new_test_ext().execute_with(|| { + set_block_1(); + setup_workers(1); + + let result = PhalaWapodWorkers::worker_description_set( + Origin::signed(1), + SignedWorkerDescription { + worker_pubkey: worker_pubkey(1).0, + worker_description: WorkerDescription { + prices: Prices::default(), + description: "my worker".to_string().into(), + }, + signature: b"valid".to_vec().into(), + }, + ); + + assert_ok!(result); + + let events = Events::take(); + assert!(events.has(Event::WorkerDescriptionSet { + worker: worker_pubkey(1) + })); + }); + } + + #[test] + fn can_not_update_session_without_register() { + new_test_ext().execute_with(|| { + set_block_1(); + + let result = PhalaWapodWorkers::worker_session_update( + Origin::signed(1), + SignedSessionUpdate { + public_key: worker_pubkey(0).0, + update: SessionUpdate { + session: [1; 32], + seed: [1; 32], + reward_receiver: [1; 32].to_vec().into(), + }, + signature: b"valid".to_vec().into(), + }, + ); + + assert_err!(result, Error::::InvalidWorkerPubkey); + }); + } + + #[test] + fn can_update_session_first_time() { + new_test_ext().execute_with(|| { + set_block_1(); + setup_workers(1); + + let result = PhalaWapodWorkers::worker_session_update( + Origin::signed(1), + SignedSessionUpdate { + public_key: worker_pubkey(1).0, + update: SessionUpdate { + session: [1; 32], + seed: [1; 32], + reward_receiver: [1; 32].to_vec().into(), + }, + signature: b"valid".to_vec().into(), + }, + ); + + assert_ok!(result); + + let events = Events::take(); + assert!(events.has(Event::WorkerSessionUpdated { + worker: worker_pubkey(1), + session: [1; 32], + })); + }); + } + + #[test] + fn can_not_update_session_second_time_with_incorrect_nonce() { + new_test_ext().execute_with(|| { + set_block_1(); + setup_workers(1); + + let result = PhalaWapodWorkers::worker_session_update( + Origin::signed(1), + SignedSessionUpdate { + public_key: worker_pubkey(1).0, + update: SessionUpdate { + session: [1; 32], + seed: [1; 32], + reward_receiver: [1; 32].to_vec().into(), + }, + signature: b"valid".to_vec().into(), + }, + ); + + assert_ok!(result); + + let result = PhalaWapodWorkers::worker_session_update( + Origin::signed(1), + SignedSessionUpdate { + public_key: worker_pubkey(1).0, + update: SessionUpdate { + session: [1; 32], + seed: [2; 32], + reward_receiver: [1; 32].to_vec().into(), + }, + signature: b"valid".to_vec().into(), + }, + ); + + assert_err!(result, Error::::OutdatedMessage); + + let last_nonce = WorkerSessions::::get(&worker_pubkey(1)) + .unwrap() + .last_nonce; + let seed = [2; 32]; + + // Can update session with correct nonce. + let result = PhalaWapodWorkers::worker_session_update( + Origin::signed(1), + SignedSessionUpdate { + public_key: worker_pubkey(1).0, + update: SessionUpdate { + session: SessionUpdate::session_from_seed::( + seed, + &last_nonce, + ), + seed, + reward_receiver: [1; 32].to_vec().into(), + }, + signature: b"valid".to_vec().into(), + }, + ); + assert_ok!(result); + }); + } + + #[test] + fn can_not_add_worker_without_price_to_list() { + new_test_ext().execute_with(|| { + set_block_1(); + setup_workers(1); + + let list_id = create_worker_list(); + + let result = PhalaWapodWorkers::worker_list_add_workers( + Origin::signed(1), + list_id, + vec![worker_pubkey(1)].into(), + ); + + assert_err!(result, Error::::WorkerNotFound); + }); + } + + #[test] + fn can_not_add_worker_to_list_when_price_mismatch() { + new_test_ext().execute_with(|| { + set_block_1(); + setup_workers(1); + + let result = PhalaWapodWorkers::worker_description_set( + Origin::signed(1), + SignedWorkerDescription { + worker_pubkey: worker_pubkey(1).0, + worker_description: WorkerDescription { + prices: Prices { + tip_price: Some(1), + ..Default::default() + }, + description: "my worker".to_string().into(), + }, + signature: b"valid".to_vec().into(), + }, + ); + assert_ok!(result); + + let list_id = create_worker_list(); + + let result = PhalaWapodWorkers::worker_list_add_workers( + Origin::signed(1), + list_id, + vec![worker_pubkey(1)].into(), + ); + + assert_err!(result, Error::::PriceMismatch); + }); + } + + #[test] + fn can_add_worker_to_list() { + new_test_ext().execute_with(|| { + set_block_1(); + setup_workers(1); + + let result = PhalaWapodWorkers::worker_description_set( + Origin::signed(1), + SignedWorkerDescription { + worker_pubkey: worker_pubkey(1).0, + worker_description: WorkerDescription { + prices: Prices::default(), + description: "my worker".to_string().into(), + }, + signature: b"valid".to_vec().into(), + }, + ); + assert_ok!(result); + + let list_id = create_worker_list(); + + let result = PhalaWapodWorkers::worker_list_add_workers( + Origin::signed(1), + list_id, + vec![worker_pubkey(1)].into(), + ); + + assert_ok!(result); + + let events = Events::take(); + assert!(events.has(Event::WorkersAddedToList { + list_id, + workers: vec![worker_pubkey(1)].into() + })); + }); + } + + #[test] + fn can_remove_worker_from_list() { + new_test_ext().execute_with(|| { + set_block_1(); + setup_workers(1); + + let result = PhalaWapodWorkers::worker_description_set( + Origin::signed(1), + SignedWorkerDescription { + worker_pubkey: worker_pubkey(1).0, + worker_description: WorkerDescription { + prices: Prices::default(), + description: "my worker".to_string().into(), + }, + signature: b"valid".to_vec().into(), + }, + ); + assert_ok!(result); + + let list_id = create_worker_list(); + + let result = PhalaWapodWorkers::worker_list_add_workers( + Origin::signed(1), + list_id, + vec![worker_pubkey(1)].into(), + ); + assert_ok!(result); + + let result = PhalaWapodWorkers::worker_list_remove_worker( + Origin::signed(1), + list_id, + worker_pubkey(1), + ); + assert_ok!(result); + + let events = Events::take(); + assert!(events.has(Event::WorkerRemovedFromList { + list_id, + worker: worker_pubkey(1) + })); + }); + } + + #[test] + fn can_create_ticket() { + new_test_ext().execute_with(|| { + set_block_1(); + setup_workers(1); + + let list_id = create_worker_list(); + + let result = PhalaWapodWorkers::ticket_create( + Origin::signed(1), + 0, + [1; 32], + "manifest".to_string().into(), + list_id, + Prices::default(), + ); + assert_ok!(result); + + let events = Events::take(); + assert!(events.has(Event::TicketCreated { id: 0 })); + }); + } + + #[test] + fn can_close_ticket() { + new_test_ext().execute_with(|| { + set_block_1(); + setup_workers(1); + + let list_id = create_worker_list(); + + let result = PhalaWapodWorkers::ticket_create( + Origin::signed(1), + 0, + [1; 32], + "manifest".to_string().into(), + list_id, + Prices::default(), + ); + assert_ok!(result); + + let result = PhalaWapodWorkers::ticket_close(Origin::signed(1), 0); + assert_ok!(result); + + let events = Events::take(); + assert!(events.has(Event::TicketClosed { id: 0 })); + }); + } + + #[test] + fn can_settle_ticket() { + new_test_ext().execute_with(|| { + set_block_1(); + + setup_workers(1); + + let gas_price = 1; + let tip_price = 2; + let gas_consumed = 20; + let tip = 10; + let prices = Prices { + gas_price: Some(gas_price), + tip_price: Some(tip_price), + ..Default::default() + }; + let reward = tip as u128 * tip_price + gas_consumed as u128 * gas_price; + let reward_receiver = 42_u64; + let app_address = [2; 32]; + let list_id = setup_worker_list(1, prices); + let claim_map = BoundedVec::from(vec![(app_address, vec![list_id].into())]); + + assert_ok!(PhalaWapodWorkers::worker_session_update( + Origin::signed(1), + SignedSessionUpdate { + public_key: worker_pubkey(1).0, + update: SessionUpdate { + session: [1; 32], + seed: [1; 32], + reward_receiver: reward_receiver.encode().into(), + }, + signature: b"valid".to_vec().into(), + }, + )); + + assert_ok!(PhalaWapodWorkers::ticket_create( + Origin::signed(1), + 100, + app_address, + "manifest".to_string().into(), + list_id, + Prices::default(), + )); + + assert!(WorkerListWorkers::::contains_key( + list_id, + &worker_pubkey(1) + )); + + let result = PhalaWapodWorkers::ticket_settle( + Origin::signed(1), + SignedAppsMetrics { + worker_pubkey: worker_pubkey(1).0, + metrics: VersionedAppsMetrics::V0(AppsMetrics { + token: MetricsToken { + session: [1; 32], + sn: 1, + nonce: [1; 32], + }, + apps: vec![AppMetrics { + address: app_address, + session: [1; 32], + tip, + gas_consumed, + ..Default::default() + }] + .into(), + }), + signature: b"valid".to_vec().into(), + }, + claim_map.clone(), + ); + assert_ok!(result); + + // No payment for the first commit + let events = Events::take(); + let paid = events.find_settlement_for(0, worker_pubkey(1)); + assert_eq!(paid, None); + + let result = PhalaWapodWorkers::ticket_settle( + Origin::signed(1), + SignedAppsMetrics { + worker_pubkey: worker_pubkey(1).0, + metrics: VersionedAppsMetrics::V0(AppsMetrics { + token: MetricsToken { + session: [1; 32], + sn: 2, + nonce: [1; 32], + }, + apps: vec![AppMetrics { + address: app_address, + session: [1; 32], + tip: tip * 2, + gas_consumed: gas_consumed * 2, + ..Default::default() + }] + .into(), + }), + signature: b"valid".to_vec().into(), + }, + claim_map, + ); + assert_ok!(result); + // Should pay for the second commit + let events = Events::take(); + let paid = events.find_settlement_for(0, worker_pubkey(1)); + assert_eq!(paid, Some(reward)); + }); + } + + #[test] + fn can_submit_benchmark_score() { + new_test_ext().execute_with(|| { + set_block_1(); + setup_workers(1); + + let gas_per_second = 500; + let timestamp_secs = 10; + let gas_consumed = gas_per_second * timestamp_secs; + let app_address = [2; 32]; + let receiver = 42u64; + + let metrics_token = MetricsToken { + session: [1; 32], + sn: 1, + nonce: [1; 32], + }; + + // set up the benchmark app + assert_ok!(PhalaWapodWorkers::benchmark_app_set( + Origin::root(), + app_address, + "manifest".to_string().into(), + Fraction { + numerator: 1, + denominator: 10, + }, + )); + + // set up worker session + assert_ok!(PhalaWapodWorkers::worker_session_update( + Origin::signed(1), + SignedSessionUpdate { + public_key: worker_pubkey(1).0, + update: SessionUpdate { + session: [1; 32], + seed: [1; 32], + reward_receiver: receiver.encode().into(), + }, + signature: b"valid".to_vec().into(), + }, + )); + + let message = SignedMessage { + worker_pubkey: worker_pubkey(1).0, + app_address, + signature: b"valid".to_vec().into(), + message: SigningMessage::BenchScore(BenchScore { + gas_per_second, + gas_consumed, + timestamp_secs, + metrics_token, + }), + }; + + let result = PhalaWapodWorkers::benchmark_score_submit( + Origin::signed(1), + true, + message.clone(), + ); + assert_ok!(result); + let init_score = PhalaRegistry::worker_init_score(&worker_pubkey(1)); + assert_eq!(init_score, Some(300)); + + take_events(); + + // simulate a V2 heartbeat + PhalaWapodWorkers::on_worker_event_received(DecodedMessage { + sender: MessageOrigin::Pallet(vec![]), + destination: vec![].into(), + payload: SystemEvent::WorkerEvent(WorkerEventWithKey { + pubkey: worker_pubkey(1), + event: WorkerEvent::Started { + init_p: 1000, + init_v: 2000, + session_id: 1, + }, + }), + }) + .expect("Failed to send mq message"); + + let message = SignedMessage { + worker_pubkey: worker_pubkey(1).0, + app_address, + signature: b"valid".to_vec().into(), + message: SigningMessage::BenchScore(BenchScore { + gas_per_second, + gas_consumed: gas_consumed * 2, + timestamp_secs: timestamp_secs * 2, + metrics_token: MetricsToken { + session: [1; 32], + sn: 2, + nonce: [1; 32], + }, + }), + }; + + assert_ok!(PhalaWapodWorkers::benchmark_score_submit( + Origin::signed(1), + false, + message + )); + // No heartbeat the first time + let events = Events::take(); + assert!(events.find_heartbeat_v3(worker_pubkey(1)).is_none()); + + elapse_seconds(timestamp_secs); + + let message = SignedMessage { + worker_pubkey: worker_pubkey(1).0, + app_address, + signature: b"valid".to_vec().into(), + message: SigningMessage::BenchScore(BenchScore { + gas_per_second, + gas_consumed: gas_consumed * 3, + timestamp_secs: timestamp_secs * 3, + metrics_token: MetricsToken { + session: [1; 32], + sn: 3, + nonce: [1; 32], + }, + }), + }; + assert_ok!(PhalaWapodWorkers::benchmark_score_submit( + Origin::signed(1), + false, + message + )); + let events = Events::take(); + let (iterations, p_instant) = events.find_heartbeat_v3(worker_pubkey(1)).unwrap(); + assert_eq!((iterations, p_instant), (1500, 300)); + }); + } } } From 54f612ffdd08d2a4b990a9527d6084ebfa64c3ec Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Tue, 16 Jul 2024 20:45:13 +0800 Subject: [PATCH 20/25] Use wapod-types from crates.io --- Cargo.lock | 27 +++++++++++++++------------ pallets/phala/Cargo.toml | 4 +--- pallets/phala/src/wapod_workers.rs | 17 +++++------------ 3 files changed, 21 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2276f4000..62d99b2ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2266,7 +2266,7 @@ dependencies = [ [[package]] name = "common" version = "0.1.0" -source = "git+https://github.com/w3f/ring-proof#96137b150288a66bc9e4df495efc64769b5d1321" +source = "git+https://github.com/w3f/ring-proof#626c9598be949aa3dbdd72e8a40531f68b01d6c2" dependencies = [ "ark-ec", "ark-ff", @@ -11970,13 +11970,14 @@ dependencies = [ [[package]] name = "ring" version = "0.1.0" -source = "git+https://github.com/w3f/ring-proof#96137b150288a66bc9e4df495efc64769b5d1321" +source = "git+https://github.com/w3f/ring-proof#626c9598be949aa3dbdd72e8a40531f68b01d6c2" dependencies = [ "ark-ec", "ark-ff", "ark-poly", "ark-serialize", "ark-std", + "arrayvec 0.7.4", "blake2 0.10.6", "common", "fflonk", @@ -15007,7 +15008,7 @@ dependencies = [ [[package]] name = "sp-crypto-ec-utils" version = "0.10.0" -source = "git+https://github.com/paritytech/polkadot-sdk#924728cf19523f826a08e1c0eeee711ca3bb8ee7" +source = "git+https://github.com/paritytech/polkadot-sdk#cde2eb42a6b4ed5e930e59ec4dc03b5fa5059bd5" dependencies = [ "ark-bls12-377", "ark-bls12-377-ext", @@ -15057,7 +15058,7 @@ dependencies = [ [[package]] name = "sp-debug-derive" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#924728cf19523f826a08e1c0eeee711ca3bb8ee7" +source = "git+https://github.com/paritytech/polkadot-sdk#cde2eb42a6b4ed5e930e59ec4dc03b5fa5059bd5" dependencies = [ "proc-macro2", "quote", @@ -15090,7 +15091,7 @@ dependencies = [ [[package]] name = "sp-externalities" version = "0.25.0" -source = "git+https://github.com/paritytech/polkadot-sdk#924728cf19523f826a08e1c0eeee711ca3bb8ee7" +source = "git+https://github.com/paritytech/polkadot-sdk#cde2eb42a6b4ed5e930e59ec4dc03b5fa5059bd5" dependencies = [ "environmental", "parity-scale-codec", @@ -15309,7 +15310,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface" version = "24.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#924728cf19523f826a08e1c0eeee711ca3bb8ee7" +source = "git+https://github.com/paritytech/polkadot-sdk#cde2eb42a6b4ed5e930e59ec4dc03b5fa5059bd5" dependencies = [ "bytes", "impl-trait-for-tuples", @@ -15354,7 +15355,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "17.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#924728cf19523f826a08e1c0eeee711ca3bb8ee7" +source = "git+https://github.com/paritytech/polkadot-sdk#cde2eb42a6b4ed5e930e59ec4dc03b5fa5059bd5" dependencies = [ "Inflector", "expander", @@ -15452,7 +15453,7 @@ checksum = "54c78c5a66682568cc7b153603c5d01a2cc8f5c221c7b1e921517a0eef18ae05" [[package]] name = "sp-std" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#924728cf19523f826a08e1c0eeee711ca3bb8ee7" +source = "git+https://github.com/paritytech/polkadot-sdk#cde2eb42a6b4ed5e930e59ec4dc03b5fa5059bd5" [[package]] name = "sp-storage" @@ -15484,7 +15485,7 @@ dependencies = [ [[package]] name = "sp-storage" version = "19.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#924728cf19523f826a08e1c0eeee711ca3bb8ee7" +source = "git+https://github.com/paritytech/polkadot-sdk#cde2eb42a6b4ed5e930e59ec4dc03b5fa5059bd5" dependencies = [ "impl-serde", "parity-scale-codec", @@ -15534,7 +15535,7 @@ dependencies = [ [[package]] name = "sp-tracing" version = "16.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#924728cf19523f826a08e1c0eeee711ca3bb8ee7" +source = "git+https://github.com/paritytech/polkadot-sdk#cde2eb42a6b4ed5e930e59ec4dc03b5fa5059bd5" dependencies = [ "parity-scale-codec", "tracing", @@ -15649,7 +15650,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" version = "20.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#924728cf19523f826a08e1c0eeee711ca3bb8ee7" +source = "git+https://github.com/paritytech/polkadot-sdk#cde2eb42a6b4ed5e930e59ec4dc03b5fa5059bd5" dependencies = [ "impl-trait-for-tuples", "log", @@ -17909,7 +17910,9 @@ dependencies = [ [[package]] name = "wapod-types" -version = "0.1.0" +version = "0.1.0-dev.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1af243243426435872a873bb893bbbbc4865caa88d6d4c8856d717a3fcd7094" dependencies = [ "parity-scale-codec", "scale-info", diff --git a/pallets/phala/Cargo.toml b/pallets/phala/Cargo.toml index 53d3ac08d..c4f478b8b 100644 --- a/pallets/phala/Cargo.toml +++ b/pallets/phala/Cargo.toml @@ -47,9 +47,7 @@ fixed-sqrt = { version = "0.2", default-features = false } sgx-attestation = { path = "../../crates/sgx-attestation", default-features = false, features = ["verify"] } -[dependencies.wapod-types] -path = "../../../wapo/wapod-types/" -default-features = false +wapod-types = { version = "0.1.0-dev.0", default-features = false } [dev-dependencies] frame-support-test = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "release-polkadot-v1.5.0" } diff --git a/pallets/phala/src/wapod_workers.rs b/pallets/phala/src/wapod_workers.rs index 32302b20d..81919d2ed 100644 --- a/pallets/phala/src/wapod_workers.rs +++ b/pallets/phala/src/wapod_workers.rs @@ -27,10 +27,7 @@ pub mod pallet { use wapod_types::{ bench_app::{BenchScore, SignedMessage, SigningMessage}, crypto::{verify::Verifiable, CryptoProvider}, - metrics::{ - AppMetrics, AppsMetrics, ClaimMap, MetricsToken, SignedAppsMetrics, - VersionedAppsMetrics, - }, + metrics::{ClaimMap, MetricsToken, SignedAppsMetrics, VersionedAppsMetrics}, primitives::{BoundedString, BoundedVec}, session::{SessionUpdate, SignedSessionUpdate}, ticket::{Balance, Prices, SignedWorkerDescription, WorkerDescription}, @@ -768,7 +765,6 @@ pub mod pallet { return Ok(()); } let delta_iterations = iterations - computation_state.last_iterations; - let iter_per_sec = delta_iterations / delta_time as u64; let p_instant = delta_iterations / delta_time as u64 * 6; let p_max = p_init * 120 / 100; let p_instant = p_instant.min(p_max) as u32; @@ -992,22 +988,19 @@ pub mod pallet { mod tests { use super::*; use crate::mock::{ - ecdh_pubkey, elapse_seconds, new_test_ext, set_block_1, take_events, take_messages, - worker_pubkey, BlockNumber, MockCrypto, RuntimeEvent as TestEvent, + ecdh_pubkey, elapse_seconds, new_test_ext, set_block_1, take_events, worker_pubkey, + MockCrypto, PhalaRegistry, PhalaWapodWorkers, RuntimeEvent as TestEvent, RuntimeOrigin as Origin, Test, }; // Pallets - use crate::mock::{PhalaComputation, PhalaRegistry, PhalaWapodWorkers, System}; use frame_support::{assert_err, assert_ok}; use phala_types::messaging::WorkerEventWithKey; use wapod_types::{ bench_app::{BenchScore, SignedMessage, SigningMessage}, - crypto::{verify::Verifiable, CryptoProvider}, metrics::{ - AppMetrics, AppsMetrics, ClaimMap, MetricsToken, SignedAppsMetrics, - VersionedAppsMetrics, + AppMetrics, AppsMetrics, MetricsToken, SignedAppsMetrics, VersionedAppsMetrics, }, - primitives::{BoundedString, BoundedVec}, + primitives::BoundedVec, session::{SessionUpdate, SignedSessionUpdate}, ticket::{Balance, Prices, SignedWorkerDescription, WorkerDescription}, }; From 9d0e8ed8661de7836b75dd4a4222f9b8f899956d Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Tue, 16 Jul 2024 21:56:44 +0800 Subject: [PATCH 21/25] Fix compilation error --- standalone/pruntime/Cargo.lock | 4 +++- standalone/runtime/src/lib.rs | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/standalone/pruntime/Cargo.lock b/standalone/pruntime/Cargo.lock index 20ee4aec3..26d879e0c 100644 --- a/standalone/pruntime/Cargo.lock +++ b/standalone/pruntime/Cargo.lock @@ -10571,7 +10571,9 @@ dependencies = [ [[package]] name = "wapod-types" -version = "0.1.0" +version = "0.1.0-dev.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1af243243426435872a873bb893bbbbc4865caa88d6d4c8856d717a3fcd7094" dependencies = [ "parity-scale-codec", "scale-info", diff --git a/standalone/runtime/src/lib.rs b/standalone/runtime/src/lib.rs index 7ecceb987..85c6ec8ca 100644 --- a/standalone/runtime/src/lib.rs +++ b/standalone/runtime/src/lib.rs @@ -1532,6 +1532,7 @@ impl pallet_phat_tokenomic::Config for Runtime { impl pallet_wapod_workers::Config for Runtime { type RuntimeEvent = RuntimeEvent; + type Crypto = pallet_wapod_workers::SpCrypto; } parameter_types! { From 0b1dc925a3f7a5aa42275c1e0eed95836e7c73c0 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Tue, 16 Jul 2024 22:54:57 +0800 Subject: [PATCH 22/25] Fix test failures --- ..._show_type_changes_that_affect_the_checkpoint.snap | 11 +++++++++-- .../snapshots/phala_types__tests__dump_type_info.snap | 11 +++++++++-- pallets/phala/src/test.rs | 2 +- pallets/phala/src/wapod_workers.rs | 8 ++++---- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/crates/phactory/src/snapshots/phactory__show_type_changes_that_affect_the_checkpoint.snap b/crates/phactory/src/snapshots/phactory__show_type_changes_that_affect_the_checkpoint.snap index cb169a356..2fbc24b86 100644 --- a/crates/phactory/src/snapshots/phactory__show_type_changes_that_affect_the_checkpoint.snap +++ b/crates/phactory/src/snapshots/phactory__show_type_changes_that_affect_the_checkpoint.snap @@ -1,6 +1,6 @@ --- source: crates/phactory/src/lib.rs -assertion_line: 365 +assertion_line: 382 expression: "type_info_stringify::>()" --- Option = enum { @@ -398,6 +398,9 @@ phala_types::messaging::GatekeeperEvent = enum { [2]_RepairV, [3]_PhalaLaunched, [4]_UnrespFix, + [5]SetStaticV { + enabled: bool, + } } phala_types::messaging::RandomNumberEvent = struct { block_number: u32, @@ -460,6 +463,11 @@ phala_types::messaging::WorkingReportEvent = enum { n_clusters: u32, n_contracts: u32, } + [2]HeartbeatV3 { + session_id: u32, + iterations: u64, + p_instant: u32, + } } BTreeMap = struct { : Vec<(sp_core::sr25519::Public, phactory::system::gk::WorkerInfo)>, @@ -550,4 +558,3 @@ phactory::Phactory = struct { system: Option>, netconfig: Option, } - diff --git a/crates/phala-types/src/snapshots/phala_types__tests__dump_type_info.snap b/crates/phala-types/src/snapshots/phala_types__tests__dump_type_info.snap index 75ba3e903..bd5042482 100644 --- a/crates/phala-types/src/snapshots/phala_types__tests__dump_type_info.snap +++ b/crates/phala-types/src/snapshots/phala_types__tests__dump_type_info.snap @@ -1,6 +1,6 @@ --- source: crates/phala-types/src/lib.rs -assertion_line: 929 +assertion_line: 935 expression: "type_info_stringify::()" --- phala_types::messaging::CommandPayload = enum { @@ -57,6 +57,11 @@ phala_types::messaging::WorkingReportEvent = enum { n_clusters: u32, n_contracts: u32, } + [2]HeartbeatV3 { + session_id: u32, + iterations: u64, + p_instant: u32, + } } phala_types::messaging::WorkingInfoUpdateEvent = struct { block_number: u32, @@ -134,6 +139,9 @@ phala_types::messaging::GatekeeperEvent = enum { [2]_RepairV, [3]_PhalaLaunched, [4]_UnrespFix, + [5]SetStaticV { + enabled: bool, + } } phala_types::messaging::RandomNumberEvent = struct { block_number: u32, @@ -318,4 +326,3 @@ phala_types::tests::TestData = struct { payout_reason: phala_types::PayoutReason, slash_info: phala_types::StashInfo, } - diff --git a/pallets/phala/src/test.rs b/pallets/phala/src/test.rs index e3af298ff..ea00cca98 100644 --- a/pallets/phala/src/test.rs +++ b/pallets/phala/src/test.rs @@ -889,7 +889,7 @@ fn test_add_worker() { assert_ok!(PhalaStakePoolv2::create(RuntimeOrigin::signed(1))); assert_noop!( PhalaStakePoolv2::add_worker(RuntimeOrigin::signed(1), 1, worker1), - stake_pool_v2::Error::::FailedToBindSessionAndWorker + computation::Error::::DuplicateBoundWorker ); }); } diff --git a/pallets/phala/src/wapod_workers.rs b/pallets/phala/src/wapod_workers.rs index 81919d2ed..fa3cc513b 100644 --- a/pallets/phala/src/wapod_workers.rs +++ b/pallets/phala/src/wapod_workers.rs @@ -523,7 +523,7 @@ pub mod pallet { address: Address, manifest_cid: BoundedString<128>, worker_list: ListId, - prices: Prices, + prices: Box, ) -> DispatchResult { let owner = ensure_signed(origin)?; let Some(list_info) = WorkerLists::::get(worker_list) else { @@ -1430,7 +1430,7 @@ pub mod pallet { [1; 32], "manifest".to_string().into(), list_id, - Prices::default(), + Default::default(), ); assert_ok!(result); @@ -1453,7 +1453,7 @@ pub mod pallet { [1; 32], "manifest".to_string().into(), list_id, - Prices::default(), + Default::default(), ); assert_ok!(result); @@ -1506,7 +1506,7 @@ pub mod pallet { app_address, "manifest".to_string().into(), list_id, - Prices::default(), + Default::default(), )); assert!(WorkerListWorkers::::contains_key( From 869aaf6eade09ceda3e6f2db374644655327c5a6 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Tue, 16 Jul 2024 23:02:44 +0800 Subject: [PATCH 23/25] Fix clippy --- pallets/phala/src/registry.rs | 2 +- pallets/phala/src/wapod_workers.rs | 66 ++++++++++++++---------------- 2 files changed, 32 insertions(+), 36 deletions(-) diff --git a/pallets/phala/src/registry.rs b/pallets/phala/src/registry.rs index f818f9456..84b9961e8 100644 --- a/pallets/phala/src/registry.rs +++ b/pallets/phala/src/registry.rs @@ -981,7 +981,7 @@ pub mod pallet { let score = iterations / ((now - start_time) / 1000); let score = score * 6; // iterations per 6s - Self::update_worker_init_score(&worker_pubkey, score); + Self::update_worker_init_score(worker_pubkey, score); } RegistryEvent::MasterPubkey { master_pubkey } => { let gatekeepers = Gatekeeper::::get(); diff --git a/pallets/phala/src/wapod_workers.rs b/pallets/phala/src/wapod_workers.rs index fa3cc513b..56e613dc3 100644 --- a/pallets/phala/src/wapod_workers.rs +++ b/pallets/phala/src/wapod_workers.rs @@ -354,7 +354,7 @@ pub mod pallet { let worker_pubkey = WorkerPublicKey(signed_description.worker_pubkey); // Worker price can only be set once ensure!( - !WorkerDescriptions::::contains_key(&worker_pubkey), + !WorkerDescriptions::::contains_key(worker_pubkey), Error::::NotAllowed ); ensure!( @@ -365,7 +365,7 @@ pub mod pallet { signed_description.verify::(), Error::::SignatureVerificationFailed ); - WorkerDescriptions::::insert(&worker_pubkey, signed_description.worker_description); + WorkerDescriptions::::insert(worker_pubkey, signed_description.worker_description); Self::deposit_event(Event::WorkerDescriptionSet { worker: worker_pubkey, }); @@ -396,7 +396,7 @@ pub mod pallet { Error::::InvalidWorkerPubkey ); let update = update.update; - if let Some(session) = WorkerSessions::::get(&worker_pubkey) { + if let Some(session) = WorkerSessions::::get(worker_pubkey) { let computed_session = SessionUpdate::session_from_seed::(update.seed, &session.last_nonce); ensure!( @@ -441,11 +441,11 @@ pub mod pallet { ) -> DispatchResult { let owner = ensure_signed(origin.clone())?; let id = Self::add_worker_list(WorkerListInfo { - owner: owner.into(), + owner, prices, description, }); - if init_workers.len() > 0 { + if !init_workers.is_empty() { Self::worker_list_add_workers(origin, id, init_workers)?; } Ok(()) @@ -465,7 +465,7 @@ pub mod pallet { ) -> DispatchResult { let owner = ensure_signed(origin)?; let list_info = WorkerLists::::get(list_id).ok_or(Error::::WorkerListNotFound)?; - ensure!(owner == list_info.owner.into(), Error::::NotAllowed); + ensure!(owner == list_info.owner, Error::::NotAllowed); for worker in workers.iter() { let Some(worker_info) = WorkerDescriptions::::get(worker) else { return Err(Error::::WorkerNotFound.into()); @@ -494,7 +494,7 @@ pub mod pallet { ) -> DispatchResult { let owner = ensure_signed(origin)?; let list_info = WorkerLists::::get(list_id).ok_or(Error::::WorkerListNotFound)?; - ensure!(owner == list_info.owner.into(), Error::::NotAllowed); + ensure!(owner == list_info.owner, Error::::NotAllowed); WorkerListWorkers::::remove(list_id, worker); Self::deposit_event(Event::WorkerRemovedFromList { list_id, worker }); Ok(()) @@ -604,7 +604,7 @@ pub mod pallet { let worker_info = { // ensure the session matches let MetricsToken { session, sn, nonce } = all_metrics.token; - let Some(mut session_info) = WorkerSessions::::get(&worker_pubkey) else { + let Some(mut session_info) = WorkerSessions::::get(worker_pubkey) else { return Err(Error::::WorkerNotFound.into()); }; ensure!( @@ -617,7 +617,7 @@ pub mod pallet { ); session_info.last_nonce = nonce; session_info.last_metrics_sn = sn; - WorkerSessions::::insert(&worker_pubkey, &session_info); + WorkerSessions::::insert(worker_pubkey, &session_info); session_info }; @@ -646,14 +646,14 @@ pub mod pallet { WorkerSet::Any => (), WorkerSet::WorkerList(list_id) => { ensure!( - WorkerListWorkers::::contains_key(list_id, &worker_pubkey), + WorkerListWorkers::::contains_key(list_id, worker_pubkey), Error::::NotAllowed ); } } let mut settlement = - TicketSettlementInfo::::get(ticket_id, &worker_pubkey); + TicketSettlementInfo::::get(ticket_id, worker_pubkey); // Pay out and update the settlement infomation let cost = ticket.prices.cost_of(&metrics).into(); @@ -667,7 +667,7 @@ pub mod pallet { let transfer_result = ::Currency::transfer( &ticket_account, &worker_info.reward_receiver, - pay_out.into(), + pay_out, KeepAlive, ); match transfer_result { @@ -678,8 +678,8 @@ pub mod pallet { Self::deposit_event(Event::Settled { ticket_id: *ticket_id, worker: worker_pubkey, - paid: pay_out.into(), - session_cost: cost.into(), + paid: pay_out, + session_cost: cost, paid_to: worker_info.reward_receiver.clone(), }); } @@ -687,13 +687,13 @@ pub mod pallet { Self::deposit_event(Event::SettleFailed { ticket_id: *ticket_id, worker: worker_pubkey, - paid: pay_out.into(), - session_cost: cost.into(), + paid: pay_out, + session_cost: cost, }); } } } - TicketSettlementInfo::::insert(ticket_id, &worker_pubkey, settlement); + TicketSettlementInfo::::insert(ticket_id, worker_pubkey, settlement); } } } @@ -727,7 +727,7 @@ pub mod pallet { Error::::InvalidWorkerPubkey ); let bench_app_info = - BenchmarkApps::::get(&message.app_address).ok_or(Error::::InvalidBenchApp)?; + BenchmarkApps::::get(message.app_address).ok_or(Error::::InvalidBenchApp)?; match message.message { SigningMessage::BenchScore(BenchScore { gas_per_second, @@ -751,7 +751,7 @@ pub mod pallet { let score = iterations_per_sec.saturating_mul(6); registry::Pallet::::update_worker_init_score(&worker_pubkey, score); } else if let Some(mut computation_state) = - ComputationWorkers::::get(&worker_pubkey) + ComputationWorkers::::get(worker_pubkey) { // If the worker is scheduled computing by the chain, simulate a heartbeat message. let p_init = @@ -761,14 +761,14 @@ pub mod pallet { let delta_time = now - computation_state.last_update_time; if delta_time <= 0 { computation_state.last_iterations = iterations; - ComputationWorkers::::insert(&worker_pubkey, computation_state); + ComputationWorkers::::insert(worker_pubkey, computation_state); return Ok(()); } let delta_iterations = iterations - computation_state.last_iterations; let p_instant = delta_iterations / delta_time as u64 * 6; let p_max = p_init * 120 / 100; let p_instant = p_instant.min(p_max) as u32; - let worker = MessageOrigin::Worker(worker_pubkey.into()); + let worker = MessageOrigin::Worker(worker_pubkey); // Minic the worker heartbeat message let worker_report = WorkingReportEvent::HeartbeatV3 { @@ -786,7 +786,7 @@ pub mod pallet { computation_state.last_iterations = iterations; computation_state.last_update_time = now; - ComputationWorkers::::insert(&worker_pubkey, computation_state); + ComputationWorkers::::insert(worker_pubkey, computation_state); } } }; @@ -932,7 +932,7 @@ pub mod pallet { WorkerEvent::BenchScore(_) => (), WorkerEvent::Started { session_id, .. } => { ComputationWorkers::::insert( - &worker_pubkey, + worker_pubkey, ComputationState { session_id, unresponsive: false, @@ -942,17 +942,17 @@ pub mod pallet { ); } WorkerEvent::Stopped => { - ComputationWorkers::::remove(&worker_pubkey); + ComputationWorkers::::remove(worker_pubkey); } WorkerEvent::EnterUnresponsive => { - ComputationWorkers::::mutate(&worker_pubkey, |state| { + ComputationWorkers::::mutate(worker_pubkey, |state| { if let Some(state) = state { state.unresponsive = true; } }); } WorkerEvent::ExitUnresponsive => { - ComputationWorkers::::mutate(&worker_pubkey, |state| { + ComputationWorkers::::mutate(worker_pubkey, |state| { if let Some(state) = state { state.unresponsive = false; } @@ -1108,17 +1108,13 @@ pub mod pallet { let result = PhalaWapodWorkers::worker_list_add_workers( Origin::signed(1), list_id, - (1..=n) - .into_iter() - .map(worker_pubkey) - .collect::>() - .into(), + (1..=n).map(worker_pubkey).collect::>().into(), ); assert_ok!(result); for id in 1..=n { assert!(WorkerListWorkers::::contains_key( list_id, - &worker_pubkey(id) + worker_pubkey(id) )) } list_id @@ -1259,7 +1255,7 @@ pub mod pallet { assert_err!(result, Error::::OutdatedMessage); - let last_nonce = WorkerSessions::::get(&worker_pubkey(1)) + let last_nonce = WorkerSessions::::get(worker_pubkey(1)) .unwrap() .last_nonce; let seed = [2; 32]; @@ -1368,7 +1364,7 @@ pub mod pallet { let events = Events::take(); assert!(events.has(Event::WorkersAddedToList { list_id, - workers: vec![worker_pubkey(1)].into() + workers: vec![worker_pubkey(1)], })); }); } @@ -1511,7 +1507,7 @@ pub mod pallet { assert!(WorkerListWorkers::::contains_key( list_id, - &worker_pubkey(1) + worker_pubkey(1) )); let result = PhalaWapodWorkers::ticket_settle( From 94e59d2b4509ccac9c1be0305973eeacd1d08e87 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Wed, 17 Jul 2024 09:54:38 +0800 Subject: [PATCH 24/25] Fix CI error --- pallets/phala/src/wapod_workers.rs | 1 + standalone/prouter/Cargo.lock | 186 ++++++++++++++++------------- standalone/prouter/Cargo.toml | 1 + 3 files changed, 108 insertions(+), 80 deletions(-) diff --git a/pallets/phala/src/wapod_workers.rs b/pallets/phala/src/wapod_workers.rs index 56e613dc3..af6627e44 100644 --- a/pallets/phala/src/wapod_workers.rs +++ b/pallets/phala/src/wapod_workers.rs @@ -11,6 +11,7 @@ pub mod pallet { use crate::{mq, registry, PhalaConfig}; use alloc::collections::BTreeMap; use alloc::vec::Vec; + use alloc::boxed::Box; use frame_support::{ dispatch::DispatchResult, ensure, diff --git a/standalone/prouter/Cargo.lock b/standalone/prouter/Cargo.lock index 8150d6f27..61c84be63 100644 --- a/standalone/prouter/Cargo.lock +++ b/standalone/prouter/Cargo.lock @@ -510,7 +510,7 @@ checksum = "7b2d0f03b3640e3a630367e40c468cb7f309529c708ed1d88597047b0e7c6ef7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -676,7 +676,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.43", + "syn 2.0.71", "which", ] @@ -1400,7 +1400,7 @@ checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -1448,7 +1448,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.10.0", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -1470,7 +1470,7 @@ checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a" dependencies = [ "darling_core 0.20.1", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -1499,7 +1499,7 @@ checksum = "5fe87ce4529967e0ba1dcf8450bab64d97dfd5010a6256187ffe2e43e6f0e049" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -1643,7 +1643,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.43", + "syn 2.0.71", "termcolor", "toml 0.8.2", "walkdir", @@ -1802,7 +1802,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -1822,7 +1822,7 @@ checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -2019,7 +2019,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "syn 2.0.43", + "syn 2.0.71", "toml 0.7.6", "walkdir", ] @@ -2037,7 +2037,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -2063,7 +2063,7 @@ dependencies = [ "serde", "serde_json", "strum 0.25.0", - "syn 2.0.43", + "syn 2.0.71", "tempfile", "thiserror", "tiny-keccak", @@ -2214,7 +2214,7 @@ dependencies = [ "fs-err", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -2442,10 +2442,10 @@ name = "frame-election-provider-solution-type" version = "4.0.0-dev" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#789ffb66dcfcf3b54a1e6786e928ac91c4fdb465" dependencies = [ - "proc-macro-crate 2.0.1", + "proc-macro-crate 2.0.2", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -2564,7 +2564,7 @@ dependencies = [ "proc-macro2", "quote", "sp-core-hashing", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -2573,10 +2573,10 @@ version = "4.0.0-dev" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#789ffb66dcfcf3b54a1e6786e928ac91c4fdb465" dependencies = [ "frame-support-procedural-tools-derive", - "proc-macro-crate 2.0.1", + "proc-macro-crate 2.0.2", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -2586,7 +2586,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polk dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -2740,7 +2740,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -3202,7 +3202,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.9", + "socket2 0.5.6", "tokio", "tower-service", "tracing", @@ -3784,7 +3784,7 @@ dependencies = [ "macro_magic_core", "macro_magic_macros", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -3798,7 +3798,7 @@ dependencies = [ "macro_magic_core_macros", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -3809,7 +3809,7 @@ checksum = "9ea73aa640dc01d62a590d48c0c3521ed739d53b27f919b25c3551e233481654" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -3820,7 +3820,7 @@ checksum = "ef9d79ae96aaba821963320eb2b6e34d17df1e5a83d8a1985c29cc5be59577b3" dependencies = [ "macro_magic_core", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -4110,7 +4110,7 @@ dependencies = [ "proc-macro-crate 1.2.1", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -4869,10 +4869,10 @@ name = "pallet-staking-reward-curve" version = "4.0.0-dev" source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0#789ffb66dcfcf3b54a1e6786e928ac91c4fdb465" dependencies = [ - "proc-macro-crate 2.0.1", + "proc-macro-crate 2.0.2", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -5025,9 +5025,9 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.6.5" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dec8a8073036902368c2cdc0387e85ff9a37054d7e7c98e592145e0c92cd4fb" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" dependencies = [ "arrayvec 0.7.2", "bitvec 1.0.1", @@ -5040,11 +5040,11 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.5" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312270ee71e1cd70289dacf597cab7b207aa107d2f28191c2ae45b2ece18a260" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate 1.2.1", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -5233,7 +5233,6 @@ dependencies = [ "log", "parity-scale-codec", "phala-crypto", - "phala-git-revision", "phala-node-runtime", "phala-trie-storage", "phala-types", @@ -5262,10 +5261,6 @@ dependencies = [ "sp-core", ] -[[package]] -name = "phala-git-revision" -version = "0.1.0" - [[package]] name = "phala-mq" version = "0.1.0" @@ -5405,10 +5400,12 @@ dependencies = [ "serde", "serde_json", "sgx-attestation", + "sp-api", "sp-core", "sp-io", "sp-runtime", "sp-std 8.0.0 (git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polkadot-v1.5.0)", + "wapod-types", ] [[package]] @@ -5534,7 +5531,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -5573,7 +5570,7 @@ checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -5657,7 +5654,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9825a04601d60621feed79c4e6b56d65db77cdca55cef43b46b0de1096d1c282" dependencies = [ "proc-macro2", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -5687,14 +5684,21 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a" +version = "2.0.2" +source = "git+https://github.com/kvinwang/proc-macro-crate?branch=update-toml#758987cc8f582405f07364dd536142abd5f4da55" dependencies = [ - "toml_datetime", "toml_edit 0.20.2", ] +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit 0.21.1", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -5733,14 +5737,14 @@ checksum = "834da187cfe638ae8abb0203f0b33e5ccdb02a28e7199f2f47b3e2754f50edca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -5924,9 +5928,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.33" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -6631,9 +6635,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.10.0" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7d66a1128282b7ef025a8ead62a4a9fcf017382ec53b8ffbf4d7bf77bd3c60" +checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" dependencies = [ "bitvec 1.0.1", "cfg-if", @@ -6645,11 +6649,11 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.10.0" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" +checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" dependencies = [ - "proc-macro-crate 1.2.1", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -6844,22 +6848,22 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -7173,10 +7177,10 @@ dependencies = [ "Inflector", "blake2", "expander", - "proc-macro-crate 2.0.1", + "proc-macro-crate 2.0.2", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -7363,7 +7367,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polk dependencies = [ "quote", "sp-core-hashing", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -7394,7 +7398,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polk dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -7404,7 +7408,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk#b4c816665bd094b6ad703f1 dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -7613,10 +7617,10 @@ source = "git+https://github.com/paritytech/polkadot-sdk.git?branch=release-polk dependencies = [ "Inflector", "expander", - "proc-macro-crate 2.0.1", + "proc-macro-crate 2.0.2", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -7626,10 +7630,10 @@ source = "git+https://github.com/paritytech/polkadot-sdk#b4c816665bd094b6ad703f1 dependencies = [ "Inflector", "expander", - "proc-macro-crate 2.0.1", + "proc-macro-crate 2.0.2", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -7814,7 +7818,7 @@ dependencies = [ "parity-scale-codec", "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -7997,7 +8001,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -8064,7 +8068,7 @@ dependencies = [ "quote", "scale-info", "subxt-metadata", - "syn 2.0.43", + "syn 2.0.71", "thiserror", "tokio", ] @@ -8076,7 +8080,7 @@ dependencies = [ "darling 0.20.1", "proc-macro-error", "subxt-codegen", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -8123,9 +8127,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.43" +version = "2.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53" +checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" dependencies = [ "proc-macro2", "quote", @@ -8275,7 +8279,7 @@ checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -8365,7 +8369,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -8477,9 +8481,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" dependencies = [ "serde", ] @@ -8510,6 +8514,17 @@ dependencies = [ "winnow", ] +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap 2.0.0", + "toml_datetime", + "winnow", +] + [[package]] name = "tower-service" version = "0.3.2" @@ -8536,7 +8551,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.43", + "syn 2.0.71", ] [[package]] @@ -8912,6 +8927,17 @@ dependencies = [ "try-lock", ] +[[package]] +name = "wapod-types" +version = "0.1.0-dev.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1af243243426435872a873bb893bbbbc4865caa88d6d4c8856d717a3fcd7094" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", +] + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" diff --git a/standalone/prouter/Cargo.toml b/standalone/prouter/Cargo.toml index 1d593882c..94af15cbd 100644 --- a/standalone/prouter/Cargo.toml +++ b/standalone/prouter/Cargo.toml @@ -34,3 +34,4 @@ bindgen = "0.66" [patch.crates-io] # TODO.kevin: Move back to crates.io once it released 1.0 derive_more = { version = "0.99.17", git = "https://github.com/JelteF/derive_more" } +proc-macro-crate = { git = "https://github.com/kvinwang/proc-macro-crate", branch = "update-toml" } From e0db74346dfb4abd24d87fdaee18a96b6109745f Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Wed, 17 Jul 2024 12:27:25 +0800 Subject: [PATCH 25/25] Update dep wapod-types --- Cargo.lock | 22 ++++---- pallets/phala/Cargo.toml | 2 +- pallets/phala/src/wapod_workers.rs | 82 +++++++++++++++--------------- standalone/pruntime/Cargo.lock | 4 +- 4 files changed, 55 insertions(+), 55 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 62d99b2ed..2360fd812 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15008,7 +15008,7 @@ dependencies = [ [[package]] name = "sp-crypto-ec-utils" version = "0.10.0" -source = "git+https://github.com/paritytech/polkadot-sdk#cde2eb42a6b4ed5e930e59ec4dc03b5fa5059bd5" +source = "git+https://github.com/paritytech/polkadot-sdk#975e04bbb59b643362f918e8521f0cde5c27fbc8" dependencies = [ "ark-bls12-377", "ark-bls12-377-ext", @@ -15058,7 +15058,7 @@ dependencies = [ [[package]] name = "sp-debug-derive" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#cde2eb42a6b4ed5e930e59ec4dc03b5fa5059bd5" +source = "git+https://github.com/paritytech/polkadot-sdk#975e04bbb59b643362f918e8521f0cde5c27fbc8" dependencies = [ "proc-macro2", "quote", @@ -15091,7 +15091,7 @@ dependencies = [ [[package]] name = "sp-externalities" version = "0.25.0" -source = "git+https://github.com/paritytech/polkadot-sdk#cde2eb42a6b4ed5e930e59ec4dc03b5fa5059bd5" +source = "git+https://github.com/paritytech/polkadot-sdk#975e04bbb59b643362f918e8521f0cde5c27fbc8" dependencies = [ "environmental", "parity-scale-codec", @@ -15310,7 +15310,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface" version = "24.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#cde2eb42a6b4ed5e930e59ec4dc03b5fa5059bd5" +source = "git+https://github.com/paritytech/polkadot-sdk#975e04bbb59b643362f918e8521f0cde5c27fbc8" dependencies = [ "bytes", "impl-trait-for-tuples", @@ -15355,7 +15355,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "17.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#cde2eb42a6b4ed5e930e59ec4dc03b5fa5059bd5" +source = "git+https://github.com/paritytech/polkadot-sdk#975e04bbb59b643362f918e8521f0cde5c27fbc8" dependencies = [ "Inflector", "expander", @@ -15453,7 +15453,7 @@ checksum = "54c78c5a66682568cc7b153603c5d01a2cc8f5c221c7b1e921517a0eef18ae05" [[package]] name = "sp-std" version = "14.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#cde2eb42a6b4ed5e930e59ec4dc03b5fa5059bd5" +source = "git+https://github.com/paritytech/polkadot-sdk#975e04bbb59b643362f918e8521f0cde5c27fbc8" [[package]] name = "sp-storage" @@ -15485,7 +15485,7 @@ dependencies = [ [[package]] name = "sp-storage" version = "19.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#cde2eb42a6b4ed5e930e59ec4dc03b5fa5059bd5" +source = "git+https://github.com/paritytech/polkadot-sdk#975e04bbb59b643362f918e8521f0cde5c27fbc8" dependencies = [ "impl-serde", "parity-scale-codec", @@ -15535,7 +15535,7 @@ dependencies = [ [[package]] name = "sp-tracing" version = "16.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#cde2eb42a6b4ed5e930e59ec4dc03b5fa5059bd5" +source = "git+https://github.com/paritytech/polkadot-sdk#975e04bbb59b643362f918e8521f0cde5c27fbc8" dependencies = [ "parity-scale-codec", "tracing", @@ -15650,7 +15650,7 @@ dependencies = [ [[package]] name = "sp-wasm-interface" version = "20.0.0" -source = "git+https://github.com/paritytech/polkadot-sdk#cde2eb42a6b4ed5e930e59ec4dc03b5fa5059bd5" +source = "git+https://github.com/paritytech/polkadot-sdk#975e04bbb59b643362f918e8521f0cde5c27fbc8" dependencies = [ "impl-trait-for-tuples", "log", @@ -17910,9 +17910,9 @@ dependencies = [ [[package]] name = "wapod-types" -version = "0.1.0-dev.0" +version = "0.1.0-dev.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1af243243426435872a873bb893bbbbc4865caa88d6d4c8856d717a3fcd7094" +checksum = "2e15d1f0f6fc295d001a38335e013f18d887c968de19d3ed5a4e7e3e5efbdc60" dependencies = [ "parity-scale-codec", "scale-info", diff --git a/pallets/phala/Cargo.toml b/pallets/phala/Cargo.toml index c4f478b8b..a9aeeff09 100644 --- a/pallets/phala/Cargo.toml +++ b/pallets/phala/Cargo.toml @@ -47,7 +47,7 @@ fixed-sqrt = { version = "0.2", default-features = false } sgx-attestation = { path = "../../crates/sgx-attestation", default-features = false, features = ["verify"] } -wapod-types = { version = "0.1.0-dev.0", default-features = false } +wapod-types = { version = "0.1.0-dev.1", default-features = false } [dev-dependencies] frame-support-test = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "release-polkadot-v1.5.0" } diff --git a/pallets/phala/src/wapod_workers.rs b/pallets/phala/src/wapod_workers.rs index af6627e44..302d96d60 100644 --- a/pallets/phala/src/wapod_workers.rs +++ b/pallets/phala/src/wapod_workers.rs @@ -9,9 +9,9 @@ pub use self::pallet::*; pub mod pallet { // MARK: - Imports use crate::{mq, registry, PhalaConfig}; + use alloc::boxed::Box; use alloc::collections::BTreeMap; use alloc::vec::Vec; - use alloc::boxed::Box; use frame_support::{ dispatch::DispatchResult, ensure, @@ -79,7 +79,7 @@ pub mod pallet { /// The last metrics sequence number. pub last_metrics_sn: u64, /// The account id that receives the ticket reward. - pub reward_receiver: AccountId, + pub recipient: AccountId, } /// Cryptographic provider for signature verification. @@ -293,15 +293,15 @@ pub mod pallet { Settled { ticket_id: TicketId, worker: WorkerPublicKey, - paid: BalanceOf, + payout: BalanceOf, + recipient: T::AccountId, session_cost: BalanceOf, - paid_to: T::AccountId, }, /// A settlement failed. SettleFailed { ticket_id: TicketId, worker: WorkerPublicKey, - paid: BalanceOf, + payout: BalanceOf, session_cost: BalanceOf, }, /// A worker's session was updated. @@ -399,22 +399,22 @@ pub mod pallet { let update = update.update; if let Some(session) = WorkerSessions::::get(worker_pubkey) { let computed_session = - SessionUpdate::session_from_seed::(update.seed, &session.last_nonce); + SessionUpdate::calc_session_id::(update.nonce, &session.last_nonce); ensure!( computed_session == update.session, Error::::OutdatedMessage ); }; - let Ok(reward_receiver) = Decode::decode(&mut &update.reward_receiver[..]) else { + let Ok(recipient) = Decode::decode(&mut &update.recipient[..]) else { return Err(Error::::InvalidRewardReceiver.into()); }; WorkerSessions::::insert( worker_pubkey, WorkerSession { session_id: update.session, - last_nonce: update.seed, + last_nonce: update.nonce, last_metrics_sn: 0, - reward_receiver, + recipient, }, ); Self::deposit_event(Event::WorkerSessionUpdated { @@ -662,33 +662,33 @@ pub mod pallet { settlement.current_session_id = metrics.session; settlement.current_session_paid = cost; } - let pay_out = cost.saturating_sub(settlement.current_session_paid); - if !pay_out.is_zero() { + let payout = cost.saturating_sub(settlement.current_session_paid); + if !payout.is_zero() { let ticket_account = ticket_account_address(*ticket_id); let transfer_result = ::Currency::transfer( &ticket_account, - &worker_info.reward_receiver, - pay_out, + &worker_info.recipient, + payout, KeepAlive, ); match transfer_result { Ok(_) => { settlement.current_session_paid = cost; settlement.total_paid = - settlement.total_paid.saturating_add(pay_out); + settlement.total_paid.saturating_add(payout); Self::deposit_event(Event::Settled { ticket_id: *ticket_id, worker: worker_pubkey, - paid: pay_out, + payout, session_cost: cost, - paid_to: worker_info.reward_receiver.clone(), + recipient: worker_info.recipient.clone(), }); } Err(_) => { Self::deposit_event(Event::SettleFailed { ticket_id: *ticket_id, worker: worker_pubkey, - paid: pay_out, + payout, session_cost: cost, }); } @@ -1037,12 +1037,12 @@ pub mod pallet { if let TestEvent::PhalaWapodWorkers(Event::::Settled { ticket_id, worker: worker_id, - paid, + payout, .. }) = event { if ticket_id == &ticket && worker_id == &worker { - return Some(*paid); + return Some(*payout); } } } @@ -1180,8 +1180,8 @@ pub mod pallet { public_key: worker_pubkey(0).0, update: SessionUpdate { session: [1; 32], - seed: [1; 32], - reward_receiver: [1; 32].to_vec().into(), + nonce: [1; 32], + recipient: [1; 32].to_vec().into(), }, signature: b"valid".to_vec().into(), }, @@ -1203,8 +1203,8 @@ pub mod pallet { public_key: worker_pubkey(1).0, update: SessionUpdate { session: [1; 32], - seed: [1; 32], - reward_receiver: [1; 32].to_vec().into(), + nonce: [1; 32], + recipient: [1; 32].to_vec().into(), }, signature: b"valid".to_vec().into(), }, @@ -1232,8 +1232,8 @@ pub mod pallet { public_key: worker_pubkey(1).0, update: SessionUpdate { session: [1; 32], - seed: [1; 32], - reward_receiver: [1; 32].to_vec().into(), + nonce: [1; 32], + recipient: [1; 32].to_vec().into(), }, signature: b"valid".to_vec().into(), }, @@ -1247,8 +1247,8 @@ pub mod pallet { public_key: worker_pubkey(1).0, update: SessionUpdate { session: [1; 32], - seed: [2; 32], - reward_receiver: [1; 32].to_vec().into(), + nonce: [2; 32], + recipient: [1; 32].to_vec().into(), }, signature: b"valid".to_vec().into(), }, @@ -1259,7 +1259,7 @@ pub mod pallet { let last_nonce = WorkerSessions::::get(worker_pubkey(1)) .unwrap() .last_nonce; - let seed = [2; 32]; + let nonce = [2; 32]; // Can update session with correct nonce. let result = PhalaWapodWorkers::worker_session_update( @@ -1267,12 +1267,12 @@ pub mod pallet { SignedSessionUpdate { public_key: worker_pubkey(1).0, update: SessionUpdate { - session: SessionUpdate::session_from_seed::( - seed, + session: SessionUpdate::calc_session_id::( + nonce, &last_nonce, ), - seed, - reward_receiver: [1; 32].to_vec().into(), + nonce, + recipient: [1; 32].to_vec().into(), }, signature: b"valid".to_vec().into(), }, @@ -1479,7 +1479,7 @@ pub mod pallet { ..Default::default() }; let reward = tip as u128 * tip_price + gas_consumed as u128 * gas_price; - let reward_receiver = 42_u64; + let recipient = 42_u64; let app_address = [2; 32]; let list_id = setup_worker_list(1, prices); let claim_map = BoundedVec::from(vec![(app_address, vec![list_id].into())]); @@ -1490,8 +1490,8 @@ pub mod pallet { public_key: worker_pubkey(1).0, update: SessionUpdate { session: [1; 32], - seed: [1; 32], - reward_receiver: reward_receiver.encode().into(), + nonce: [1; 32], + recipient: recipient.encode().into(), }, signature: b"valid".to_vec().into(), }, @@ -1538,8 +1538,8 @@ pub mod pallet { // No payment for the first commit let events = Events::take(); - let paid = events.find_settlement_for(0, worker_pubkey(1)); - assert_eq!(paid, None); + let payout = events.find_settlement_for(0, worker_pubkey(1)); + assert_eq!(payout, None); let result = PhalaWapodWorkers::ticket_settle( Origin::signed(1), @@ -1567,8 +1567,8 @@ pub mod pallet { assert_ok!(result); // Should pay for the second commit let events = Events::take(); - let paid = events.find_settlement_for(0, worker_pubkey(1)); - assert_eq!(paid, Some(reward)); + let payout = events.find_settlement_for(0, worker_pubkey(1)); + assert_eq!(payout, Some(reward)); }); } @@ -1608,8 +1608,8 @@ pub mod pallet { public_key: worker_pubkey(1).0, update: SessionUpdate { session: [1; 32], - seed: [1; 32], - reward_receiver: receiver.encode().into(), + nonce: [1; 32], + recipient: receiver.encode().into(), }, signature: b"valid".to_vec().into(), }, diff --git a/standalone/pruntime/Cargo.lock b/standalone/pruntime/Cargo.lock index 26d879e0c..6501084e3 100644 --- a/standalone/pruntime/Cargo.lock +++ b/standalone/pruntime/Cargo.lock @@ -10571,9 +10571,9 @@ dependencies = [ [[package]] name = "wapod-types" -version = "0.1.0-dev.0" +version = "0.1.0-dev.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1af243243426435872a873bb893bbbbc4865caa88d6d4c8856d717a3fcd7094" +checksum = "2e15d1f0f6fc295d001a38335e013f18d887c968de19d3ed5a4e7e3e5efbdc60" dependencies = [ "parity-scale-codec", "scale-info",