From c9073e25f927480c629a2285b985651a973a29f8 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Wed, 17 Jul 2024 15:23:16 +0800 Subject: [PATCH 1/8] Update curve25519-dalek --- Cargo.lock | 23 ++++++++--------------- wapod-pherry/Cargo.lock | 11 ++--------- 2 files changed, 10 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ffef645..5fee846 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1528,16 +1528,15 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.2" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", - "platforms", "rustc_version", "subtle", "zeroize", @@ -1932,7 +1931,7 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "ed25519", "serde", "sha2 0.10.8", @@ -1960,7 +1959,7 @@ version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9" dependencies = [ - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "ed25519", "hashbrown 0.14.5", "hex", @@ -4413,7 +4412,7 @@ checksum = "4e69bf016dc406eff7d53a7d3f7cf1c2e72c82b9088aac1118591e36dd2cd3e9" dependencies = [ "bitcoin_hashes 0.13.0", "rand", - "rand_core 0.6.4", + "rand_core 0.5.1", "serde", "unicode-normalization", ] @@ -4778,12 +4777,6 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" -[[package]] -name = "platforms" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" - [[package]] name = "polkavm-common" version = "0.9.0" @@ -6009,7 +6002,7 @@ dependencies = [ "aead", "arrayref", "arrayvec 0.7.4", - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "getrandom_or_panic", "merlin", "rand_core 0.6.4", @@ -8258,7 +8251,7 @@ name = "wapod-crypto" version = "0.1.0" dependencies = [ "anyhow", - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "derive_more", "eip712_enc", "ethers", @@ -9086,7 +9079,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" dependencies = [ - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "rand_core 0.6.4", "serde", "zeroize", diff --git a/wapod-pherry/Cargo.lock b/wapod-pherry/Cargo.lock index e334793..4fbd73b 100644 --- a/wapod-pherry/Cargo.lock +++ b/wapod-pherry/Cargo.lock @@ -1012,16 +1012,15 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.2" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", - "platforms", "rustc_version", "subtle", "zeroize", @@ -3179,12 +3178,6 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" -[[package]] -name = "platforms" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" - [[package]] name = "polkavm-common" version = "0.9.0" From 6035ab9bd21249f3d4f4e1902e78ea06d77c13dc Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Wed, 17 Jul 2024 15:35:03 +0800 Subject: [PATCH 2/8] Review wapod-pherry, wapod-types and benchmark --- Cargo.lock | 23 +- examples/benchmark/.gitignore | 1 + examples/benchmark/Cargo.toml | 21 + examples/benchmark/WapodDeploy.json | 13 + examples/benchmark/src/bench.rs | 17 + examples/benchmark/src/main.rs | 15 + examples/benchmark/src/query.rs | 149 + wapod-pherry/.gitignore | 2 + wapod-pherry/Cargo.lock | 6291 ++++++++++++++++++ wapod-pherry/Cargo.toml | 29 + wapod-pherry/bridge.sh | 6 + wapod-pherry/src/bridge.rs | 722 ++ wapod-pherry/src/chain_state.rs | 182 + wapod-pherry/src/chain_state/chain_client.rs | 229 + wapod-pherry/src/deploy.rs | 195 + wapod-pherry/src/endpoints.rs | 43 + wapod-pherry/src/ipfs_downloader.rs | 244 + wapod-pherry/src/lib.rs | 45 + wapod-pherry/src/main.rs | 189 + wapod-pherry/src/register.rs | 112 + wapod-pherry/src/rpc_client.rs | 65 + wapod-types/Cargo.toml | 21 + wapod-types/src/bench_app.rs | 72 + wapod-types/src/crypto/mod.rs | 19 + wapod-types/src/crypto/query.rs | 98 + wapod-types/src/crypto/verify.rs | 53 + wapod-types/src/helpers.rs | 1 + wapod-types/src/helpers/scale.rs | 26 + wapod-types/src/lib.rs | 55 + wapod-types/src/metrics.rs | 129 + wapod-types/src/primitives.rs | 208 + wapod-types/src/session.rs | 74 + wapod-types/src/ticket.rs | 168 + wapod-types/src/worker.rs | 63 + 34 files changed, 9565 insertions(+), 15 deletions(-) create mode 100644 examples/benchmark/.gitignore create mode 100644 examples/benchmark/Cargo.toml create mode 100644 examples/benchmark/WapodDeploy.json create mode 100644 examples/benchmark/src/bench.rs create mode 100644 examples/benchmark/src/main.rs create mode 100644 examples/benchmark/src/query.rs create mode 100644 wapod-pherry/.gitignore create mode 100644 wapod-pherry/Cargo.lock create mode 100644 wapod-pherry/Cargo.toml create mode 100644 wapod-pherry/bridge.sh create mode 100644 wapod-pherry/src/bridge.rs create mode 100644 wapod-pherry/src/chain_state.rs create mode 100644 wapod-pherry/src/chain_state/chain_client.rs create mode 100644 wapod-pherry/src/deploy.rs create mode 100644 wapod-pherry/src/endpoints.rs create mode 100644 wapod-pherry/src/ipfs_downloader.rs create mode 100644 wapod-pherry/src/lib.rs create mode 100644 wapod-pherry/src/main.rs create mode 100644 wapod-pherry/src/register.rs create mode 100644 wapod-pherry/src/rpc_client.rs create mode 100644 wapod-types/Cargo.toml create mode 100644 wapod-types/src/bench_app.rs create mode 100644 wapod-types/src/crypto/mod.rs create mode 100644 wapod-types/src/crypto/query.rs create mode 100644 wapod-types/src/crypto/verify.rs create mode 100644 wapod-types/src/helpers.rs create mode 100644 wapod-types/src/helpers/scale.rs create mode 100644 wapod-types/src/lib.rs create mode 100644 wapod-types/src/metrics.rs create mode 100644 wapod-types/src/primitives.rs create mode 100644 wapod-types/src/session.rs create mode 100644 wapod-types/src/ticket.rs create mode 100644 wapod-types/src/worker.rs diff --git a/Cargo.lock b/Cargo.lock index ffef645..5fee846 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1528,16 +1528,15 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.2" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", - "platforms", "rustc_version", "subtle", "zeroize", @@ -1932,7 +1931,7 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "ed25519", "serde", "sha2 0.10.8", @@ -1960,7 +1959,7 @@ version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9" dependencies = [ - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "ed25519", "hashbrown 0.14.5", "hex", @@ -4413,7 +4412,7 @@ checksum = "4e69bf016dc406eff7d53a7d3f7cf1c2e72c82b9088aac1118591e36dd2cd3e9" dependencies = [ "bitcoin_hashes 0.13.0", "rand", - "rand_core 0.6.4", + "rand_core 0.5.1", "serde", "unicode-normalization", ] @@ -4778,12 +4777,6 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" -[[package]] -name = "platforms" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" - [[package]] name = "polkavm-common" version = "0.9.0" @@ -6009,7 +6002,7 @@ dependencies = [ "aead", "arrayref", "arrayvec 0.7.4", - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "getrandom_or_panic", "merlin", "rand_core 0.6.4", @@ -8258,7 +8251,7 @@ name = "wapod-crypto" version = "0.1.0" dependencies = [ "anyhow", - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "derive_more", "eip712_enc", "ethers", @@ -9086,7 +9079,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" dependencies = [ - "curve25519-dalek 4.1.2", + "curve25519-dalek 4.1.3", "rand_core 0.6.4", "serde", "zeroize", diff --git a/examples/benchmark/.gitignore b/examples/benchmark/.gitignore new file mode 100644 index 0000000..9b1c8b1 --- /dev/null +++ b/examples/benchmark/.gitignore @@ -0,0 +1 @@ +/dist diff --git a/examples/benchmark/Cargo.toml b/examples/benchmark/Cargo.toml new file mode 100644 index 0000000..a3f1303 --- /dev/null +++ b/examples/benchmark/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "benchmark" +version = "0.1.0" +edition = "2021" + +[dependencies] +log = "0.4.16" +once_cell = "1.10.0" +sha2 = "0.10.8" +tokio = { version = "1.38.0", features = ["macros"] } +anyhow = "1.0.86" +httptime = { version = "0.1.0", path = "../../httptime" } +futures = "0.3.30" +serde = { version = "1.0.203", features = ["derive"] } +wapod-types = { path = "../../wapod-types" } +serde_json = "1.0.117" + +[dependencies.wapo] +version = "0.1.0" +path = "../../wapo" +features = ["hyper-v0"] diff --git a/examples/benchmark/WapodDeploy.json b/examples/benchmark/WapodDeploy.json new file mode 100644 index 0000000..79b8383 --- /dev/null +++ b/examples/benchmark/WapodDeploy.json @@ -0,0 +1,13 @@ +{ + "label": "worker-benchmark", + "output_dir": "dist", + "wasm_code": "../../target/wasm32-wasi/release/benchmark.wasm", + "args": [], + "env_vars": { + "RUST_LOG": "info" + }, + "on_demand": false, + "resizable": true, + "max_query_size": 102400, + "deps": [] +} \ No newline at end of file diff --git a/examples/benchmark/src/bench.rs b/examples/benchmark/src/bench.rs new file mode 100644 index 0000000..b6ee757 --- /dev/null +++ b/examples/benchmark/src/bench.rs @@ -0,0 +1,17 @@ +fn sha256(data: &[u8]) -> [u8; 32] { + use sha2::{Digest, Sha256}; + let mut hasher = Sha256::new(); + hasher.update(data); + hasher.finalize().into() +} + +pub async fn benchmark() { + let mut init = sha256(b"init"); + loop { + for _ in 0..10000 { + init = sha256(&init); + } + std::hint::black_box(&init); + wapo::time::breath().await; + } +} diff --git a/examples/benchmark/src/main.rs b/examples/benchmark/src/main.rs new file mode 100644 index 0000000..38bd4d1 --- /dev/null +++ b/examples/benchmark/src/main.rs @@ -0,0 +1,15 @@ +#![cfg_attr(not(test), no_main)] + +mod bench; +mod query; + +#[wapo::main] +async fn main() { + wapo::logger::init(); + let filter_str = std::env::var("RUST_LOG").unwrap_or_else(|_| "info".to_string()); + log::info!("benchmark app started, log filter: {filter_str}"); + tokio::select! { + _ = bench::benchmark() => {} + _ = query::query_serve() => {} + } +} diff --git a/examples/benchmark/src/query.rs b/examples/benchmark/src/query.rs new file mode 100644 index 0000000..91db6ae --- /dev/null +++ b/examples/benchmark/src/query.rs @@ -0,0 +1,149 @@ +use anyhow::{bail, Result}; +use futures::stream::FuturesUnordered; +use futures::StreamExt as _; +use log::{debug, info}; +use std::time::{Duration, Instant, SystemTime}; +use tokio::sync::mpsc::Sender; + +use wapod_types::bench_app::{BenchScore, SignedMessage, SigningMessage}; +use wapod_types::scale::Encode; + +struct State { + score: BenchScore, +} + +pub async fn query_serve() { + let query_rx = wapo::channel::incoming_queries(); + + let (score_tx, mut score_rx) = tokio::sync::mpsc::channel(1); + + debug!("spawning score update task"); + wapo::spawn_named("score update", score_update(score_tx)); + + let mut state = State { + score: BenchScore::default(), + }; + + loop { + tokio::select! { + query = query_rx.next() => { + let Some(query) = query else { + break; + }; + match handle_query(&mut state, query.path, query.payload).await { + Ok(reply) => { + _ = query.reply_tx.send(&reply); + } + Err(e) => { + _ = query.reply_tx.send_error(&e.to_string()); + } + } + } + score = score_rx.recv() => { + let Some(score) = score else { + info!("score channel closed"); + break; + }; + state.score = score; + } + } + } +} + +async fn score_update(tx: Sender) { + debug!("score update task started"); + loop { + let net_start_time = net_now().await; + let local_start_time = Instant::now(); + let (gas_at_start, _) = + wapo::ocall::app_gas_consumed().expect("failed to get gas consumed"); + debug!("net_start_time: {:?}", net_start_time); + debug!("gas_at_start: {:?}", gas_at_start); + wapo::time::sleep(Duration::from_secs(30)).await; + let (gas_at_end, token) = + wapo::ocall::app_gas_consumed().expect("failed to get gas consumed"); + let local_elapsed = local_start_time.elapsed(); + let net_end_time = net_now().await; + debug!("net_end_time: {:?}", net_end_time); + debug!("gas_at_end: {:?}", gas_at_end); + match (&net_start_time, &net_end_time) { + (Ok(start_time), Ok(end_time)) => { + let Ok(net_elapsed) = end_time.duration_since(*start_time) else { + info!("invalid net time, skipping score update"); + continue; + }; + let diff = local_elapsed.as_secs_f64() - net_elapsed.as_secs_f64(); + if diff.abs() > 10_f64 { + info!("time diff between local and net is too large: {diff}"); + continue; + } + let gas_diff = gas_at_end.saturating_sub(gas_at_start); + let score = gas_diff.saturating_div(local_elapsed.as_secs()); + debug!("score: {:?}", score); + let score = BenchScore { + gas_per_second: score, + gas_consumed: gas_at_end, + timestamp_secs: end_time + .duration_since(SystemTime::UNIX_EPOCH) + .expect("failed to get timestamp") + .as_secs(), + metrics_token: token, + }; + tx.send(score).await.expect("failed to send score"); + } + _ => { + info!("failed to get net time, skipping score update"); + } + } + } +} + +async fn net_now() -> Result { + let servers = [ + "https://www.cloudflare.com", + "https://www.apple.com", + "https://www.baidu.com", + "https://kernel.org/", + ]; + + let mut futures = FuturesUnordered::new(); + for server in servers { + futures.push(httptime::get_time(server, Duration::from_secs(2))); + } + loop { + let Some(result) = futures.next().await else { + bail!("all servers failed"); + }; + if let Ok(time) = result { + return Ok(time); + } + } +} + +async fn handle_query(state: &mut State, path: String, _payload: Vec) -> Result> { + match path.as_str() { + "/version" => Ok(env!("CARGO_PKG_VERSION").as_bytes().to_vec()), + "/score" => serde_json::to_vec(&state.score) + .map_err(|e| anyhow::anyhow!("failed to serialize score: {}", e)), + "/signedScore" => { + let score = &state.score; + let message = SigningMessage::BenchScore(score.clone()); + let encoded_message = message.encode(); + let signature = wapo::ocall::sign(&encoded_message) + .expect("ocall::sign never fails") + .into(); + let address = wapo::ocall::app_address().expect("failed to get app address"); + let worker_pubkey = wapo::ocall::worker_pubkey().expect("failed to get worker pubkey"); + let signed_message = SignedMessage { + message, + signature, + worker_pubkey, + app_address: address, + }; + Ok(signed_message.encode()) + } + _ => { + bail!("unknown path: {}", path); + } + } +} diff --git a/wapod-pherry/.gitignore b/wapod-pherry/.gitignore new file mode 100644 index 0000000..a727c0a --- /dev/null +++ b/wapod-pherry/.gitignore @@ -0,0 +1,2 @@ +/target +/data diff --git a/wapod-pherry/Cargo.lock b/wapod-pherry/Cargo.lock new file mode 100644 index 0000000..4fbd73b --- /dev/null +++ b/wapod-pherry/Cargo.lock @@ -0,0 +1,6291 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "ark-bls12-377" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb00293ba84f51ce3bd026bd0de55899c4e68f0a39a5728cebae3a73ffdc0a4f" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-bls12-381" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c775f0d12169cba7aae4caeb547bb6a50781c7449a8aa53793827c9ec4abf488" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools 0.10.5", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint", + "num-traits", + "paste", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "array-bytes" +version = "6.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5dde061bd34119e902bbb2d9b90c5692635cf59fb91d582c2b68043f1b8293" + +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + +[[package]] +name = "arrayvec" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +dependencies = [ + "nodrop", +] + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "asn1_der" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "155a5a185e42c6b77ac7b88a15143d930a9e9727a5b7b77eed417404ab15c247" + +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy 0.5.2", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b10202063978b3351199d68f8b22c4e47e4b1b822f8d43fd862d5ea8c006b29a" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a" +dependencies = [ + "async-lock", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-io" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcccb0f599cfa2f8ace422d3555572f47424da5648a4382a9dd0310ff8210884" +dependencies = [ + "async-lock", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "async-lock" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" +dependencies = [ + "event-listener 4.0.3", + "event-listener-strategy 0.4.0", + "pin-project-lite", +] + +[[package]] +name = "async-net" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7" +dependencies = [ + "async-io", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-process" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a53fc6301894e04a92cb2584fedde80cb25ba8e02d9dc39d4a87d036e22f397d" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener 5.3.0", + "futures-lite", + "rustix", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "async-signal" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afe66191c335039c7bb78f99dc7520b0cbb166b3a1cb33a03f53d8a1c6f2afda" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix", + "signal-hook-registry", + "slab", + "windows-sys 0.52.0", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "atomic-take" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8ab6b55fe97976e46f91ddbed8d147d966475dc29b2032757ba47e02376fbc3" + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base-x" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base58" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" +dependencies = [ + "serde", +] + +[[package]] +name = "bip39" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f2635620bf0b9d4576eb7bb9a38a55df78bd1205d26fa994b25911a69f212f" +dependencies = [ + "bitcoin_hashes 0.11.0", +] + +[[package]] +name = "bitcoin-internals" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" + +[[package]] +name = "bitcoin_hashes" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90064b8dee6815a6470d60bad07bbbaee885c0e12d04177138fa3291a01b7bc4" + +[[package]] +name = "bitcoin_hashes" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" +dependencies = [ + "bitcoin-internals", + "hex-conservative", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "blake2-rfc" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" +dependencies = [ + "arrayvec 0.4.12", + "constant_time_eq 0.1.5", +] + +[[package]] +name = "blake2b_simd" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" +dependencies = [ + "arrayref", + "arrayvec 0.5.2", + "constant_time_eq 0.1.5", +] + +[[package]] +name = "blake2b_simd" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" +dependencies = [ + "arrayref", + "arrayvec 0.7.4", + "constant_time_eq 0.3.0", +] + +[[package]] +name = "blake2s_simd" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e461a7034e85b211a4acb57ee2e6730b32912b06c08cc242243c39fc21ae6a2" +dependencies = [ + "arrayref", + "arrayvec 0.5.2", + "constant_time_eq 0.1.5", +] + +[[package]] +name = "blake2s_simd" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94230421e395b9920d23df13ea5d77a20e1725331f90fbbf6df6040b33f756ae" +dependencies = [ + "arrayref", + "arrayvec 0.7.4", + "constant_time_eq 0.3.0", +] + +[[package]] +name = "blake3" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +dependencies = [ + "arrayref", + "arrayvec 0.7.4", + "cc", + "cfg-if", + "constant_time_eq 0.3.0", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "block-padding", + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" + +[[package]] +name = "blocking" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "495f7104e962b7356f0aeb34247aca1fe7d2e783b346582db7f2904cb5717e88" +dependencies = [ + "async-channel", + "async-lock", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + +[[package]] +name = "bounded-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32385ecb91a31bddaf908e8dcf4a15aef1bcd3913cc03ebfad02ff6d568abc1" +dependencies = [ + "log", + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" + +[[package]] +name = "cc" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets 0.52.5", +] + +[[package]] +name = "cid" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8709d481fb78b9808f34a1b4b4fadd08a15a0971052c18bc2b751faefaed595e" +dependencies = [ + "multibase 0.8.0", + "multihash 0.11.4", + "unsigned-varint 0.3.3", +] + +[[package]] +name = "cid" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd94671561e36e4e7de75f753f577edafb0e7c05d6e4547229fdf7938fbcd2c3" +dependencies = [ + "core2", + "multibase 0.9.1", + "multihash 0.18.1", + "serde", + "unsigned-varint 0.7.2", +] + +[[package]] +name = "cid" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3147d8272e8fa0ccd29ce51194dd98f79ddfb8191ba9e3409884e751798acf3a" +dependencies = [ + "core2", + "multibase 0.9.1", + "multihash 0.19.1", + "unsigned-varint 0.8.0", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "clap" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim 0.11.1", +] + +[[package]] +name = "clap_derive" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "clap_lex" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + +[[package]] +name = "common-path" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2382f75942f4b3be3690fe4f86365e9c853c1587d6ee58212cebf6e2a9ccd101" + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd7e35aee659887cbfb97aaf227ac12cad1a9d7c71e55ff3376839ed4e282d08" + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "core2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +dependencies = [ + "memchr", +] + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "rand_core", + "typenum", +] + +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core 0.14.4", + "darling_macro 0.14.4", +] + +[[package]] +name = "darling" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" +dependencies = [ + "darling_core 0.20.9", + "darling_macro 0.20.9", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn 1.0.109", +] + +[[package]] +name = "darling_core" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.11.1", + "syn 2.0.65", +] + +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core 0.14.4", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" +dependencies = [ + "darling_core 0.20.9", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "data-encoding" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" + +[[package]] +name = "data-encoding-macro" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1559b6cba622276d6d63706db152618eeb15b89b3e4041446b05876e352e639" +dependencies = [ + "data-encoding", + "data-encoding-macro-internal", +] + +[[package]] +name = "data-encoding-macro-internal" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "332d754c0af53bc87c108fed664d121ecf59207ec4196041f04d6ab9002ad33f" +dependencies = [ + "data-encoding", + "syn 1.0.109", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "der_derive", + "flagset", + "zeroize", +] + +[[package]] +name = "der_derive" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fe87ce4529967e0ba1dcf8450bab64d97dfd5010a6256187ffe2e43e6f0e049" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "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.65", +] + +[[package]] +name = "derive-where" +version = "1.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "docify" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a2f138ad521dc4a2ced1a4576148a6a610b4c5923933b062a263130a6802ce" +dependencies = [ + "docify_macros", +] + +[[package]] +name = "docify_macros" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a081e51fb188742f5a7a1164ad752121abcb22874b21e2c3b0dd040c515fdad" +dependencies = [ + "common-path", + "derive-syn-parse", + "once_cell", + "proc-macro2", + "quote", + "regex", + "syn 2.0.65", + "termcolor", + "toml 0.8.13", + "walkdir", +] + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dyn-clonable" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e9232f0e607a262ceb9bd5141a3dfb3e4db6994b31989bbfd845878cba59fd4" +dependencies = [ + "dyn-clonable-impl", + "dyn-clone", +] + +[[package]] +name = "dyn-clonable-impl" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "558e40ea573c374cf53507fd240b7ee2f5477df7cfebdb97323ec61c719399c5" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "serdect", + "signature", + "spki", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +dependencies = [ + "curve25519-dalek", + "ed25519", + "serde", + "sha2 0.10.8", + "subtle", + "zeroize", +] + +[[package]] +name = "ed25519-zebra" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9" +dependencies = [ + "curve25519-dalek", + "ed25519", + "hashbrown 0.14.5", + "hex", + "rand_core", + "sha2 0.10.8", + "zeroize", +] + +[[package]] +name = "either" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enum-as-inner" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "environmental" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48c92028aaa870e83d51c64e5d4e0b6981b360c522198c23959f219a4e1b15b" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "event-listener" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d9944b8ca13534cdfb2800775f8dd4902ff3fc75a50101466decadfdf322a24" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" +dependencies = [ + "event-listener 4.0.3", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener 5.3.0", + "pin-project-lite", +] + +[[package]] +name = "expander" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00e83c02035136f1592a47964ea60c05a50e4ed8b5892cfac197063850898d4d" +dependencies = [ + "blake2", + "fs-err", + "prettier-please", + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "fastrand" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "filetime" +version = "0.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.4.1", + "windows-sys 0.52.0", +] + +[[package]] +name = "finito" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2384245d85162258a14b43567a9ee3598f5ae746a1581fb5d3d2cb780f0dbf95" +dependencies = [ + "futures-timer", + "pin-project", +] + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "flagset" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb3aa5e95cf9aabc17f060cfa0ced7b83f042390760ca53bf09df9968acaa1" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "frame-metadata" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "878babb0b136e731cc77ec2fd883ff02745ff21e6fb662729953d44923df009c" +dependencies = [ + "cfg-if", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "frame-metadata" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cf1549fba25a6fcac22785b61698317d958e96cac72a59102ea45b9ae64692" +dependencies = [ + "cfg-if", + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "fs-err" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41" +dependencies = [ + "autocfg", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", + "num_cpus", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-lite" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom_or_panic" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea1015b5a70616b688dc230cfe50c8af89d972cb132d5a622814d29773b10b9" +dependencies = [ + "rand", + "rand_core", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h2" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.1.0", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hash-db" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e7d7786361d7425ae2fe4f9e407eb0efaa0840f5212d109cc018c40c35c6ab4" + +[[package]] +name = "hash256-std-hasher" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" +dependencies = [ + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", + "serde", +] + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-conservative" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212ab92002354b4819390025006c897e8140934349e8635c9b077f47b4dcbd20" + +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + +[[package]] +name = "hex_fmt" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b07f60793ff0a4d9cef0f18e63b5357e06209987153a64648c972c1e5aff336f" + +[[package]] +name = "hickory-proto" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07698b8420e2f0d6447a436ba999ec85d8fbf2a398bbd737b82cac4a2e96e512" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna 0.4.0", + "ipnet", + "once_cell", + "rand", + "thiserror", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "hickory-resolver" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28757f23aa75c98f254cf0405e6d8c25b831b32921b050a66692427679b1f243" +dependencies = [ + "cfg-if", + "futures-util", + "hickory-proto", + "ipconfig", + "lru-cache", + "once_cell", + "parking_lot", + "rand", + "resolv-conf", + "smallvec", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array", + "hmac 0.8.1", +] + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "hostname" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +dependencies = [ + "libc", + "match_cfg", + "winapi", +] + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes", + "futures-core", + "http 1.1.0", + "http-body 1.0.0", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2 0.4.5", + "http 1.1.0", + "http-body 1.0.0", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http 0.2.12", + "hyper 0.14.28", + "log", + "rustls 0.21.12", + "rustls-native-certs 0.6.3", + "tokio", + "tokio-rustls 0.24.1", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper 1.3.1", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "hyper 1.3.1", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown 0.14.5", +] + +[[package]] +name = "indexmap-nostd" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e04e2fd2b8188ea827b32ef11de88377086d690286ab35747ef7f9bf3ccb590" + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "integer-sqrt" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" +dependencies = [ + "num-traits", +] + +[[package]] +name = "ipconfig" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +dependencies = [ + "socket2", + "widestring", + "windows-sys 0.48.0", + "winreg 0.50.0", +] + +[[package]] +name = "ipfs-cid" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bb6d2566e28d91bb41dc1a9f774aff1426429e6968ba5d499b7917ac963d8c" +dependencies = [ + "bs58", + "cid 0.10.1", + "ipfs-unixfs", + "multibase 0.9.1", + "num-bigint", + "thiserror", +] + +[[package]] +name = "ipfs-unixfs" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67d1cf65363f3d01682283456651d1cea436019de5be7a974bb61716c940d44f" +dependencies = [ + "cid 0.5.1", + "either", + "filetime", + "multihash 0.11.4", + "quick-protobuf", + "sha2 0.9.9", +] + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "jsonrpsee" +version = "0.22.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfdb12a2381ea5b2e68c3469ec604a007b367778cdb14d09612c8069ebd616ad" +dependencies = [ + "jsonrpsee-client-transport", + "jsonrpsee-core", + "jsonrpsee-http-client", + "jsonrpsee-types", + "jsonrpsee-ws-client", +] + +[[package]] +name = "jsonrpsee-client-transport" +version = "0.22.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4978087a58c3ab02efc5b07c5e5e2803024536106fd5506f558db172c889b3aa" +dependencies = [ + "futures-util", + "http 0.2.12", + "jsonrpsee-core", + "pin-project", + "rustls-native-certs 0.7.0", + "rustls-pki-types 1.7.0", + "soketto", + "thiserror", + "tokio", + "tokio-rustls 0.25.0", + "tokio-util", + "tracing", + "url", +] + +[[package]] +name = "jsonrpsee-core" +version = "0.22.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4b257e1ec385e07b0255dde0b933f948b5c8b8c28d42afda9587c3a967b896d" +dependencies = [ + "anyhow", + "async-trait", + "beef", + "futures-timer", + "futures-util", + "hyper 0.14.28", + "jsonrpsee-types", + "pin-project", + "rustc-hash", + "serde", + "serde_json", + "thiserror", + "tokio", + "tokio-stream", + "tracing", +] + +[[package]] +name = "jsonrpsee-http-client" +version = "0.22.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ccf93fc4a0bfe05d851d37d7c32b7f370fe94336b52a2f0efc5f1981895c2e5" +dependencies = [ + "async-trait", + "hyper 0.14.28", + "hyper-rustls", + "jsonrpsee-core", + "jsonrpsee-types", + "serde", + "serde_json", + "thiserror", + "tokio", + "tower", + "tracing", + "url", +] + +[[package]] +name = "jsonrpsee-types" +version = "0.22.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "150d6168405890a7a3231a3c74843f58b8959471f6df76078db2619ddee1d07d" +dependencies = [ + "anyhow", + "beef", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "jsonrpsee-ws-client" +version = "0.22.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58b9db2dfd5bb1194b0ce921504df9ceae210a345bc2f6c5a61432089bbab070" +dependencies = [ + "http 0.2.12", + "jsonrpsee-client-transport", + "jsonrpsee-core", + "jsonrpsee-types", + "url", +] + +[[package]] +name = "k256" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "serdect", + "sha2 0.10.8", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "libsecp256k1" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" +dependencies = [ + "arrayref", + "base64 0.13.1", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand", + "serde", + "sha2 0.9.9", + "typenum", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "lru" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +dependencies = [ + "hashbrown 0.14.5", +] + +[[package]] +name = "lru-cache" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +dependencies = [ + "linked-hash-map", +] + +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + +[[package]] +name = "matchers" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "memory-db" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808b50db46293432a45e63bc15ea51e0ab4c0a1647b8eb114e31a3e698dd6fbe" +dependencies = [ + "hash-db", +] + +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core", + "zeroize", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "multibase" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b78c60039650ff12e140ae867ef5299a58e19dded4d334c849dc7177083667e2" +dependencies = [ + "base-x", + "data-encoding", + "data-encoding-macro", +] + +[[package]] +name = "multibase" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b3539ec3c1f04ac9748a260728e855f261b4977f5c3406612c884564f329404" +dependencies = [ + "base-x", + "data-encoding", + "data-encoding-macro", +] + +[[package]] +name = "multihash" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567122ab6492f49b59def14ecc36e13e64dca4188196dd0cd41f9f3f979f3df6" +dependencies = [ + "blake2b_simd 0.5.11", + "blake2s_simd 0.5.11", + "digest 0.9.0", + "sha-1", + "sha2 0.9.9", + "sha3 0.9.1", + "unsigned-varint 0.5.1", +] + +[[package]] +name = "multihash" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfd8a792c1694c6da4f68db0a9d707c72bd260994da179e6030a5dcee00bb815" +dependencies = [ + "blake2b_simd 1.0.2", + "blake2s_simd 1.0.2", + "blake3", + "core2", + "digest 0.10.7", + "multihash-derive", + "sha2 0.10.8", + "sha3 0.10.8", + "unsigned-varint 0.7.2", +] + +[[package]] +name = "multihash" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "076d548d76a0e2a0d4ab471d0b1c36c577786dfc4471242035d97a12a735c492" +dependencies = [ + "core2", + "unsigned-varint 0.7.2", +] + +[[package]] +name = "multihash-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6d4752e6230d8ef7adf7bd5d8c4b1f6561c1014c5ba9a37445ccefe18aa1db" +dependencies = [ + "proc-macro-crate 1.1.3", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure", +] + +[[package]] +name = "multimap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" + +[[package]] +name = "multimap" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" +dependencies = [ + "serde", +] + +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "no-std-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-format" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" +dependencies = [ + "arrayvec 0.7.4", + "itoa", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "openssl" +version = "0.10.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +dependencies = [ + "bitflags 2.5.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "parity-bip39" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e69bf016dc406eff7d53a7d3f7cf1c2e72c82b9088aac1118591e36dd2cd3e9" +dependencies = [ + "bitcoin_hashes 0.13.0", + "rand", + "rand_core", + "serde", + "unicode-normalization", +] + +[[package]] +name = "parity-scale-codec" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +dependencies = [ + "arrayvec 0.7.4", + "bitvec", + "byte-slice-cast", + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +dependencies = [ + "proc-macro-crate 3.1.0", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + +[[package]] +name = "parking_lot" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.1", + "smallvec", + "windows-targets 0.52.5", +] + +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core", + "subtle", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest 0.10.7", + "password-hash", +] + +[[package]] +name = "pem" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" +dependencies = [ + "base64 0.22.1", + "serde", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "phaxt" +version = "0.1.0" +dependencies = [ + "anyhow", + "hex", + "jsonrpsee", + "parity-scale-codec", + "paste", + "primitive-types", + "scale-encode", + "scale-info", + "serde", + "serde_json", + "sp-core", + "sp-runtime", + "subxt", + "subxt-codegen", + "syn 2.0.65", + "tokio", + "tracing", + "wapod-types", +] + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pink-json" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c146010528d0b4f6a3d3255ef2a179e8ef25a1114dfb75542becf89def7c5232" +dependencies = [ + "ryu", + "serde", +] + +[[package]] +name = "pink-types" +version = "0.1.2" +source = "git+https://github.com/Phala-Network/phala-blockchain.git#99e7a2c875164da8466937eca5538c6b888e2262" +dependencies = [ + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "piper" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "464db0c665917b13ebb5d453ccdec4add5658ee1adc7affc7677615356a8afaf" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "polkavm-common" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d9428a5cfcc85c5d7b9fc4b6a18c4b802d0173d768182a51cc7751640f08b92" + +[[package]] +name = "polkavm-derive" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae8c4bea6f3e11cd89bb18bcdddac10bd9a24015399bd1c485ad68a985a19606" +dependencies = [ + "polkavm-derive-impl-macro", +] + +[[package]] +name = "polkavm-derive-impl" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c4fdfc49717fb9a196e74a5d28e0bc764eb394a2c803eb11133a31ac996c60c" +dependencies = [ + "polkavm-common", + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "polkavm-derive-impl-macro" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ba81f7b5faac81e528eb6158a6f3c9e0bb1008e0ffa19653bc8dea925ecb429" +dependencies = [ + "polkavm-derive-impl", + "syn 2.0.65", +] + +[[package]] +name = "polling" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645493cf344456ef24219d02a768cf1fb92ddf8c92161679ae3d91b91a637be3" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "prettier-please" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22020dfcf177fcc7bf5deaf7440af371400c67c0de14c399938d8ed4fb4645d3" +dependencies = [ + "proc-macro2", + "syn 2.0.65", +] + +[[package]] +name = "prettyplease" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" +dependencies = [ + "proc-macro2", + "syn 2.0.65", +] + +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash", + "impl-codec", + "impl-serde", + "scale-info", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" +dependencies = [ + "thiserror", + "toml 0.5.11", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proc-quote" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e84ab161de78c915302ca325a19bee6df272800e2ae1a43fe3ef430bab2a100" +dependencies = [ + "proc-macro-hack", + "proc-macro2", + "proc-quote-impl", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "proc-quote-impl" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fb3ec628b063cdbcf316e06a8b8c1a541d28fa6c0a8eacd2bfb2b7f49e88aa0" +dependencies = [ + "proc-macro-hack", + "proc-macro2", + "quote", +] + +[[package]] +name = "prost" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" +dependencies = [ + "bytes", + "prost-derive 0.9.0", +] + +[[package]] +name = "prost" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" +dependencies = [ + "bytes", + "prost-derive 0.12.6", +] + +[[package]] +name = "prost-build" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5" +dependencies = [ + "bytes", + "heck 0.3.3", + "itertools 0.10.5", + "lazy_static", + "log", + "multimap 0.8.3", + "petgraph", + "prost 0.9.0", + "prost-types 0.9.0", + "regex", + "tempfile", + "which", +] + +[[package]] +name = "prost-build" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" +dependencies = [ + "bytes", + "heck 0.5.0", + "itertools 0.12.1", + "log", + "multimap 0.10.0", + "once_cell", + "petgraph", + "prettyplease", + "prost 0.12.6", + "prost-types 0.12.6", + "regex", + "syn 2.0.65", + "tempfile", +] + +[[package]] +name = "prost-derive" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" +dependencies = [ + "anyhow", + "itertools 0.10.5", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "prost-derive" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" +dependencies = [ + "anyhow", + "itertools 0.12.1", + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "prost-types" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a" +dependencies = [ + "bytes", + "prost 0.9.0", +] + +[[package]] +name = "prost-types" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" +dependencies = [ + "prost 0.12.6", +] + +[[package]] +name = "prpc" +version = "0.2.0" +dependencies = [ + "anyhow", + "async-trait", + "derive_more", + "hex", + "hex_fmt", + "parity-scale-codec", + "prost 0.12.6", + "prpc-serde-bytes", + "serde", + "serde_json", +] + +[[package]] +name = "prpc-build" +version = "0.2.0" +dependencies = [ + "either", + "heck 0.5.0", + "itertools 0.12.1", + "log", + "multimap 0.10.0", + "proc-macro2", + "prost 0.12.6", + "prost-build 0.12.6", + "prost-build 0.9.0", + "prost-types 0.12.6", + "quote", + "syn 2.0.65", + "template-quote", +] + +[[package]] +name = "prpc-serde-bytes" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "syn 2.0.65", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quick-protobuf" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e489d4a83c17ea69b0291630229b5d4c92a94a3bf0165f7f72f506e94cda8b4b" +dependencies = [ + "byteorder", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "reconnecting-jsonrpsee-ws-client" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89cc4a6f1e641017e300c050f0c4c46a198627fb39ec03e7a028d20256b5e54" +dependencies = [ + "cfg_aliases", + "finito", + "futures", + "jsonrpsee", + "serde_json", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +dependencies = [ + "bitflags 2.5.0", +] + +[[package]] +name = "ref-cast" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "regex" +version = "1.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.6", + "regex-syntax 0.8.3", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.3", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + +[[package]] +name = "reqwest" +version = "0.11.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +dependencies = [ + "base64 0.21.7", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2 0.3.26", + "hickory-resolver", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.28", + "hyper-rustls", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls 0.21.12", + "rustls-pemfile 1.0.4", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-rustls 0.24.1", + "tokio-socks", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", + "winreg 0.50.0", +] + +[[package]] +name = "reqwest" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" +dependencies = [ + "base64 0.22.1", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2 0.4.5", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.3.1", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile 2.1.2", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg 0.52.0", +] + +[[package]] +name = "reqwest-env-proxy" +version = "0.1.0" +source = "git+https://github.com/Phala-Network/phala-blockchain.git#99e7a2c875164da8466937eca5538c6b888e2262" +dependencies = [ + "reqwest 0.11.27", +] + +[[package]] +name = "resolv-conf" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +dependencies = [ + "hostname", + "quick-error", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac 0.12.1", + "subtle", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin 0.5.2", + "untrusted 0.7.1", + "web-sys", + "winapi", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags 2.5.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring 0.17.8", + "rustls-webpki 0.101.7", + "sct", +] + +[[package]] +name = "rustls" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" +dependencies = [ + "log", + "ring 0.17.8", + "rustls-pki-types 1.7.0", + "rustls-webpki 0.102.4", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile 1.0.4", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-native-certs" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" +dependencies = [ + "openssl-probe", + "rustls-pemfile 2.1.2", + "rustls-pki-types 1.7.0", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + +[[package]] +name = "rustls-pemfile" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +dependencies = [ + "base64 0.22.1", + "rustls-pki-types 1.7.0", +] + +[[package]] +name = "rustls-pki-types" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47003264dea418db67060fa420ad16d0d2f8f0a0360d825c00e177ac52cb5d8" + +[[package]] +name = "rustls-pki-types" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring 0.17.8", + "untrusted 0.9.0", +] + +[[package]] +name = "rustls-webpki" +version = "0.102.0-alpha.3" +source = "git+https://github.com/rustls/webpki?rev=2ed9a4324f48c2c46ffdd7dc9d3eb315af25fce2#2ed9a4324f48c2c46ffdd7dc9d3eb315af25fce2" +dependencies = [ + "ring 0.16.20", + "rustls-pki-types 0.2.1", + "untrusted 0.7.1", +] + +[[package]] +name = "rustls-webpki" +version = "0.102.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" +dependencies = [ + "ring 0.17.8", + "rustls-pki-types 1.7.0", + "untrusted 0.9.0", +] + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "ruzstd" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c4eb8a81997cf040a091d1f7e1938aeab6749d3a0dfa73af43cdc32393483d" +dependencies = [ + "byteorder", + "derive_more", + "twox-hash", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scale-bits" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57b1e7f6b65ed1f04e79a85a57d755ad56d76fdf1e9bddcc9ae14f71fcdcf54" +dependencies = [ + "parity-scale-codec", + "scale-info", + "scale-type-resolver", + "serde", +] + +[[package]] +name = "scale-decode" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e98f3262c250d90e700bb802eb704e1f841e03331c2eb815e46516c4edbf5b27" +dependencies = [ + "derive_more", + "parity-scale-codec", + "primitive-types", + "scale-bits", + "scale-decode-derive", + "scale-type-resolver", + "smallvec", +] + +[[package]] +name = "scale-decode-derive" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb22f574168103cdd3133b19281639ca65ad985e24612728f727339dcaf4021" +dependencies = [ + "darling 0.14.4", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-encode" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ba0b9c48dc0eb20c60b083c29447c0c4617cb7c4a4c9fef72aa5c5bc539e15e" +dependencies = [ + "derive_more", + "parity-scale-codec", + "primitive-types", + "scale-bits", + "scale-encode-derive", + "scale-type-resolver", + "smallvec", +] + +[[package]] +name = "scale-encode-derive" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82ab7e60e2d9c8d47105f44527b26f04418e5e624ffc034f6b4a86c0ba19c5bf" +dependencies = [ + "darling 0.14.4", + "proc-macro-crate 1.1.3", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-info" +version = "2.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" +dependencies = [ + "bitvec", + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", + "serde", +] + +[[package]] +name = "scale-info-derive" +version = "2.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" +dependencies = [ + "proc-macro-crate 3.1.0", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-type-resolver" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0cded6518aa0bd6c1be2b88ac81bf7044992f0f154bfbabd5ad34f43512abcb" +dependencies = [ + "scale-info", + "smallvec", +] + +[[package]] +name = "scale-typegen" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "498d1aecf2ea61325d4511787c115791639c0fd21ef4f8e11e49dd09eff2bbac" +dependencies = [ + "proc-macro2", + "quote", + "scale-info", + "syn 2.0.65", + "thiserror", +] + +[[package]] +name = "scale-value" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cf9738c263c665144177201126bdad39d3d62512152f178f35002228026976" +dependencies = [ + "base58", + "blake2", + "derive_more", + "either", + "frame-metadata 15.1.0", + "parity-scale-codec", + "scale-bits", + "scale-decode", + "scale-encode", + "scale-info", + "scale-type-resolver", + "serde", + "yap", +] + +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "schnellru" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9a8ef13a93c54d20580de1e5c413e624e53121d42fc7e2c11d10ef7f8b02367" +dependencies = [ + "ahash", + "cfg-if", + "hashbrown 0.13.2", +] + +[[package]] +name = "schnorrkel" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de18f6d8ba0aad7045f5feae07ec29899c1112584a38509a84ad7b04451eaa0" +dependencies = [ + "aead", + "arrayref", + "arrayvec 0.7.4", + "curve25519-dalek", + "getrandom_or_panic", + "merlin", + "rand_core", + "serde_bytes", + "sha2 0.10.8", + "subtle", + "zeroize", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring 0.17.8", + "untrusted 0.9.0", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "secp256k1" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" +dependencies = [ + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb" +dependencies = [ + "cc", +] + +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "zeroize", +] + +[[package]] +name = "security-framework" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" +dependencies = [ + "bitflags 2.5.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.204" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_bytes" +version = "0.11.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.204" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "serde_json" +version = "1.0.120" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + +[[package]] +name = "sgx-attestation" +version = "0.1.0" +source = "git+https://github.com/Phala-Network/phala-blockchain.git#99e7a2c875164da8466937eca5538c6b888e2262" +dependencies = [ + "anyhow", + "asn1_der", + "base64 0.21.7", + "byteorder", + "chrono", + "const-oid", + "der", + "futures", + "hex", + "log", + "parity-scale-codec", + "pem", + "pink-json", + "pink-types", + "reqwest 0.11.27", + "reqwest-env-proxy", + "ring 0.16.20", + "rustls-webpki 0.102.0-alpha.3", + "scale-info", + "serde", + "serde_json", + "tracing", + "urlencoding", + "x509-cert", +] + +[[package]] +name = "sha-1" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" +dependencies = [ + "block-buffer 0.9.0", + "digest 0.9.0", + "keccak", + "opaque-debug", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core", +] + +[[package]] +name = "simple-mermaid" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "620a1d43d70e142b1d46a929af51d44f383db9c7a2ec122de2cd992ccfcf3c18" + +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "smol" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e635339259e51ef85ac7aa29a1cd991b957047507288697a690e80ab97d07cad" +dependencies = [ + "async-channel", + "async-executor", + "async-fs", + "async-io", + "async-lock", + "async-net", + "async-process", + "blocking", + "futures-lite", +] + +[[package]] +name = "smoldot" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d1eaa97d77be4d026a1e7ffad1bb3b78448763b357ea6f8188d3e6f736a9b9" +dependencies = [ + "arrayvec 0.7.4", + "async-lock", + "atomic-take", + "base64 0.21.7", + "bip39", + "blake2-rfc", + "bs58", + "chacha20", + "crossbeam-queue", + "derive_more", + "ed25519-zebra", + "either", + "event-listener 4.0.3", + "fnv", + "futures-lite", + "futures-util", + "hashbrown 0.14.5", + "hex", + "hmac 0.12.1", + "itertools 0.12.1", + "libm", + "libsecp256k1", + "merlin", + "no-std-net", + "nom", + "num-bigint", + "num-rational", + "num-traits", + "pbkdf2", + "pin-project", + "poly1305", + "rand", + "rand_chacha", + "ruzstd", + "schnorrkel", + "serde", + "serde_json", + "sha2 0.10.8", + "sha3 0.10.8", + "siphasher", + "slab", + "smallvec", + "soketto", + "twox-hash", + "wasmi", + "x25519-dalek", + "zeroize", +] + +[[package]] +name = "smoldot-light" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5496f2d116b7019a526b1039ec2247dd172b8670633b1a64a614c9ea12c9d8c7" +dependencies = [ + "async-channel", + "async-lock", + "base64 0.21.7", + "blake2-rfc", + "derive_more", + "either", + "event-listener 4.0.3", + "fnv", + "futures-channel", + "futures-lite", + "futures-util", + "hashbrown 0.14.5", + "hex", + "itertools 0.12.1", + "log", + "lru", + "no-std-net", + "parking_lot", + "pin-project", + "rand", + "rand_chacha", + "serde", + "serde_json", + "siphasher", + "slab", + "smol", + "smoldot", + "zeroize", +] + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "soketto" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" +dependencies = [ + "base64 0.13.1", + "bytes", + "futures", + "httparse", + "log", + "rand", + "sha-1", +] + +[[package]] +name = "sp-application-crypto" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "296282f718f15d4d812664415942665302a484d3495cf8d2e2ab3192b32d2c73" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-std", +] + +[[package]] +name = "sp-arithmetic" +version = "26.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46d0d0a4c591c421d3231ddd5e27d828618c24456d51445d21a1f79fcee97c23" +dependencies = [ + "docify", + "integer-sqrt", + "num-traits", + "parity-scale-codec", + "scale-info", + "serde", + "sp-std", + "static_assertions", +] + +[[package]] +name = "sp-core" +version = "33.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db70266c8fef301c5233ebdf493d785591140eb11e1c06040a9f6e3e5743dc0b" +dependencies = [ + "array-bytes", + "bitflags 1.3.2", + "blake2", + "bounded-collections", + "bs58", + "dyn-clonable", + "ed25519-zebra", + "futures", + "hash-db", + "hash256-std-hasher", + "impl-serde", + "itertools 0.11.0", + "k256", + "libsecp256k1", + "log", + "merlin", + "parity-bip39", + "parity-scale-codec", + "parking_lot", + "paste", + "primitive-types", + "rand", + "scale-info", + "schnorrkel", + "secp256k1", + "secrecy", + "serde", + "sp-crypto-hashing", + "sp-debug-derive", + "sp-externalities", + "sp-runtime-interface", + "sp-std", + "sp-storage", + "ss58-registry", + "substrate-bip39", + "thiserror", + "tracing", + "w3f-bls", + "zeroize", +] + +[[package]] +name = "sp-crypto-hashing" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc9927a7f81334ed5b8a98a4a978c81324d12bd9713ec76b5c68fd410174c5eb" +dependencies = [ + "blake2b_simd 1.0.2", + "byteorder", + "digest 0.10.7", + "sha2 0.10.8", + "sha3 0.10.8", + "twox-hash", +] + +[[package]] +name = "sp-debug-derive" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d09fa0a5f7299fb81ee25ae3853d26200f7a348148aed6de76be905c007dbe" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "sp-externalities" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33abaec4be69b1613796bbf430decbbcaaf978756379e2016e683a4d6379cd02" +dependencies = [ + "environmental", + "parity-scale-codec", + "sp-storage", +] + +[[package]] +name = "sp-io" +version = "36.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a31ce27358b73656a09b4933f09a700019d63afa15ede966f7c9893c1d4db5" +dependencies = [ + "bytes", + "ed25519-dalek", + "libsecp256k1", + "log", + "parity-scale-codec", + "polkavm-derive", + "rustversion", + "secp256k1", + "sp-core", + "sp-crypto-hashing", + "sp-externalities", + "sp-keystore", + "sp-runtime-interface", + "sp-state-machine", + "sp-std", + "sp-tracing", + "sp-trie", + "tracing", + "tracing-core", +] + +[[package]] +name = "sp-keystore" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92a909528663a80829b95d582a20dd4c9acd6e575650dee2bcaf56f4740b305e" +dependencies = [ + "parity-scale-codec", + "parking_lot", + "sp-core", + "sp-externalities", +] + +[[package]] +name = "sp-panic-handler" +version = "13.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8f5a17a0a11de029a8b811cb6e8b32ce7e02183cc04a3e965c383246798c416" +dependencies = [ + "backtrace", + "lazy_static", + "regex", +] + +[[package]] +name = "sp-runtime" +version = "37.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c2a6148bf0ba74999ecfea9b4c1ade544f0663e0baba19630bb7761b2142b19" +dependencies = [ + "docify", + "either", + "hash256-std-hasher", + "impl-trait-for-tuples", + "log", + "num-traits", + "parity-scale-codec", + "paste", + "rand", + "scale-info", + "serde", + "simple-mermaid", + "sp-application-crypto", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-std", + "sp-weights", +] + +[[package]] +name = "sp-runtime-interface" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "647db5e1dc481686628b41554e832df6ab400c4b43a6a54e54d3b0a71ca404aa" +dependencies = [ + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec", + "polkavm-derive", + "primitive-types", + "sp-externalities", + "sp-runtime-interface-proc-macro", + "sp-std", + "sp-storage", + "sp-tracing", + "sp-wasm-interface", + "static_assertions", +] + +[[package]] +name = "sp-runtime-interface-proc-macro" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0195f32c628fee3ce1dfbbf2e7e52a30ea85f3589da9fe62a8b816d70fc06294" +dependencies = [ + "Inflector", + "expander", + "proc-macro-crate 3.1.0", + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "sp-state-machine" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f6ac196ea92c4d0613c071e1a050765dbfa30107a990224a4aba02c7dbcd063" +dependencies = [ + "hash-db", + "log", + "parity-scale-codec", + "parking_lot", + "rand", + "smallvec", + "sp-core", + "sp-externalities", + "sp-panic-handler", + "sp-trie", + "thiserror", + "tracing", + "trie-db", +] + +[[package]] +name = "sp-std" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f8ee986414b0a9ad741776762f4083cd3a5128449b982a3919c4df36874834" + +[[package]] +name = "sp-storage" +version = "21.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99c82989b3a4979a7e1ad848aad9f5d0b4388f1f454cc131766526601ab9e8f8" +dependencies = [ + "impl-serde", + "parity-scale-codec", + "ref-cast", + "serde", + "sp-debug-derive", +] + +[[package]] +name = "sp-tracing" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90b3decf116db9f1dfaf1f1597096b043d0e12c952d3bcdc018c6d6b77deec7e" +dependencies = [ + "parity-scale-codec", + "tracing", + "tracing-core", + "tracing-subscriber 0.2.25", +] + +[[package]] +name = "sp-trie" +version = "35.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a61ab0c3e003f457203702e4753aa5fe9e762380543fada44650b1217e4aa5a5" +dependencies = [ + "ahash", + "hash-db", + "lazy_static", + "memory-db", + "nohash-hasher", + "parity-scale-codec", + "parking_lot", + "rand", + "scale-info", + "schnellru", + "sp-core", + "sp-externalities", + "thiserror", + "tracing", + "trie-db", + "trie-root", +] + +[[package]] +name = "sp-wasm-interface" +version = "21.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b04b919e150b4736d85089d49327eab65507deb1485eec929af69daa2278eb3" +dependencies = [ + "impl-trait-for-tuples", + "log", + "parity-scale-codec", +] + +[[package]] +name = "sp-weights" +version = "31.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93cdaf72a1dad537bbb130ba4d47307ebe5170405280ed1aa31fa712718a400e" +dependencies = [ + "bounded-collections", + "parity-scale-codec", + "scale-info", + "serde", + "smallvec", + "sp-arithmetic", + "sp-debug-derive", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "ss58-registry" +version = "1.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4743ce898933fbff7bbf414f497c459a782d496269644b3d650a398ae6a487ba" +dependencies = [ + "Inflector", + "num-format", + "proc-macro2", + "quote", + "serde", + "serde_json", + "unicode-xid", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "substrate-bip39" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca58ffd742f693dc13d69bdbb2e642ae239e0053f6aab3b104252892f856700a" +dependencies = [ + "hmac 0.12.1", + "pbkdf2", + "schnorrkel", + "sha2 0.10.8", + "zeroize", +] + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "subxt" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a160cba1edbf3ec4fbbeaea3f1a185f70448116a6bccc8276bb39adb3b3053bd" +dependencies = [ + "async-trait", + "derive-where", + "either", + "frame-metadata 16.0.0", + "futures", + "hex", + "impl-serde", + "instant", + "jsonrpsee", + "parity-scale-codec", + "primitive-types", + "reconnecting-jsonrpsee-ws-client", + "scale-bits", + "scale-decode", + "scale-encode", + "scale-info", + "scale-value", + "serde", + "serde_json", + "sp-crypto-hashing", + "subxt-core", + "subxt-lightclient", + "subxt-macro", + "subxt-metadata", + "thiserror", + "tokio-util", + "tracing", + "url", +] + +[[package]] +name = "subxt-codegen" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d703dca0905cc5272d7cc27a4ac5f37dcaae7671acc7fef0200057cc8c317786" +dependencies = [ + "frame-metadata 16.0.0", + "heck 0.5.0", + "hex", + "jsonrpsee", + "parity-scale-codec", + "proc-macro2", + "quote", + "scale-info", + "scale-typegen", + "subxt-metadata", + "syn 2.0.65", + "thiserror", + "tokio", +] + +[[package]] +name = "subxt-core" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59f41eb2e2eea6ed45649508cc735f92c27f1fcfb15229e75f8270ea73177345" +dependencies = [ + "base58", + "blake2", + "derive-where", + "frame-metadata 16.0.0", + "hashbrown 0.14.5", + "hex", + "impl-serde", + "parity-scale-codec", + "primitive-types", + "scale-bits", + "scale-decode", + "scale-encode", + "scale-info", + "scale-value", + "serde", + "serde_json", + "sp-crypto-hashing", + "subxt-metadata", + "tracing", +] + +[[package]] +name = "subxt-lightclient" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d9406fbdb9548c110803cb8afa750f8b911d51eefdf95474b11319591d225d9" +dependencies = [ + "futures", + "futures-util", + "serde", + "serde_json", + "smoldot-light", + "thiserror", + "tokio", + "tokio-stream", + "tracing", +] + +[[package]] +name = "subxt-macro" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c195f803d70687e409aba9be6c87115b5da8952cd83c4d13f2e043239818fcd" +dependencies = [ + "darling 0.20.9", + "parity-scale-codec", + "proc-macro-error", + "quote", + "scale-typegen", + "subxt-codegen", + "syn 2.0.65", +] + +[[package]] +name = "subxt-metadata" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "738be5890fdeff899bbffff4d9c0f244fe2a952fb861301b937e3aa40ebb55da" +dependencies = [ + "frame-metadata 16.0.0", + "hashbrown 0.14.5", + "parity-scale-codec", + "scale-info", + "sp-crypto-hashing", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2863d96a84c6439701d7a38f9de935ec562c8832cc55d1dde0f513b52fad106" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-xid", +] + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +dependencies = [ + "cfg-if", + "fastrand", + "rustix", + "windows-sys 0.52.0", +] + +[[package]] +name = "template-quote" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41b79602418bea6101014d9648243a478b992bf00e136f856bef5c496ad24b21" +dependencies = [ + "proc-quote", + "template-quote-impl", +] + +[[package]] +name = "template-quote-impl" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48245913d30c549fa6b219f94f0aae683a8848d124944bc03f77fbf021053b68" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.12", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +dependencies = [ + "rustls 0.22.4", + "rustls-pki-types 1.7.0", + "tokio", +] + +[[package]] +name = "tokio-socks" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51165dfa029d2a65969413a6cc96f354b86b464498702f174a4efa13608fd8c0" +dependencies = [ + "either", + "futures-util", + "thiserror", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +dependencies = [ + "bytes", + "futures-core", + "futures-io", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "toml" +version = "0.8.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e43f8cc456c9704c851ae29c67e17ef65d2c30017c17a9765b89c382dc8bba" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.22.13", +] + +[[package]] +name = "toml_datetime" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.22.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c127785850e8c20836d49732ae6abfa47616e60bf9d9f57c43c250361a9db96c" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow 0.6.8", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-serde" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +dependencies = [ + "serde", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" +dependencies = [ + "ansi_term", + "chrono", + "lazy_static", + "matchers 0.0.1", + "regex", + "serde", + "serde_json", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log 0.1.4", + "tracing-serde", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers 0.1.0", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log 0.2.0", +] + +[[package]] +name = "trie-db" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c992b4f40c234a074d48a757efeabb1a6be88af84c0c23f7ca158950cb0ae7f" +dependencies = [ + "hash-db", + "log", + "rustc-hex", + "smallvec", +] + +[[package]] +name = "trie-root" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ed310ef5ab98f5fa467900ed906cb9232dd5376597e00fd4cba2a449d06c0b" +dependencies = [ + "hash-db", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "digest 0.10.7", + "rand", + "static_assertions", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + +[[package]] +name = "unsigned-varint" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f67332660eb59a6f1eb24ff1220c9e8d01738a8503c6002e30bcfe4bd9f2b4a9" + +[[package]] +name = "unsigned-varint" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fdeedbf205afadfe39ae559b75c3240f24e257d0ca27e85f85cb82aa19ac35" + +[[package]] +name = "unsigned-varint" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6889a77d49f1f013504cec6bf97a2c730394adedaeb1deb5ea08949a50541105" + +[[package]] +name = "unsigned-varint" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb066959b24b5196ae73cb057f45598450d2c5f71460e98c49b738086eff9c06" + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna 0.5.0", + "percent-encoding", +] + +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "w3f-bls" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7335e4c132c28cc43caef6adb339789e599e39adbe78da0c4d547fad48cbc331" +dependencies = [ + "ark-bls12-377", + "ark-bls12-381", + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-serialize-derive", + "arrayref", + "constcat", + "digest 0.10.7", + "rand", + "rand_chacha", + "rand_core", + "sha2 0.10.8", + "sha3 0.10.8", + "thiserror", + "zeroize", +] + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wapod-pherry" +version = "0.1.0" +dependencies = [ + "anyhow", + "cid 0.11.1", + "clap", + "hex", + "hex-literal", + "hex_fmt", + "ipfs-cid", + "parity-scale-codec", + "phaxt", + "reqwest 0.12.4", + "rustls-pki-types 0.2.1", + "serde", + "serde_json", + "sgx-attestation", + "sha2 0.10.8", + "sp-core", + "tempfile", + "tokio", + "tracing", + "tracing-subscriber 0.3.18", + "wapod-rpc", + "wapod-types", +] + +[[package]] +name = "wapod-rpc" +version = "0.1.0" +dependencies = [ + "anyhow", + "parity-scale-codec", + "prost 0.12.6", + "prpc", + "prpc-build", + "serde", + "serde_json", + "wapod-types", +] + +[[package]] +name = "wapod-types" +version = "0.1.0-dev.1" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.65", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "wasmi" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8281d1d660cdf54c76a3efa9ddd0c270cada1383a995db3ccb43d166456c7" +dependencies = [ + "smallvec", + "spin 0.9.8", + "wasmi_arena", + "wasmi_core", + "wasmparser-nostd", +] + +[[package]] +name = "wasmi_arena" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "104a7f73be44570cac297b3035d76b169d6599637631cf37a1703326a0727073" + +[[package]] +name = "wasmi_core" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf1a7db34bff95b85c261002720c00c3a6168256dcb93041d3fa2054d19856a" +dependencies = [ + "downcast-rs", + "libm", + "num-traits", + "paste", +] + +[[package]] +name = "wasmparser-nostd" +version = "0.100.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5a015fe95f3504a94bb1462c717aae75253e39b9dd6c3fb1062c934535c64aa" +dependencies = [ + "indexmap-nostd", +] + +[[package]] +name = "web-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + +[[package]] +name = "widestring" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "winreg" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "x25519-dalek" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" +dependencies = [ + "curve25519-dalek", + "rand_core", + "serde", + "zeroize", +] + +[[package]] +name = "x509-cert" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1301e935010a701ae5f8655edc0ad17c44bad3ac5ce8c39185f75453b720ae94" +dependencies = [ + "const-oid", + "der", + "spki", +] + +[[package]] +name = "yap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff4524214bc4629eba08d78ceb1d6507070cc0bcbbed23af74e19e6e924a24cf" + +[[package]] +name = "zerocopy" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.65", +] diff --git a/wapod-pherry/Cargo.toml b/wapod-pherry/Cargo.toml new file mode 100644 index 0000000..4ea755c --- /dev/null +++ b/wapod-pherry/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "wapod-pherry" +version = "0.1.0" +edition = "2021" + +[dependencies] +clap = { version = "4.5.4", features = ["derive"] } +tokio = { version = "1.37.0", features = ["full"] } +phaxt = { path = "../phaxt" } +wapod-rpc = { path = "../wapod-rpc" } +wapod-types = { path = "../wapod-types" } +reqwest = "0.12.4" +anyhow = "1.0.86" +sp-core = "33.0.0" +sgx-attestation = { git = "https://github.com/Phala-Network/phala-blockchain.git" } + +rustls-pki-types = "=0.2.1" +scale = { version = "3.6.12", package = "parity-scale-codec" } +tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } +tracing = "0.1.40" +hex = "0.4.3" +hex_fmt = "0.3.0" +cid = "0.11.1" +tempfile = "3.10.1" +serde_json = "1.0.120" +hex-literal = "0.4.1" +serde = { version = "1.0.204", features = ["derive"] } +sha2 = "0.10.8" +ipfs-cid = "2.0.0" diff --git a/wapod-pherry/bridge.sh b/wapod-pherry/bridge.sh new file mode 100644 index 0000000..3d496d6 --- /dev/null +++ b/wapod-pherry/bridge.sh @@ -0,0 +1,6 @@ +cargo run -- bridge \ + --recipient 41rXoa2REMA1c7zVyta3s4CSG35VTUkJCFA8KE4GwuFzp57n \ + --metrics-interval 10 \ + --ipfs-url https://files.kvin.wang:8443/ipfs/ \ + --gas-until-report 1 + diff --git a/wapod-pherry/src/bridge.rs b/wapod-pherry/src/bridge.rs new file mode 100644 index 0000000..9dc9a82 --- /dev/null +++ b/wapod-pherry/src/bridge.rs @@ -0,0 +1,722 @@ +use std::{ + collections::{BTreeMap, BTreeSet}, + pin::pin, + rc::Rc, + time::{Duration, Instant}, +}; + +use anyhow::{bail, Context, Result}; +use cid::Cid; +use hex_fmt::HexFmt as Hex; +use phaxt::{ + phala::{ + phala_computation::events::HeartbeatChallenge, + runtime_types::{ + phala_pallets::wapod_workers::pallet::WorkerSet, sp_core::sr25519::Public, + }, + }, + RecodeTo, +}; +use scale::Decode; +use sp_core::{sr25519, Pair}; +use tokio::sync::mpsc; +use tracing::{debug, error, info, warn}; +use wapod_rpc::{ + prpc::{self as pb, AppListArgs, Blob, DeployArgs, InitArgs, QueryArgs, SetBenchAppArgs}, + types::{Address, VersionedAppsMetrics}, +}; +use wapod_types::{ + bench_app::BenchScore, + metrics::{SignedAppsMetrics, MAX_APPS_METRICS, MAX_CLAIM_TICKETS}, + session::SignedSessionUpdate, + ticket::AppManifest, +}; + +use crate::{ + chain_state::{monitor_chain_state, ChainClient, NonceJar, TicketInfo}, + ipfs_downloader::IpfsDownloader, + register::register_with_client, + util::IgnoreError, +}; +use crate::{ + chain_state::{ChainState, TicketId}, + rpc_client::WorkerClient, +}; + +pub struct BridgeConfig { + pub node_url: String, + pub tx_signer: String, + pub worker_url: String, + pub worker_token: String, + pub ipfs_base_url: String, + pub ipfs_cache_dir: String, + pub max_apps: usize, + pub metrics_interval: Duration, + pub recipient: String, + pub operator: String, + pub pccs_url: String, + pub gas_until_report: u64, +} + +pub enum Event { + ManifestResolved { + cid: String, + result: Result, + }, +} + +#[derive(Clone, Debug)] +struct Ticket { + info: TicketInfo, + manifest: AppManifest, + // prices: Prices, +} + +pub struct BridgeState { + worker_pubkey: Address, + worker_client: WorkerClient, + chain_client: ChainClient, + ipfs_downloader: IpfsDownloader, + planning_state: PlanningState, + chain_state: ChainState, + config: BridgeConfig, + last_metrics_report: Instant, + init_score_reported: bool, +} + +#[derive(Default)] +struct PlanningState { + tickets: BTreeMap, + ticket_balances: BTreeMap, + /// (address, instances) of the bench app + bench_app: Option<(Address, u64)>, + all_apps: BTreeMap>, + selected_apps: BTreeMap>, + download_failures: BTreeMap, +} + +pub struct AppInfo { + manifest: AppManifest, + associated_tickets: BTreeSet, + balance: u128, +} + +#[derive(Clone)] +pub struct BlobDep { + pub hash: String, + pub cid: String, +} + +impl BridgeState { + pub async fn create( + config: BridgeConfig, + worker_client: WorkerClient, + chain_client: ChainClient, + downloader: IpfsDownloader, + ) -> Result { + let info = worker_client.operation().info().await?; + Ok(Self { + worker_pubkey: info.decode_pubkey().context("invalid pubkey from worker")?, + worker_client, + chain_client, + ipfs_downloader: downloader, + planning_state: Default::default(), + chain_state: Default::default(), + config, + last_metrics_report: Instant::now(), + init_score_reported: false, + }) + } + + pub async fn maybe_register_worker(&self, nonce_jar: &mut NonceJar) -> Result<()> { + let info = self.worker_client.operation().info().await?; + let pubkey = Public(info.decode_pubkey()?); + let worker_info_address = phaxt::phala::storage().phala_registry().workers(&pubkey); + let worker_info = self + .chain_client + .fetch(worker_info_address) + .await + .context("failed to get worker info")?; + if worker_info.is_some() { + return Ok(()); + } + register_with_client( + &self.chain_client, + &self.worker_client, + &self.config.operator, + &self.config.pccs_url, + nonce_jar, + ) + .await + } + + pub async fn maybe_update_session(&self, nonce_jar: &mut NonceJar) -> Result<()> { + let info = self.worker_client.operation().info().await?; + let pubkey = Public(info.decode_pubkey()?); + let worker_session_address = phaxt::phala::storage() + .phala_wapod_workers() + .worker_sessions(&pubkey); + let session = self + .chain_client + .fetch(worker_session_address) + .await + .context("failed to get worker session")?; + + if Some(info.session.as_slice()) == session.as_ref().map(|s| s.session_id.as_slice()) { + return Ok(()); + } + // if there is a session recorded on-chain, use the last_nonce to initialize the worker + // else initialize the worker with an empty nonce + let pnonce = match &session { + Some(session) => &session.last_nonce[..], + None => &[], + }; + info!("session mismatch, resetting the worker"); + self.worker_client + .operation() + .app_remove_all() + .await + .context("failed to remove all apps")?; + info!("initializing worker with pnonce: 0x{}", Hex(pnonce)); + let response = self + .worker_client + .operation() + .worker_init(InitArgs { + pnonce: pnonce.to_vec(), + recipient: self.config.recipient.clone(), + }) + .await?; + let update = response.decode_session_update()?; + info!(?update, "updating worker session"); + let signed_update = SignedSessionUpdate { + update, + signature: response.signature.into(), + public_key: pubkey.0, + } + .recode_to() + .context("failed to encode session update")?; + let tx = phaxt::phala::tx() + .phala_wapod_workers() + .worker_session_update(signed_update); + self.chain_client + .submit_tx("update session", tx, true, nonce_jar) + .await + .context("failed to update session")?; + info!("worker session updated"); + Ok(()) + } + + fn set_chain_state(&mut self, chain_state: ChainState) { + self.chain_state = chain_state; + self.planning_state = Default::default(); + } + + pub async fn get_running_apps(&self) -> Result> { + let apps = self + .worker_client + .operation() + .app_list(AppListArgs { + start: 0, + count: u32::MAX, + }) + .await? + .apps; + let apps = apps + .into_iter() + .map(|app| { + let address = + Address::decode(&mut &app.address[..]).context("invalid app address")?; + Ok((address, app.instances)) + }) + .collect::>()?; + Ok(apps) + } + + pub async fn apply_plan(&self) -> Result<()> { + let info = self.worker_client.operation().info().await?; + + let apps = self.get_running_apps().await?; + let mut to_deploy = vec![]; + let mut to_remove = vec![]; + + for (address, plan) in self.planning_state.selected_apps.iter() { + if !apps.contains_key(address) { + to_deploy.push((*address, plan)); + } + } + for (address, _running_instances) in apps.iter() { + if !self.planning_state.selected_apps.contains_key(address) { + to_remove.push(*address); + } + } + + info!( + tickets_onchain = self.chain_state.tickets.len(), + tickets_for_worker = self.planning_state.tickets.len(), + apps = self.planning_state.all_apps.len(), + selected_apps = self.planning_state.selected_apps.len(), + deployed = info.deployed_apps, + running = info.running_instances, + to_deploy = to_deploy.len(), + to_remove = to_remove.len(), + "applying plan" + ); + + 'next_app: for (address, info) in to_deploy { + let deps = info + .associated_tickets + .iter() + .map(|id| { + self.planning_state.tickets[id] + .manifest + .required_blobs + .clone() + .into_iter() + }) + .flatten() + .collect::>(); + for (hash, cid_str) in deps { + let uploaded = self + .worker_client + .operation() + .blob_exists(Blob { + hash: hash.clone(), + body: vec![], + }) + .await? + .value; + if uploaded { + continue; + } + let cid: Cid = cid_str.parse().context("invalid blob cid")?; + let blob = self + .ipfs_downloader + .read(&cid) + .await? + .context("blob not found")?; + info!(?hash, ?cid, address=%Hex(address), "uploading blob"); + let result = self + .worker_client + .operation() + .blob_put(Blob { hash, body: blob }) + .await; + if let Err(err) = result { + error!("failed to upload blob: {:?}", err); + continue 'next_app; + } + } + info!("deploying app 0x{}", Hex(address)); + let result = self + .worker_client + .operation() + .app_deploy(DeployArgs { + manifest: Some(info.manifest.clone().into()), + }) + .await; + match result { + Ok(response) => { + if response.address != address { + error!( + "deployed address mismatch: expected 0x{}, got 0x{}", + Hex(address), + Hex(response.address) + ); + } else { + info!("deployed app 0x{}", Hex(address)); + } + } + Err(e) => { + error!("failed to deploy app 0x{}: {:?}", Hex(address), e); + } + } + } + + for address in to_remove { + info!("removing app 0x{}", Hex(address)); + let result = self + .worker_client + .operation() + .app_remove(pb::Address { + address: address.to_vec(), + }) + .await; + match result { + Ok(_) => { + info!("removed app {}", Hex(address)); + } + Err(e) => { + error!("failed to remove app {}: {:?}", Hex(address), e); + } + } + } + Ok(()) + } + + /// Try to resolve a ticket. + /// + /// Returns the resolved ticket if all required blobs are ready. + /// Returns None if the manifest or any of the required blobs are not + /// ready and ask the downloader to download them. + async fn try_resolve(&self, ticket_info: &TicketInfo) -> Result> { + let cid = ticket_info + .manifest_cid + .parse() + .context("invalid manifest cid")?; + let Some(manifest_data) = self.ipfs_downloader.read(&cid).await? else { + if let Some(err) = self + .planning_state + .download_failures + .get(&ticket_info.manifest_cid) + { + bail!("failed to download manifest: {err}"); + } + self.ipfs_downloader.download(&cid, false)?; + return Ok(None); + }; + let manifest: AppManifest = + serde_json::from_slice(&manifest_data).context("invalid manifest")?; + for (_hash, cid_str) in manifest.required_blobs.iter() { + let cid: Cid = cid_str.parse().context("invalid blob cid")?; + if let Some(err) = self.planning_state.download_failures.get(cid_str) { + bail!("failed to download blob: {err}"); + } + let downloaded = self.ipfs_downloader.download(&cid, false)?; + if !downloaded { + return Ok(None); + } + } + Ok(Some(Ticket { + info: ticket_info.clone(), + manifest, + })) + } + + fn is_ticket_for_worker(&self, info: &TicketInfo) -> bool { + if Some(info.address) == self.chain_state.bench_app_address { + return true; + } + let WorkerSet::WorkerList(list_id) = info.workers else { + return false; + }; + let Some(list) = self.chain_state.worker_list_workers.get(&list_id) else { + return false; + }; + list.contains(&self.worker_pubkey) + } + + async fn try_resolve_deps(&mut self) -> Result<()> { + for (id, info) in self.chain_state.tickets.iter() { + if self.planning_state.tickets.contains_key(id) { + continue; + } + if !self.is_ticket_for_worker(info) { + continue; + } + debug!(id, "resolving ticket"); + let resolved = match self.try_resolve(info).await { + Ok(r) => r, + Err(err) => { + error!("failed to resolve ticket {}: {:?}", id, err); + continue; + } + }; + debug!(id, "resolved ticket: {resolved:?}"); + let Some(ticket) = resolved else { + continue; + }; + self.planning_state.tickets.insert(*id, ticket); + } + Ok(()) + } + + async fn maybe_sync_bench_app(&self) -> Result<()> { + let (address, instances) = match self.planning_state.bench_app { + Some((address, instances)) => (Some(address), instances), + None => (None, 0), + }; + info!( + "setting bench app to {:?} with {} instances", + address.as_ref().map(Hex), + instances + ); + let request = SetBenchAppArgs::new(address, instances); + self.worker_client + .operation() + .set_bench_app(request) + .await + .context("failed to set bench app")?; + Ok(()) + } + + async fn update_plan(&mut self) -> Result<()> { + self.try_resolve_deps().await?; + let worker_info = self.worker_client.operation().info().await?; + let mut all_apps = BTreeMap::new(); + for (id, ticket) in self.planning_state.tickets.iter() { + let info = &ticket.info; + let manifest = &ticket.manifest; + let address = manifest.address(sp_core::hashing::blake2_256); + if info.address != address { + error!( + id, + "ticket address mismatch: expected 0x{}, got 0x{}", + Hex(info.address), + Hex(address) + ); + continue; + } + let balance = match self.planning_state.ticket_balances.get(id) { + Some(b) => *b, + None => { + let balance = self + .chain_client + .ticket_balance(*id) + .await + .context("failed to get ticket balance")?; + self.planning_state.ticket_balances.insert(*id, balance); + balance + } + }; + let rm = info!("ticket {id} balance: {balance}"); + let entry = all_apps.entry(address); + let app_info = entry.or_insert(AppInfo { + manifest: manifest.clone(), + associated_tickets: BTreeSet::new(), + balance: 0, + }); + app_info.associated_tickets.insert(*id); + app_info.balance += balance; + } + let all_apps: BTreeMap<_, _> = all_apps.into_iter().map(|(k, v)| (k, Rc::new(v))).collect(); + let mut sorted_apps: Vec<_> = all_apps + .iter() + .map(|(id, info)| (id.clone(), info.clone())) + .collect(); + + // Sort apps by balance in descending order. + let todo = "better strategy to select apps."; + sorted_apps.sort_by(|a, b| b.1.balance.cmp(&a.1.balance)); + + let selected_apps = sorted_apps + .into_iter() + .take(self.config.max_apps) + .collect::>(); + self.planning_state.all_apps = all_apps; + self.planning_state.selected_apps = selected_apps; + self.planning_state.bench_app = self + .chain_state + .bench_app_address + .map(|address| (address, worker_info.max_instances)); + self.apply_plan().await?; + Ok(()) + } + + async fn maybe_report_app_metrics(&mut self, nonce_jar: &mut NonceJar) -> Result<()> { + let todo = "report app metrics"; + if self.last_metrics_report.elapsed() < self.config.metrics_interval { + return Ok(()); + } + self.last_metrics_report = Instant::now(); + let response = self + .worker_client + .operation() + .app_metrics(Default::default()) + .await?; + let metrics = response.decode_metrics()?; + let signature = response.signature; + let VersionedAppsMetrics::V0(all_metrics) = &metrics; + + let mut claim_map = vec![]; + + for m in all_metrics.apps.0.iter().take(MAX_APPS_METRICS) { + let Some(info) = self.planning_state.all_apps.get(&m.address) else { + debug!( + "app 0x{} not found, skipping to claim settlement", + Hex(m.address) + ); + continue; + }; + let ids = info + .associated_tickets + .iter() + .cloned() + .take(MAX_CLAIM_TICKETS) + .collect::>(); + claim_map.push((m.address, ids)); + } + if claim_map.is_empty() { + return Ok(()); + } + + let signed = SignedAppsMetrics::new(metrics, signature.into(), self.worker_pubkey); + let tx = phaxt::phala::tx().phala_wapod_workers().ticket_settle( + signed.recode_to().context("failed to encode app metrics")?, + claim_map, + ); + self.chain_client + .submit_tx("report metrics", tx, false, nonce_jar) + .await + .context("failed to submit app metrics")?; + Ok(()) + } + + async fn maybe_report_init_score(&mut self, nonce_jar: &mut NonceJar) -> Result<()> { + if self.init_score_reported { + return Ok(()); + } + let Some((address, _n)) = &self.planning_state.bench_app else { + info!("no bench app, skipping init score report"); + return Ok(()); + }; + let encoded_score = self + .worker_client + .operation() + .app_query(QueryArgs::new(*address, "/score".into(), vec![], None)) + .await + .context("bench app is not running")? + .output; + let score: BenchScore = serde_json::from_slice(&encoded_score).context("invalid score")?; + if score.gas_consumed < self.config.gas_until_report { + info!("skipping to report init score, wait a while to get more accurate score"); + return Ok(()); + } + self.do_report_bench_score(true, nonce_jar).await?; + Ok(()) + } + + async fn maybe_report_bench_score(&mut self, nonce_jar: &mut NonceJar) -> Result<()> { + let Some(challenge) = &self.chain_state.heartbeat_challenge else { + return Ok(()); + }; + if !is_challenging_the_worker(challenge, &self.worker_pubkey) { + return Ok(()); + } + { + let working_address = phaxt::phala::storage() + .phala_wapod_workers() + .computation_workers(Public(self.worker_pubkey)); + let working = self + .chain_client + .fetch(working_address) + .await + .context("failed to get working workers")? + .is_some(); + if !working { + return Ok(()); + } + }; + self.do_report_bench_score(false, nonce_jar).await + } + + async fn do_report_bench_score( + &mut self, + is_init: bool, + nonce_jar: &mut NonceJar, + ) -> Result<()> { + let Some((address, _instances)) = &self.planning_state.bench_app else { + debug!("no bench app"); + return Ok(()); + }; + let signed_score = self + .worker_client + .operation() + .app_query(QueryArgs::new( + *address, + "/signedScore".into(), + vec![], + None, + )) + .await + .context("bench app is not running")? + .output; + let tx = phaxt::phala::tx() + .phala_wapod_workers() + .benchmark_score_submit(is_init, Decode::decode(&mut &signed_score[..])?); + info!("submitting bench score"); + self.chain_client + .submit_tx("report bench score", tx, false, nonce_jar) + .await + .context("failed to submit bench score")?; + self.init_score_reported = true; + Ok(()) + } + + async fn bridge(mut self) -> Result<()> { + let todo = "tx queue"; + let todo = "reinit worker if it was restarted"; + // things the bridge does: + // init worker if needed + // sync chain state + // hunt for new tickets + // hunt for heartbeat and response it + // hunt for new bench app + // monitor worker state, schedule jobs + // submit bench score + // submit app metrics + let node_url = self.config.node_url.clone(); + let (chain_state_tx, mut chain_state_rx) = mpsc::channel(1); + let mut chain_state_monitor = pin!(monitor_chain_state(node_url, chain_state_tx)); + let mut downloader_events = self.ipfs_downloader.subscribe_events(); + let mut nonce_jar = NonceJar::default(); + self.maybe_register_worker(&mut nonce_jar).await?; + self.maybe_update_session(&mut nonce_jar).await?; + loop { + nonce_jar.reset(); + tokio::select! { + _ = &mut chain_state_monitor => {} + state = chain_state_rx.recv() => { + self.maybe_report_bench_score(&mut nonce_jar).await.ignore_error("failed to report bench score"); + self.maybe_report_init_score(&mut nonce_jar).await.ignore_error("failed to report init score"); + self.maybe_report_app_metrics(&mut nonce_jar).await.ignore_error("failed to report app metrics"); + self.set_chain_state(state.context("chain state monitor ended")?); + } + event = downloader_events.recv() => { + let event = event.context("downloader event channel closed")?; + use crate::ipfs_downloader::Event as DownloaderEvent; + match event { + DownloaderEvent::Downloaded { cid: _ } => {} + DownloaderEvent::DownloadFailure { cid, error } => { + warn!("download {cid} failed: {error}"); + self.planning_state.download_failures.insert(cid, error); + continue; + } + } + } + } + self.update_plan() + .await + .ignore_error("failed to update plan"); + self.maybe_sync_bench_app() + .await + .ignore_error("failed to sync bench app"); + } + } +} + +pub fn is_challenging_the_worker(heartbeat: &HeartbeatChallenge, worker: &Address) -> bool { + let pkh = sp_core::blake2_256(worker); + let hashed_id: sp_core::U256 = pkh.into(); + let seed = sp_core::U256(heartbeat.seed.0); + let online_target = sp_core::U256(heartbeat.online_target.0); + info!( + "chanllenge target: {}/10000", + online_target / (sp_core::U256::MAX / 10000) + ); + let x = hashed_id ^ seed; + x <= online_target +} + +pub async fn run_bridge(config: BridgeConfig) -> Result<()> { + let pair = sr25519::Pair::from_string(&config.tx_signer, None).context("invalid tx signer")?; + let chain_api = phaxt::connect(&config.node_url.clone()) + .await + .context("connect to chain failed")?; + let chain_client = ChainClient::new(chain_api, pair.into()); + let worker_client = WorkerClient::new(config.worker_url.clone(), config.worker_token.clone()); + let ipfs_downloader = + IpfsDownloader::new(config.ipfs_base_url.clone(), config.ipfs_cache_dir.clone()); + let state = BridgeState::create(config, worker_client, chain_client, ipfs_downloader) + .await + .context("failed to create bridge")?; + state.bridge().await +} diff --git a/wapod-pherry/src/chain_state.rs b/wapod-pherry/src/chain_state.rs new file mode 100644 index 0000000..1f82c62 --- /dev/null +++ b/wapod-pherry/src/chain_state.rs @@ -0,0 +1,182 @@ +use std::{collections::BTreeMap, mem::size_of}; + +use anyhow::{bail, Context, Result}; +use phaxt::phala::phala_computation::events::HeartbeatChallenge; +use phaxt::phala::runtime_types::phala_pallets::wapod_workers::pallet::{ + BenchAppInfo, TicketInfo as TicketInfoRT, WorkerListInfo as WorkerListInfoRT, +}; +use scale::Decode; +use tokio::{ + sync::mpsc::Sender, + time::{timeout, Duration}, +}; +use tracing::{debug, error, info, trace}; +use wapod_rpc::types::Address; + +pub use chain_client::{ChainClient, NonceJar}; + +mod chain_client; + +pub type TicketId = u64; +pub type WorkerListId = u64; +pub type AccountId = phaxt::subxt::utils::AccountId32; + +pub(crate) type TicketInfo = TicketInfoRT; +pub(crate) type WorkerListInfo = WorkerListInfoRT; + +#[derive(Default)] +pub struct ChainState { + pub tickets: BTreeMap, + pub worker_lists: BTreeMap, + pub worker_list_workers: BTreeMap>, + pub bench_app_address: Option
, + pub valid_bench_apps: BTreeMap, + pub heartbeat_challenge: Option, +} + +/// Timeout for network connecting and handshaking, etc. +const NET_TIMEOUT: Duration = Duration::from_secs(60); +/// Timeout for data transfering. +const DATA_TIMEOUT: Duration = Duration::from_secs(120); +/// Timeout for block subscription. +const BLOCK_TIMEOUT: Duration = Duration::from_secs(60); + +pub async fn monitor_chain_state(uri: String, state_tx: Sender) { + loop { + if let Err(err) = monitor(&uri, state_tx.clone()).await { + error!("monitoring chain state error: {err}"); + tokio::time::sleep(Duration::from_secs(5)).await; + } + } +} + +// This is a workaround for the issue that the subxt generated code always set the iter Keys to `()` +fn decode_key(key_bytes: &[u8]) -> Result { + if key_bytes.len() < size_of::() { + bail!("invalid key"); + } + let tail = &key_bytes[key_bytes.len() - size_of::()..]; + K::decode(&mut &*tail).context("invalid key") +} + +async fn monitor(uri: &str, tx: Sender) -> Result<()> { + let client = timeout(NET_TIMEOUT, phaxt::connect(&uri)) + .await + .context("connect to chain timeout")? + .context("connect to chain failed")?; + let mut sub = timeout(NET_TIMEOUT, client.client().blocks().subscribe_finalized()) + .await + .context("block subscription timeout")? + .context("block subscription failed")?; + loop { + debug!("waiting for new block"); + let block = timeout(BLOCK_TIMEOUT, sub.next()) + .await + .context("block subscription timeout")? + .context("block subscription ended")? + .context("block subscription failed")?; + let block_hash = block.hash(); + let block_number = block.number(); + info!("new block: {block_number} {block_hash}"); + + timeout(DATA_TIMEOUT, async { + let pallet = phaxt::phala::storage().phala_wapod_workers(); + + let tickets = { + let mut tickets = BTreeMap::::new(); + + let query_tickets = pallet.tickets_iter(); + let mut tickets_iter = block.storage().iter(query_tickets).await?; + while let Some(pair) = tickets_iter + .next() + .await + .transpose() + .context("failed to fetch tickets")? + { + let ticket_id = decode_key(&pair.key_bytes)?; + trace!("found ticket {ticket_id}: {:?}", pair.value); + tickets.insert(ticket_id, pair.value); + } + tickets + }; + let (worker_lists, worker_list_workers) = { + let mut worker_lists = BTreeMap::::new(); + let mut worker_list_workers = BTreeMap::>::new(); + + let query_worker_lists = pallet.worker_lists_iter(); + let mut worker_lists_iter = block.storage().iter(query_worker_lists).await?; + while let Some(pair) = worker_lists_iter + .next() + .await + .transpose() + .context("failed to fetch worker lists")? + { + let worker_list_id = decode_key(&pair.key_bytes)?; + trace!("found worker list {worker_list_id}: {:?}", pair.value); + worker_lists.insert(worker_list_id, pair.value); + + let mut list: Vec
= vec![]; + let query_workers = pallet.worker_list_workers_iter1(worker_list_id); + let mut workers_iter = block.storage().iter(query_workers).await?; + while let Some(worker) = workers_iter + .next() + .await + .transpose() + .context("failed to fetch workers of list")? + { + let worker_address = decode_key(&worker.key_bytes)?; + list.push(worker_address); + } + worker_list_workers.insert(worker_list_id, list); + } + (worker_lists, worker_list_workers) + }; + + let bench_app_address = { + let query_bench_app = pallet.recommended_benchmark_app(); + let bench_app = block.storage().fetch(&query_bench_app).await?; + trace!("found bench app: {:?}", bench_app); + bench_app + }; + + let valid_bench_apps = { + let mut valid_bench_apps = BTreeMap::::new(); + + let query_valid_bench_apps = pallet.benchmark_apps_iter(); + let mut valid_bench_apps_iter = + block.storage().iter(query_valid_bench_apps).await?; + while let Some(pair) = valid_bench_apps_iter + .next() + .await + .transpose() + .context("failed to fetch bench apps")? + { + let bench_app_address = decode_key(&pair.key_bytes)?; + valid_bench_apps.insert(bench_app_address, pair.value); + } + valid_bench_apps + }; + let heartbeat_challenge = { + let events = block.events().await.context("failed to fetch events")?; + events + .find_first::() + .context("failed to find heartbeat challenge")? + }; + if heartbeat_challenge.is_none() { + info!("no heartbeat challenge found"); + } + let state = ChainState { + tickets, + worker_lists, + worker_list_workers, + bench_app_address, + valid_bench_apps, + heartbeat_challenge, + }; + tx.send(state).await?; + Ok::<_, anyhow::Error>(()) + }) + .await + .context("fetch chain state timeout")??; + } +} diff --git a/wapod-pherry/src/chain_state/chain_client.rs b/wapod-pherry/src/chain_state/chain_client.rs new file mode 100644 index 0000000..15a0805 --- /dev/null +++ b/wapod-pherry/src/chain_state/chain_client.rs @@ -0,0 +1,229 @@ +use std::ops::Deref; + +use anyhow::{Context, Result}; +use phaxt::{ + phala::Event, + signer::PhalaSigner, + subxt::{ + config::{Header as _, RefineParams, RefineParamsData}, + dynamic::Value, + metadata::DecodeWithMetadata, + storage::{DefaultAddress, StorageKey}, + tx::{Payload, SubmittableExtrinsic}, + utils::Yes, + }, + BuiltExtrinsicParams, ChainApi, +}; +use sp_core::{sr25519, Pair}; +use tokio::time::timeout; +use tracing::{debug, error, info}; + +use super::NET_TIMEOUT; + +#[derive(Debug, Default)] +pub struct NonceJar { + next_nonce: Option, +} + +impl NonceJar { + pub async fn next(&mut self, client: &ChainClient) -> Result { + let nonce = match self.next_nonce { + Some(nonce) => nonce, + None => client.account_nonce(client.signer().account_id()).await?, + }; + self.next_nonce = Some(nonce + 1); + Ok(nonce) + } + pub fn reset(&mut self) { + self.next_nonce = None; + } +} + +pub struct ChainClient { + client: ChainApi, + signer: PhalaSigner, +} + +impl Deref for ChainClient { + type Target = ChainApi; + + fn deref(&self) -> &Self::Target { + &self.client + } +} + +impl ChainClient { + pub fn new(client: ChainApi, signer: PhalaSigner) -> Self { + Self { client, signer } + } + + pub fn signer(&self) -> &PhalaSigner { + &self.signer + } + + pub async fn connect(url: &str, signer: &str) -> Result { + let client = timeout(NET_TIMEOUT, phaxt::connect(url)) + .await + .context("connect to chain timeout")? + .context("connect to chain failed")?; + let pair = sr25519::Pair::from_string(signer, None).context("invalid signer")?; + let signer = PhalaSigner::new(pair); + Ok(Self::new(client, signer)) + } + + pub async fn fetch( + &self, + address: DefaultAddress, + ) -> Result> + where + Keys: StorageKey, + ReturnTy: DecodeWithMetadata, + { + self.storage() + .at_latest() + .await? + .fetch(&address) + .await + .context("failed to get worker session") + } + + pub async fn submit_tx( + &self, + label: &str, + tx: Call, + wait_finalized: bool, + nonce_jar: &mut NonceJar, + ) -> Result<()> + where + Call: Payload, + { + self.submit_tx_innner(tx, wait_finalized, label, nonce_jar) + .await + .with_context(|| format!("submit tx({label}) failed")) + } + + async fn submit_tx_innner( + &self, + tx: Call, + wait_finalized: bool, + label: &str, + nonce_jar: &mut NonceJar, + ) -> Result<()> + where + Call: Payload, + { + let todo = "support tx lifetime and tip"; + let todo = "manage account nonce"; + let params = self + .mk_params(8, 0) + .await + .context("mk params failed")? + .build(); + let nonce = nonce_jar.next(self).await?; + let signed_tx = self + .create_signed(&tx, params, nonce) + .await + .context("sign tx failed")?; + let progress = signed_tx + .submit_and_watch() + .await + .context("submit tx failed")?; + if wait_finalized { + let events = progress + .wait_for_finalized_success() + .await + .context("tx failed")?; + info!("tx({label}) finalized"); + for (i, event) in events.all_events_in_block().iter().enumerate() { + let Ok(event) = event else { + debug!("event {i}: decode failed"); + continue; + }; + let Ok(event) = event.as_root_event::() else { + debug!("event {i}: decode failed"); + continue; + }; + debug!("event {i}: {:?}", event); + } + } else { + info!("tx({label}) submitted: {:?}", progress); + let label = label.to_string(); + tokio::spawn(async move { + match progress.wait_for_finalized_success().await { + Err(err) => error!("tx({label}) failed: {err}"), + Ok(_) => info!("tx({label}) finalized"), + } + }); + } + Ok(()) + } + + pub async fn ticket_balance(&self, ticket_id: u64) -> Result { + let runtime_api_call = phaxt::subxt::dynamic::runtime_api_call( + "WapodWorkersApi", + "balance_of_ticket", + vec![Value::u128(ticket_id as _)], + ); + + let balance = self + .client + .runtime_api() + .at_latest() + .await? + .call(runtime_api_call) + .await? + .to_value()? + .as_u128() + .context("invalid balance")?; + Ok(balance) + } + + pub async fn register_worker( + &self, + runtime_info: Vec, + attestation: Vec, + nonce_jar: &mut NonceJar, + ) -> Result<()> { + let tx = phaxt::dynamic::tx::register_worker(runtime_info, attestation, true); + self.submit_tx("register worker", tx, true, nonce_jar).await + } +} + +impl ChainClient { + async fn create_signed( + &self, + call: &Call, + mut params: BuiltExtrinsicParams, + account_nonce: u64, + ) -> Result> + where + Call: Payload, + { + let tx_client = self.client.tx(); + tx_client.validate(call)?; + self.refine_params(account_nonce, &mut params).await?; + let partial_signed = tx_client.create_partial_signed_offline(call, params.into())?; + Ok(partial_signed.sign(self.signer())) + } + + async fn refine_params( + &self, + account_nonce: u64, + params: &mut BuiltExtrinsicParams, + ) -> Result<()> { + let block_ref = self.client.backend().latest_finalized_block_ref().await?; + let block_header = self + .client + .backend() + .block_header(block_ref.hash()) + .await? + .context("block header not found")?; + + params.refine(&RefineParamsData::new( + account_nonce, + block_header.number.into(), + block_header.hash(), + )); + Ok(()) + } +} diff --git a/wapod-pherry/src/deploy.rs b/wapod-pherry/src/deploy.rs new file mode 100644 index 0000000..c2c8877 --- /dev/null +++ b/wapod-pherry/src/deploy.rs @@ -0,0 +1,195 @@ +use std::{ + collections::BTreeMap, + path::{Path, PathBuf}, +}; + +use anyhow::{Context, Result}; +use hex_fmt::HexFmt; +use phaxt::{ + phala::runtime_types::{sp_core::sr25519::Public, wapod_types::ticket::Prices}, + RecodeTo, +}; +use serde::Deserialize; +use tracing::info; +use wapod_rpc::prpc::SignWorkerDescriptionArgs; +use wapod_types::{ticket::AppManifest, Address}; + +use crate::{ + chain_state::ChainClient, + util::{read_file, write_file}, +}; + +#[derive(Deserialize, Debug, Clone)] +struct DeployConfig { + output_dir: Option, + wasm_code: PathBuf, + args: Vec, + env_vars: BTreeMap, + on_demand: bool, + resizable: bool, + max_query_size: u32, + label: String, + deps: Vec, +} + +fn sha256_hash(data: &[u8]) -> String { + use sha2::{Digest, Sha256}; + let mut hasher = Sha256::new(); + hasher.update(data); + format!("sha256:{}", hex::encode(hasher.finalize())) +} + +fn cid_of(data: &[u8]) -> Result { + let cid = ipfs_cid::generate_cid_v0(data)?; + Ok(cid) +} + +fn hash(data: &[u8], output_dir: impl AsRef) -> Result<(String, String)> { + let hash = sha256_hash(data); + let cid = cid_of(data)?; + write_file(output_dir.as_ref().join(&cid), data)?; + Ok((hash, cid)) +} + +pub fn build_manifest(config_file: impl AsRef) -> Result<(Address, String)> { + let todo = "more config items"; + let config_file = std::fs::canonicalize(config_file.as_ref())?; + let config: DeployConfig = serde_json::from_reader(std::fs::File::open(&config_file)?) + .context("failed to parse config")?; + + let base_dir = config_file.parent().context("no parent")?; + let output_dir = base_dir.join(config.output_dir.unwrap_or_else(|| "build".to_string())); + let blobs_dir = output_dir.join("blobs"); + if output_dir.exists() { + std::fs::remove_dir_all(&output_dir).context("failed to remove output_dir")?; + } + std::fs::create_dir_all(&blobs_dir).context("failed to create output_dir")?; + + let mut deps = BTreeMap::new(); + + let wasm_code = + read_file(base_dir.join(config.wasm_code)).context("failed to read wasm_code")?; + let (code_hash, cid) = hash(&wasm_code, &blobs_dir)?; + deps.insert(code_hash.clone(), cid); + + let mut args = vec![]; + + for arg in config.args.into_iter() { + let prefix = "sha256-of-file:"; + if arg.starts_with(prefix) { + let file = arg.trim_start_matches(prefix); + let data = read_file(base_dir.join(file)).context("failed to read file")?; + let (hash, cid) = hash(&data, &blobs_dir)?; + args.push(hash.clone()); + deps.insert(hash, cid); + } else { + args.push(arg); + } + } + + for dep in config.deps { + let dep_code = read_file(base_dir.join(dep)).context("failed to read dep")?; + let (dep_hash, dep_cid) = hash(&dep_code, &blobs_dir)?; + if deps.contains_key(&dep_hash) { + continue; + } + deps.insert(dep_hash, dep_cid); + } + + let manifest = AppManifest { + version: 1, + code_hash, + args, + env_vars: config.env_vars.into_iter().collect(), + on_demand: config.on_demand, + resizable: config.resizable, + max_query_size: config.max_query_size, + label: config.label, + required_blobs: deps.into_iter().collect(), + }; + let address = manifest.address(sp_core::hashing::blake2_256); + + let manifest_json = serde_json::to_string_pretty(&manifest)?; + let (_manifest_hash, manifest_cid) = + hash(manifest_json.as_bytes(), &blobs_dir).context("failed to hash manifest file")?; + write_file(output_dir.join("manifest.json"), manifest_json.as_bytes()) + .context("failed to write manifest")?; + println!("manifest cid : {}", manifest_cid); + println!("app address : 0x{}", HexFmt(address)); + Ok((address, manifest_cid)) +} + +pub async fn deploy_manifest( + config_file: impl AsRef, + node_url: &str, + signer: &str, + deposit: u128, + worker_list: u64, +) -> Result<()> { + let (address, manifest_cid) = build_manifest(config_file)?; + let tx = phaxt::phala::tx().phala_wapod_workers().ticket_create( + deposit, + address, + manifest_cid, + worker_list, + Prices { + general_fee_per_second: Some(1_000_000_000), + ..Default::default() + }, + ); + let chain_client = ChainClient::connect(node_url, signer).await?; + chain_client + .submit_tx("create ticket", tx, true, &mut Default::default()) + .await?; + Ok(()) +} + +pub async fn create_worker_list( + node_url: String, + signer: String, + worker_url: String, + worker_token: String, +) -> Result<()> { + let worker_client = crate::WorkerClient::new(worker_url, worker_token); + let chain_client = ChainClient::connect(&node_url, &signer).await?; + let info = worker_client.operation().info().await?; + let pubkey = info.decode_pubkey()?; + + info!("worker pubkey: {:?}", HexFmt(pubkey)); + let signed = worker_client + .operation() + .sign_worker_description(SignWorkerDescriptionArgs::new( + "test-worker".into(), + Default::default(), + )) + .await? + .decode_signed_description()?; + info!("signed worker description"); + let tx = phaxt::phala::tx() + .phala_wapod_workers() + .worker_description_set( + signed + .recode_to() + .context("failed to encode worker description")?, + ); + info!("setting worker description..."); + chain_client + .submit_tx("set worker description", tx, true, &mut Default::default()) + .await?; + info!("worker description set"); + + let tx = phaxt::phala::tx().phala_wapod_workers().worker_list_create( + "pherry-created".into(), + Prices { + general_fee_per_second: Some(1_000_000_000), + ..Default::default() + }, + vec![Public(pubkey)], + ); + info!("creating worker list..."); + chain_client + .submit_tx("create worker list", tx, true, &mut Default::default()) + .await?; + info!("worker list created"); + Ok(()) +} diff --git a/wapod-pherry/src/endpoints.rs b/wapod-pherry/src/endpoints.rs new file mode 100644 index 0000000..bc83cec --- /dev/null +++ b/wapod-pherry/src/endpoints.rs @@ -0,0 +1,43 @@ +use anyhow::{Context, Result}; +use phaxt::signer::PairSigner; +use sp_core::Pair; +use wapod_rpc::prpc::SignEndpointsArgs; + +use crate::WorkerClient; + +pub struct UpdateEndpointArgs { + pub worker_url: String, + pub token: String, + pub node_url: String, + pub endpoint: String, + pub signer: String, +} + +pub async fn update_endpoint(args: UpdateEndpointArgs) -> Result<()> { + let UpdateEndpointArgs { + worker_url, + token, + node_url, + endpoint, + signer: operator, + } = args; + let worker_client = WorkerClient::new(worker_url, token); + let chain_client = phaxt::connect(&node_url) + .await + .context("failed to connect to the chain")?; + let rpc_args = SignEndpointsArgs { + endpoints: vec![endpoint], + }; + let response = worker_client.operation().sign_endpoints(rpc_args).await?; + let alice = sp_core::sr25519::Pair::from_string(&operator, None) + .expect("should create signer from mnemonic"); + let mut signer = PairSigner::new(alice); + chain_client + .update_worker_endpoints( + response.encoded_endpoint_payload, + response.signature, + &mut signer, + ) + .await?; + Ok(()) +} diff --git a/wapod-pherry/src/ipfs_downloader.rs b/wapod-pherry/src/ipfs_downloader.rs new file mode 100644 index 0000000..627d9b0 --- /dev/null +++ b/wapod-pherry/src/ipfs_downloader.rs @@ -0,0 +1,244 @@ +use std::{ + collections::BTreeSet, + path::{Path, PathBuf}, + sync::{Arc, Mutex}, + time::Duration, +}; + +use anyhow::{bail, Result}; +use cid::Cid; +use reqwest::Client as HttpClient; +use tokio::{io::AsyncWriteExt as _, sync::broadcast, time::timeout}; +use tracing::{debug, error, info}; + +struct IpfsDownloaderState { + pending: BTreeSet, + downloading: BTreeSet, +} + +#[derive(Debug, Clone)] +pub enum Event { + Downloaded { cid: String }, + DownloadFailure { cid: String, error: String }, +} + +#[derive(Debug, Clone, Copy)] +pub enum ResState { + Downloading, + Downloaded, + NotFound, +} + +pub struct Config { + base_url: String, + http_client: HttpClient, + data_dir: PathBuf, + max_downloading: usize, + max_pending: usize, + max_file_size: usize, + max_download_time: Duration, + notify: broadcast::Sender, +} + +pub struct IpfsDownloader { + config: Arc, + state: Arc>, +} + +impl Clone for IpfsDownloader { + fn clone(&self) -> Self { + Self { + config: self.config.clone(), + state: self.state.clone(), + } + } +} + +impl IpfsDownloader { + pub fn new(base_url: String, data_dir: impl AsRef) -> Self { + let todo = "download size limit and cleanup unused files"; + let base_url = base_url.trim_end_matches('/').to_string(); + Self { + config: Arc::new(Config { + base_url, + http_client: HttpClient::builder() + .connect_timeout(Duration::from_secs(30)) + .build() + .expect("failed to create http client"), + data_dir: data_dir.as_ref().to_path_buf(), + max_downloading: 10, + max_pending: 10000, + max_file_size: 1024 * 1024 * 20, + max_download_time: Duration::from_secs(600), + notify: broadcast::channel(1).0, + }), + state: Arc::new(Mutex::new(IpfsDownloaderState { + pending: BTreeSet::new(), + downloading: BTreeSet::new(), + })), + } + } + + fn path_of(&self, cid: &str) -> PathBuf { + self.config.data_dir.join(cid) + } + + fn tmp_path_of(&self, cid: &str) -> PathBuf { + self.config.data_dir.join(format!("{}.tmp", cid)) + } + + pub fn subscribe_events(&self) -> broadcast::Receiver { + self.config.notify.subscribe() + } + + pub fn exists(&self, cid: &Cid) -> bool { + self.path_of(&cid.to_string()).exists() + } + + pub fn state_of(&self, cid: &Cid) -> ResState { + let cid_str = cid.to_string(); + let state = self.state.lock().unwrap(); + if state.downloading.contains(&cid_str) || state.pending.contains(&cid_str) { + ResState::Downloading + } else if self.exists(cid) { + ResState::Downloaded + } else { + ResState::NotFound + } + } + + pub fn download(&self, cid: &Cid, force: bool) -> Result { + if !force && self.exists(cid) { + return Ok(true); + } + let cid_str = cid.to_string(); + let mut state = self.state.lock().unwrap(); + + if state.downloading.contains(&cid_str) || state.pending.contains(&cid_str) { + debug!("already downloading {cid_str}"); + return Ok(false); + } + if state.downloading.len() < self.config.max_downloading { + state.downloading.insert(cid_str.clone()); + let todo = "cancel task if the downloader is dropped"; + tokio::spawn(self.clone().download_task(cid_str)); + return Ok(false); + } else if state.pending.len() < self.config.max_pending { + state.pending.insert(cid_str.clone()); + info!("queued {cid_str}"); + return Ok(false); + } else { + bail!("download queue full, failed to download {cid_str}"); + } + } + + pub async fn read(&self, cid: &Cid) -> Result>> { + let path = self.path_of(&cid.to_string()); + let data = match tokio::fs::read(path).await { + Ok(data) => data, + Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(None), + Err(err) => return Err(err.into()), + }; + Ok(Some(data)) + } + + pub async fn read_or_download(&self, cid: &Cid) -> Result> { + let mut rx = self.subscribe_events(); + match self.read(cid).await { + Ok(Some(data)) => return Ok(data), + Ok(None) => {} + Err(err) => return Err(err), + } + self.download(cid, true)?; + loop { + let event = rx.recv().await?; + match event { + Event::Downloaded { + cid: downloaded_cid, + } => { + if downloaded_cid == cid.to_string() { + return self + .read(cid) + .await? + .ok_or_else(|| anyhow::anyhow!("downloaded file not found: {cid}")); + } + } + Event::DownloadFailure { + cid: event_cid, + error, + } => { + if event_cid == cid.to_string() { + bail!("download failed: {error}"); + } + } + } + } + } + + async fn download_task(self, mut cid_str: String) { + loop { + let tmp_file = self.tmp_path_of(&cid_str); + let url = format!("{}/{}", self.config.base_url, cid_str); + info!("downloading {cid_str} from {url}"); + let result: Result, _> = timeout(self.config.max_download_time, async { + tmp_file + .parent() + .map_or(Ok(()), |p| std::fs::create_dir_all(p))?; + let mut output_io = tokio::fs::File::create(&tmp_file).await?; + let mut response = self + .config + .http_client + .get(url) + .send() + .await? + .error_for_status()?; + let mut size = 0; + while let Some(chunk) = response.chunk().await? { + size += chunk.len(); + if size > self.config.max_file_size { + bail!("file too large"); + } + output_io.write_all(&chunk).await?; + } + Ok(()) + }) + .await; + let event = match result { + Ok(Ok(_)) => { + debug!("downloaded {cid_str}"); + if let Err(err) = std::fs::rename(&tmp_file, self.path_of(&cid_str)) { + error!("failed to rename tmp file: {err:?}"); + } + Event::Downloaded { + cid: cid_str.clone(), + } + } + Ok(Err(err)) => { + debug!("download {cid_str} failed: {err}"); + let _ = std::fs::remove_file(&tmp_file); + Event::DownloadFailure { + cid: cid_str.clone(), + error: err.to_string(), + } + } + Err(_) => { + debug!("download {cid_str} timeout"); + let _ = std::fs::remove_file(&tmp_file); + Event::DownloadFailure { + cid: cid_str.clone(), + error: "timeout".to_string(), + } + } + }; + let mut state = self.state.lock().unwrap(); + state.downloading.remove(&cid_str); + self.config.notify.send(event).ok(); + if let Some(next_cid) = state.pending.pop_first() { + state.downloading.insert(next_cid.clone()); + cid_str = next_cid; + continue; + } + break; + } + } +} diff --git a/wapod-pherry/src/lib.rs b/wapod-pherry/src/lib.rs new file mode 100644 index 0000000..0f74535 --- /dev/null +++ b/wapod-pherry/src/lib.rs @@ -0,0 +1,45 @@ +pub use rpc_client::WorkerClient; + +pub mod endpoints; +pub mod register; +mod rpc_client; + +pub mod bridge; +pub mod chain_state; +pub mod deploy; +pub mod ipfs_downloader; + +mod util { + use anyhow::{Context, Result}; + use core::fmt::Debug; + use std::path::Path; + use tracing::error; + + pub fn read_file(path: impl AsRef) -> Result> { + std::fs::read(path.as_ref()) + .with_context(|| format!("failed to read file: {}", path.as_ref().display())) + } + + pub fn write_file(path: impl AsRef, data: &[u8]) -> Result<()> { + std::fs::write(path.as_ref(), data) + .with_context(|| format!("failed to write file: {}", path.as_ref().display())) + } + + pub trait IgnoreError { + type T; + fn ignore_error(self, prefix: &str) -> Option; + } + + impl IgnoreError for Result { + type T = T; + fn ignore_error(self, prefix: &str) -> Option { + match self { + Ok(v) => Some(v), + Err(err) => { + error!("{prefix}: {err:?}"); + None + } + } + } + } +} diff --git a/wapod-pherry/src/main.rs b/wapod-pherry/src/main.rs new file mode 100644 index 0000000..b28f18e --- /dev/null +++ b/wapod-pherry/src/main.rs @@ -0,0 +1,189 @@ +use std::time::Duration; + +use anyhow::Result; +use clap::{Parser, Subcommand}; +use sp_core::hashing::blake2_256; +use tracing_subscriber::{filter::LevelFilter, EnvFilter}; +use wapod_pherry::{ + bridge::{run_bridge, BridgeConfig}, + deploy, + endpoints::{update_endpoint, UpdateEndpointArgs}, + register::{register, RegisterArgs}, +}; +use wapod_types::{ + ticket::{ticket_account_address, TicketId}, + Address, +}; + +#[derive(Parser, Clone, Debug)] +struct CommonArgs { + #[arg(long, default_value = "ws://localhost:9944/ws")] + node_url: String, + #[arg(long, default_value = "http://localhost:8001")] + worker_url: String, + #[arg(long, default_value_t = String::new())] + token: String, + #[arg(long, default_value = "//Ferdie")] + signer: String, +} + +#[derive(Parser, Clone, Debug)] +#[clap(version, author)] +struct Args { + #[command(subcommand)] + command: Command, +} + +#[derive(Subcommand, Clone, Debug)] +enum Command { + Register { + #[command(flatten)] + other: CommonArgs, + #[arg(long)] + operator: String, + #[arg(long)] + pccs_url: String, + }, + UpdateEndpoint { + #[command(flatten)] + other: CommonArgs, + #[arg(long)] + endpoint: String, + }, + Bridge { + #[command(flatten)] + other: CommonArgs, + /// The operator account. + #[arg(long)] + operator: Option, + /// The PCCS URL. + #[arg(long, default_value = "")] + pccs_url: String, + /// The base URL of the IPFS gateway. + #[arg(long, default_value = "https://ipfs.io/ipfs/")] + ipfs_url: String, + /// The cache directory of IPFS. + #[arg(long, default_value = "./data/ipfs_cache")] + ipfs_cache_dir: String, + /// The maximum number of apps that can be deployed. + #[arg(long, default_value = "128")] + max_apps: usize, + /// The interval in seconds of reporting app metrics. + #[arg(long, default_value = "600")] + metrics_interval: u64, + /// The account to receive rewards. + #[arg(long)] + recipient: String, + /// Waiting for the benchmark app to consume amount of gas until report the init score. + #[arg(long, default_value = "1000000000")] + gas_until_report: u64, + }, + CreateWorkerList { + #[command(flatten)] + other: CommonArgs, + }, + Build { + /// The path to the config file. + #[arg(long, short, default_value = "WapodDeploy.json")] + config: String, + }, + Deploy { + #[command(flatten)] + other: CommonArgs, + /// The path to the config file. + #[arg(long, short, default_value = "WapodDeploy.json")] + config: String, + #[arg(long)] + worker_list: u64, + #[arg(long, default_value = "10000000000")] + deposit: u128, + }, + TicketAddress { + ticket_id: TicketId, + }, +} + +#[tokio::main] +async fn main() -> Result<()> { + let filter = EnvFilter::builder() + .with_default_directive(LevelFilter::INFO.into()) + .from_env_lossy(); + tracing_subscriber::fmt().with_env_filter(filter).init(); + + let args = Args::parse(); + match args.command { + Command::Register { + operator, + pccs_url, + other, + } => { + let args = RegisterArgs { + worker_url: other.worker_url, + token: other.token, + node_url: other.node_url, + signer: other.signer, + operator, + pccs_url, + }; + register(args).await?; + } + Command::UpdateEndpoint { endpoint, other } => { + let args = UpdateEndpointArgs { + worker_url: other.worker_url, + token: other.token, + node_url: other.node_url, + signer: other.signer, + endpoint, + }; + update_endpoint(args).await?; + } + Command::Bridge { + other, + ipfs_url, + ipfs_cache_dir, + max_apps, + metrics_interval, + recipient, + operator, + pccs_url, + gas_until_report, + } => { + let config = BridgeConfig { + node_url: other.node_url, + tx_signer: other.signer, + worker_url: other.worker_url, + worker_token: other.token, + ipfs_base_url: ipfs_url, + ipfs_cache_dir, + max_apps, + metrics_interval: Duration::from_secs(metrics_interval), + recipient, + operator: operator.unwrap_or_default(), + pccs_url, + gas_until_report, + }; + run_bridge(config).await?; + } + Command::CreateWorkerList { other } => { + deploy::create_worker_list(other.node_url, other.signer, other.worker_url, other.token) + .await?; + } + Command::Build { config } => { + deploy::build_manifest(config)?; + } + Command::Deploy { + other, + config, + worker_list, + deposit, + } => { + deploy::deploy_manifest(config, &other.node_url, &other.signer, deposit, worker_list) + .await?; + } + Command::TicketAddress { ticket_id } => { + let address: Address = ticket_account_address(ticket_id, blake2_256); + println!("0x{}", hex_fmt::HexFmt(address)); + } + } + Ok(()) +} diff --git a/wapod-pherry/src/register.rs b/wapod-pherry/src/register.rs new file mode 100644 index 0000000..eb1068d --- /dev/null +++ b/wapod-pherry/src/register.rs @@ -0,0 +1,112 @@ +use std::str::FromStr as _; +use std::time::Duration; + +use anyhow::{Context, Result}; +use phaxt::subxt::utils::AccountId32; +use scale::Encode; +use sgx_attestation::dcap::report::get_collateral; +use tracing::info; +use wapod_rpc::prpc::SignRegisterInfoArgs; +use wapod_rpc::types::AttestationReport; + +use crate::chain_state::{ChainClient, NonceJar}; +use crate::WorkerClient; + +pub struct RegisterArgs { + pub worker_url: String, + pub token: String, + pub node_url: String, + pub signer: String, + pub operator: String, + pub pccs_url: String, +} + +pub async fn register(args: RegisterArgs) -> Result<()> { + let RegisterArgs { + worker_url, + token, + node_url, + signer, + operator, + pccs_url, + } = args; + let worker_client = WorkerClient::new(worker_url, token); + info!("connecting to the chain"); + let chain_client = ChainClient::connect(&node_url, &signer) + .await + .context("failed to connect to the chain")?; + register_with_client( + &chain_client, + &worker_client, + &operator, + &pccs_url, + &mut Default::default(), + ) + .await +} + +pub async fn register_with_client( + chain_client: &ChainClient, + worker_client: &WorkerClient, + operator: &str, + pccs_url: &str, + nonce_jar: &mut NonceJar, +) -> Result<()> { + info!("getting paraid"); + let para_id = chain_client.get_paraid().await?; + let genesis_block_hash = chain_client.genesis_hash(); + let operator = if operator.is_empty() { + None + } else { + Some( + AccountId32::from_str(&operator) + .context("invalid operator")? + .0, + ) + }; + info!("requesting worker to sign register data"); + let register_info = SignRegisterInfoArgs::new(genesis_block_hash.into(), operator, para_id); + let response = worker_client + .operation() + .sign_register_info(register_info) + .await?; + info!("got signed register data"); + let attestation = response.decode_report()?; + let report = match attestation { + Some(AttestationReport::SgxDcap { + quote, + collateral: _, + }) => { + #[derive(Encode)] + pub enum Report { + _SgxIas, + SgxDcap { + quote: Vec, + collateral: Option>, + }, + } + #[derive(Encode)] + pub enum Collateral { + SgxV30(T), + } + + let collateral = get_collateral(pccs_url, "e, Duration::from_secs(10)).await?; + Some(Report::SgxDcap { + quote, + collateral: Some(Collateral::SgxV30(collateral)), + }) + .encode() + } + _ => attestation.encode(), + }; + + chain_client + .register_worker(response.encoded_runtime_info, report, nonce_jar) + .await?; + let info = worker_client.operation().info().await?; + info!( + "worker 0x{} registered successfully", + hex::encode(info.pubkey) + ); + Ok(()) +} diff --git a/wapod-pherry/src/rpc_client.rs b/wapod-pherry/src/rpc_client.rs new file mode 100644 index 0000000..d2f6032 --- /dev/null +++ b/wapod-pherry/src/rpc_client.rs @@ -0,0 +1,65 @@ +use reqwest::Client; +use wapod_rpc::prpc::client::{Error, RequestClient}; +use wapod_rpc::prpc::operation_client::OperationClient; +use wapod_rpc::prpc::server::ProtoError; +use wapod_rpc::prpc::user_client::UserClient; +use wapod_rpc::prpc::Message as _; + +#[derive(Clone)] +pub struct WorkerClient { + base_url: String, + token: String, + http_client: Client, +} + +impl WorkerClient { + pub fn new(base_url: String, token: String) -> Self { + Self { + token, + base_url, + http_client: Client::new(), + } + } + + pub fn operation(&self) -> OperationClient { + OperationClient::new(self.clone()) + } + + pub fn user(&self) -> UserClient { + UserClient::new(self.clone()) + } +} + +impl RequestClient for WorkerClient { + async fn request(&self, path: &str, body: Vec) -> Result, Error> { + let base_url = self.base_url.trim_end_matches('/'); + let url = format!("{}/prpc/{}", base_url, path); + let request_builder = self.http_client.post(url); + let request_builder = if self.token.is_empty() { + request_builder + } else { + request_builder.bearer_auth(&self.token) + }; + let response = request_builder + .body(body) + .send() + .await + .map_err(|err| Error::RpcError(err.to_string()))?; + if !response.status().is_success() { + let error = Error::RpcError(format!("HTTP error: {}", response.status())); + if response.status().as_u16() == 400 { + let Ok(body) = response.bytes().await else { + return Err(error); + }; + let proto_error = ProtoError::decode(body).or(Err(error))?; + return Err(Error::ServerError(proto_error)); + } + return Err(error); + } + let body = response + .bytes() + .await + .map_err(|err| Error::RpcError(err.to_string()))?; + Ok(body.into()) + } +} diff --git a/wapod-types/Cargo.toml b/wapod-types/Cargo.toml new file mode 100644 index 0000000..cb2ed19 --- /dev/null +++ b/wapod-types/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "wapod-types" +version = "0.1.0-dev.1" +edition = "2021" + +description = "Types for wapod interface" +license = "Apache-2.0" +homepage = "https://github.com/Phala-Network/wapo" + +[dependencies] +scale = { version = "3.6.12", package = "parity-scale-codec", default-features = false, features = ["max-encoded-len"]} +scale-info = { version = "2.11.3", default-features = false, features = ["derive"] } +serde = { version = "1.0.203", default-features = false, features = ["derive"] } + +[features] +default = ["std"] +std = [ + "scale/std", + "scale-info/std", + "serde/std", +] diff --git a/wapod-types/src/bench_app.rs b/wapod-types/src/bench_app.rs new file mode 100644 index 0000000..21adc38 --- /dev/null +++ b/wapod-types/src/bench_app.rs @@ -0,0 +1,72 @@ +//! The types used by the benchmark app. + +use scale::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use serde::{Deserialize, Serialize}; + +use crate::{ + crypto::{ + verify::{verify_app_data, Verifiable}, + CryptoProvider, Signature, + }, + metrics::MetricsToken, + primitives::{Address, WorkerPubkey}, +}; + +/// The json response of the benchmark app. + +#[derive( + Default, + Debug, + Serialize, + Deserialize, + Decode, + Encode, + TypeInfo, + MaxEncodedLen, + Clone, + PartialEq, + Eq, +)] +pub struct BenchScore { + /// The score. + pub gas_per_second: u64, + /// The amount of gas consumed to calculate the score. + pub gas_consumed: u64, + /// The timestamp (seconds since UNIX epoch) when the score was recorded. + pub timestamp_secs: u64, + /// The metrics token for the worker. + pub metrics_token: MetricsToken, +} + +/// A message that the benchmark app can emit. +#[derive(Decode, Encode, TypeInfo, MaxEncodedLen, Debug, Clone, PartialEq, Eq)] +pub enum SigningMessage { + /// A benchmark score. This can be submitted to the chain as the worker's initial score. + BenchScore(BenchScore), +} + +/// A signed message. +#[derive(Decode, Encode, TypeInfo, MaxEncodedLen, Debug, Clone, PartialEq, Eq)] +pub struct SignedMessage { + /// The message. + pub message: SigningMessage, + /// The signature of the message. + pub signature: Signature, + /// The public key of the worker that signed the message. + pub worker_pubkey: WorkerPubkey, + /// The address of the app that the message is intended for. + pub app_address: Address, +} + +impl Verifiable for SignedMessage { + fn verify(&self) -> bool { + let encoded_message = self.message.encode(); + verify_app_data::( + &self.app_address, + &encoded_message, + &self.signature, + &self.worker_pubkey, + ) + } +} diff --git a/wapod-types/src/crypto/mod.rs b/wapod-types/src/crypto/mod.rs new file mode 100644 index 0000000..ca8b745 --- /dev/null +++ b/wapod-types/src/crypto/mod.rs @@ -0,0 +1,19 @@ +//! Cryptographic primitives and utilities. + +use crate::{primitives::BoundedVec, ContentType}; + +pub mod query; +pub mod verify; + +/// A cryptographic signature. Used when talking to the pallet. +pub type Signature = BoundedVec; + +/// A type implementing this trait provides cryptographic primitives. +pub trait CryptoProvider { + /// Verify a sr25519 signature. + fn sr25519_verify(public_key: &[u8], message: &[u8], signature: &[u8]) -> bool; + /// Calculate the keccak 256-bit hash of the given data. + fn keccak_256(data: &[u8]) -> [u8; 32]; + /// Calculate the blake2b 256-bit hash of the given data. + fn blake2b_256(data: &[u8]) -> [u8; 32]; +} diff --git a/wapod-types/src/crypto/query.rs b/wapod-types/src/crypto/query.rs new file mode 100644 index 0000000..9898942 --- /dev/null +++ b/wapod-types/src/crypto/query.rs @@ -0,0 +1,98 @@ +//! The query module provides types for the wapod query RPC request and response. + +use alloc::{string::String, vec::Vec}; +use scale::{Decode, Encode}; + +/// The query signature type. +pub type QuerySignature = Signature; + +/// A query request. +#[derive(Clone, Encode, Decode)] +pub struct Query { + /// The dest app address of the query. + pub address: Vec, + /// The path of the query. + pub path: String, + /// The query payload. + pub payload: Vec, +} + + +/// A signature signed by a worker for query response. +#[derive(Encode, Decode, Clone)] +pub struct Signature { + /// The signature type + pub signature_type: SignatureType, + /// The signature of the data + pub signature: Vec, + /// The certificate of the signer + pub signer: S, +} + +/// The signature type +#[derive(Encode, Decode, Clone, Copy)] +pub enum SignatureType { + /// A substrate-flavor ed25519 signature. + Ed25519 = 0, + /// A substrate-flavor sr25519 signature. + Sr25519 = 1, + /// A substrate-flavor ecdsa signature. + Ecdsa = 2, + /// A polkadot-wallet signed ed25519 signature. + Ed25519WrapBytes = 3, + /// A polkadot-wallet signed sr25519 signature. + Sr25519WrapBytes = 4, + /// A polkadot-wallet signed ecdsa signature. + EcdsaWrapBytes = 5, + /// An EIP712 signature. + Eip712 = 6, + /// An EVM-flavor ECDSA signature. + EvmEcdsa = 7, + /// An EVM-flavor ECDSA signature with wrapped bytes. + EvmEcdsaWrapBytes = 8, +} + +/// A root signer. +#[derive(Clone, Encode, Decode)] +pub struct RootSigner { + /// The public key of the root signer. + pub pubkey: Vec, +} + +/// A root signer or a signed certificate. +#[derive(Clone, Encode, Decode)] +pub enum RootOrCertificate { + /// A root signer. + Root(RootSigner), + /// A signed certificate. + Certificate(Certificate), +} + +/// A certificate. +#[derive(Encode, Decode, Clone)] +pub struct Certificate { + /// The body of the certificate + pub body: CertificateBody, + /// An optinal signature of the body signed by a parent certificate. + pub signature: Signature, +} + +/// The body of a certificate. +#[derive(Clone, Encode, Decode, Debug)] +pub struct CertificateBody { + /// The public key of the certificate. + pub pubkey: Vec, + /// The expiration time of the certificate in seconds since the Unix epoch. + pub expiration: u64, + /// The operation scopes that allow the certificate to sign. + pub scopes: Vec, +} + +/// The operation scope of a certificate. +#[derive(Clone, Encode, Decode, Debug)] +pub struct Scope { + /// The application address of the operation. + pub app: Vec, + /// The resources paths that the application. + pub resources: Vec, +} diff --git a/wapod-types/src/crypto/verify.rs b/wapod-types/src/crypto/verify.rs new file mode 100644 index 0000000..1f706ae --- /dev/null +++ b/wapod-types/src/crypto/verify.rs @@ -0,0 +1,53 @@ +//! Verification functions for messages and app data. + +use alloc::vec::Vec; + +use super::{ContentType, CryptoProvider}; + +/// A trait for verifying a message. +pub trait Verifiable { + /// Verify self. + fn verify(&self) -> bool; +} + +/// Verify a message with a given content type. +pub fn verify_message( + content_type: ContentType, + message: &[u8], + signature: &[u8], + public_key: &[u8], +) -> bool { + let message = content_type.wrap_message(message); + Crypto::sr25519_verify(public_key, &message, signature) +} + +/// Verify an app data message. +pub fn verify_app_data( + address: &[u8], + message: &[u8], + signature: &[u8], + public_key: &[u8], +) -> bool { + let message = wrap_app_data(address, message); + Crypto::sr25519_verify(public_key, &message, signature) +} + +/// Wrap an app data message with the app data content type. +/// +/// When an app uses `wapo::ocalls::worker_sign`, the underlying worker sign API will +/// receive the same message as calculated by this function. +pub fn wrap_app_data(address: &[u8], message: &[u8]) -> Vec { + ContentType::AppData.wrap_message_iter(address.iter().chain(message.iter()).copied()) +} + +/// Calculate the user data passed to sgx quote for a given app data. +/// +/// When an app uses `wapo::ocalls::sgx_quote`, the underlying sgx quote API will +/// receive the same user data as calculated by this function. +pub fn sgx_quote_app_data(address: &[u8], message: &[u8]) -> [u8; 64] { + let message = wrap_app_data(address, message); + let hash = Crypto::keccak_256(&message); + let mut user_data = hash.to_vec(); + user_data.extend_from_slice([0u8; 32].as_ref()); + user_data.try_into().expect("execpted 64 bytes") +} diff --git a/wapod-types/src/helpers.rs b/wapod-types/src/helpers.rs new file mode 100644 index 0000000..898f3ed --- /dev/null +++ b/wapod-types/src/helpers.rs @@ -0,0 +1 @@ +pub mod scale; diff --git a/wapod-types/src/helpers/scale.rs b/wapod-types/src/helpers/scale.rs new file mode 100644 index 0000000..31f5f32 --- /dev/null +++ b/wapod-types/src/helpers/scale.rs @@ -0,0 +1,26 @@ +/// Input that adds infinite number of zero after wrapped input. +pub(crate) struct TrailingZeroInput<'a>(&'a [u8]); + +impl<'a> TrailingZeroInput<'a> { + /// Create a new instance from the given byte array. + pub fn new(data: &'a [u8]) -> Self { + Self(data) + } +} + +impl<'a> scale::Input for TrailingZeroInput<'a> { + fn remaining_len(&mut self) -> Result, scale::Error> { + Ok(None) + } + + fn read(&mut self, into: &mut [u8]) -> Result<(), scale::Error> { + let len_from_inner = into.len().min(self.0.len()); + into[..len_from_inner].copy_from_slice(&self.0[..len_from_inner]); + for i in &mut into[len_from_inner..] { + *i = 0; + } + self.0 = &self.0[len_from_inner..]; + + Ok(()) + } +} diff --git a/wapod-types/src/lib.rs b/wapod-types/src/lib.rs new file mode 100644 index 0000000..639b7d9 --- /dev/null +++ b/wapod-types/src/lib.rs @@ -0,0 +1,55 @@ +//! Types that third-party softwares can use to talk to a wapod worker. + +#![cfg_attr(not(feature = "std"), no_std)] +#![deny(missing_docs)] + +extern crate alloc; + +use alloc::vec::Vec; +use core::fmt::Debug; + +pub use primitives::{Address, Bytes32, Hash, WorkerPubkey}; +pub use scale; + +pub mod bench_app; +pub mod crypto; +pub mod metrics; +pub mod primitives; +pub mod session; +pub mod ticket; +pub mod worker; + +mod helpers; + +/// The content type of a signed message. +#[derive(Clone, Copy, Debug)] +#[repr(u8)] +pub enum ContentType { + /// A response to an RPC request. + RpcResponse = 1, + /// An endpoint info message. + EndpointInfo = 2, + // A gap to avoid conflicts with pruntime v2 + /// Metrics of applications. + Metrics = 100, + /// App requested worker signed data. + AppData = 101, + /// Worker attestation. + WorkerAttestation = 102, + /// Worker description. + WorkerDescription = 103, + /// Worker session update. + SessionUpdate = 104, +} + +impl ContentType { + /// Wrap a message with the content type to create a signed message. + pub fn wrap_message(&self, message: impl AsRef<[u8]>) -> Vec { + self.wrap_message_iter(message.as_ref().iter().copied()) + } + + /// Wrap a message with the content type to create a signed message. + pub fn wrap_message_iter(&self, message: impl IntoIterator) -> Vec { + [0xff_u8, *self as u8].into_iter().chain(message).collect() + } +} diff --git a/wapod-types/src/metrics.rs b/wapod-types/src/metrics.rs new file mode 100644 index 0000000..7fff78e --- /dev/null +++ b/wapod-types/src/metrics.rs @@ -0,0 +1,129 @@ +//! Types for app metrics. + +use scale::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use serde::{Deserialize, Serialize}; + +use crate::{ + crypto::{ + verify::{verify_message, Verifiable}, + CryptoProvider, Signature, + }, + primitives::{BoundedVec, WorkerPubkey}, + ticket::TicketId, + Address, Bytes32, ContentType, +}; + +/// The metrics token. +#[derive( + Decode, + Encode, + TypeInfo, + MaxEncodedLen, + Debug, + Clone, + PartialEq, + Eq, + Default, + Serialize, + Deserialize, +)] +pub struct MetricsToken { + /// The sequence number of the metrics token. Reset to 0 when the worker session is reset. + pub sn: u64, + /// The session id. + pub session: [u8; 32], + /// A random nonce generated by the worker. + pub nonce: [u8; 32], +} + +/// The app metrics. +#[derive(Debug, Encode, Decode, TypeInfo, MaxEncodedLen, Clone, PartialEq, Eq, Default)] +pub struct AppMetrics { + /// The address of the app. + pub address: Address, + /// The session id of the app. + pub session: Bytes32, + /// The accumulated time that the app has been running. + pub running_time_ms: u64, + /// The accumulated gas consumed by the app. + pub gas_consumed: u64, + /// The accumulated network ingress of the app in bytes. + pub network_ingress: u64, + /// The accumulated network egress of the app in bytes. + pub network_egress: u64, + /// The accumulated storage read of the app in bytes. + pub storage_read: u64, + /// The accumulated storage write of the app in bytes. + pub storage_write: u64, + /// The storage used by the app. (not used yet) + pub storage_used: u128, + /// The memory used by the app. (not used yet) + pub memory_used: u128, + /// The tip that the worker received for running the app. + pub tip: u64, + /// The counter of the number of times the app has been started. + pub starts: u64, +} + +/// The maximum number of app metrics in a single submission. +pub const MAX_APPS_METRICS: usize = 64; +/// The maximum number of claim tickets per app in a single submission. +pub const MAX_CLAIM_TICKETS: usize = 3; + +/// A list of app metrics. +#[derive(Debug, Encode, Decode, TypeInfo, MaxEncodedLen, Clone, PartialEq, Eq)] +pub struct AppsMetrics { + /// The metrics token generated by the worker. + pub token: MetricsToken, + /// The app metrics. + pub apps: BoundedVec, +} + +/// A versioned apps metrics. +#[derive(Debug, Encode, Decode, TypeInfo, MaxEncodedLen, Clone, PartialEq, Eq)] +pub enum VersionedAppsMetrics { + /// V0 + V0(AppsMetrics), +} + +/// A map from app address to a list of claim tickets. +pub type ClaimMap = + BoundedVec<(Address, BoundedVec), MAX_APPS_METRICS>; + +/// A signed apps metrics. +#[derive(Debug, Encode, Decode, TypeInfo, MaxEncodedLen, Clone, PartialEq, Eq)] +pub struct SignedAppsMetrics { + /// The metrics. + pub metrics: VersionedAppsMetrics, + /// The signature of the metrics. + pub signature: Signature, + /// The public key of the worker that signed the metrics. + pub worker_pubkey: WorkerPubkey, +} + +impl SignedAppsMetrics { + /// Construct a new signed apps metrics. + pub fn new( + metrics: VersionedAppsMetrics, + signature: BoundedVec, + worker_pubkey: WorkerPubkey, + ) -> Self { + Self { + metrics, + signature, + worker_pubkey, + } + } +} +impl Verifiable for SignedAppsMetrics { + fn verify(&self) -> bool { + let encoded_message = self.metrics.encode(); + verify_message::( + ContentType::Metrics, + &encoded_message, + &self.signature, + &self.worker_pubkey, + ) + } +} diff --git a/wapod-types/src/primitives.rs b/wapod-types/src/primitives.rs new file mode 100644 index 0000000..f47bcfd --- /dev/null +++ b/wapod-types/src/primitives.rs @@ -0,0 +1,208 @@ +//! Some basic types used in the Wapod project. + +use alloc::string::{String, ToString}; +use alloc::vec::Vec; + +use core::ops::Deref; +use scale::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; + +/// A 32-byte array. +pub type Bytes32 = [u8; 32]; +/// Address of an application or a worker. +pub type Address = Bytes32; +/// A blake2b hash value. +pub type Hash = Bytes32; +/// Worker public key. +pub type WorkerPubkey = Bytes32; + +/// A bounded vector with a maximum length. +#[derive(Debug, Clone, PartialEq, Eq, Encode)] +pub struct BoundedVec(pub Vec); + +impl BoundedVec { + /// The maximum length of the vector. + pub fn max_len(&self) -> usize { + B + } + + /// The current length of the vector. + pub fn len(&self) -> usize { + self.0.len() + } + + /// Whether the vector is empty. + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + + /// Push a value to the vector. + pub fn push(&mut self, value: T) -> Result<(), T> { + if self.len() >= B { + return Err(value); + } + self.0.push(value); + Ok(()) + } + + /// Pop a value from the vector. + pub fn pop(&mut self) -> Option { + self.0.pop() + } + + /// Clear the vector. + pub fn clear(&mut self) { + self.0.clear() + } + + /// Iterate over the vector. + pub fn iter(&self) -> core::slice::Iter<'_, T> { + self.0.iter() + } + + /// Mutably iterate over the vector. + pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, T> { + self.0.iter_mut() + } + + /// As a slice. + pub fn as_slice(&self) -> &[T] { + self.0.as_slice() + } + + /// As a mutable slice. + pub fn as_mut_slice(&mut self) -> &mut [T] { + self.0.as_mut_slice() + } + + /// Convert into the inner vector. + pub fn into_inner(self) -> Vec { + self.0 + } +} + +impl Default for BoundedVec { + fn default() -> Self { + Self(Default::default()) + } +} + +impl Decode for BoundedVec { + fn decode(input: &mut I) -> Result { + let vec = Vec::::decode(input)?; + if vec.len() > B { + return Err(scale::Error::from("BoundedVec: length exceeds bound")); + } + Ok(Self(vec)) + } +} + +impl Deref for BoundedVec { + type Target = [T]; + + fn deref(&self) -> &Self::Target { + self.0.deref() + } +} + +impl From> for BoundedVec { + fn from(vec: Vec) -> Self { + Self(vec) + } +} + +impl From<&[T]> for BoundedVec +where + T: Clone, +{ + fn from(slice: &[T]) -> Self { + Self(slice.to_vec()) + } +} + +impl From> for Vec { + fn from(bounded_vec: BoundedVec) -> Self { + bounded_vec.0 + } +} +impl MaxEncodedLen for BoundedVec { + fn max_encoded_len() -> usize { + B * T::max_encoded_len() + } +} + +impl TypeInfo for BoundedVec { + type Identity = as TypeInfo>::Identity; + + fn type_info() -> scale_info::Type { + as TypeInfo>::type_info() + } +} + +impl IntoIterator for BoundedVec { + type Item = as IntoIterator>::Item; + type IntoIter = as IntoIterator>::IntoIter; + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +/// A bounded string with a maximum length. +#[derive(Debug, Clone, PartialEq, Eq, Encode, Default)] +pub struct BoundedString(pub String); + +impl Deref for BoundedString { + type Target = str; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl From for BoundedString { + fn from(s: String) -> Self { + Self(s) + } +} + +impl From<&str> for BoundedString { + fn from(s: &str) -> Self { + Self(s.to_string()) + } +} + +impl From> for String { + fn from(bounded_string: BoundedString) -> Self { + bounded_string.0 + } +} + +impl TypeInfo for BoundedString { + type Identity = ::Identity; + + fn type_info() -> scale_info::Type { + ::type_info() + } +} + +impl Decode for BoundedString { + fn decode(input: &mut I) -> Result { + let s = String::decode(input)?; + if s.as_bytes().len() > B { + return Err(scale::Error::from("BoundedString: length exceeds bound")); + } + Ok(Self(s)) + } +} + +impl core::fmt::Display for BoundedString { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.0) + } +} + +impl MaxEncodedLen for BoundedString { + fn max_encoded_len() -> usize { + B + } +} diff --git a/wapod-types/src/session.rs b/wapod-types/src/session.rs new file mode 100644 index 0000000..27feead --- /dev/null +++ b/wapod-types/src/session.rs @@ -0,0 +1,74 @@ +//! Worker session update message and its signed version. + +use scale::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; + +use crate::{ + crypto::{ + verify::{verify_message, Verifiable}, + CryptoProvider, Signature, + }, + primitives::{BoundedVec, WorkerPubkey}, + Address, ContentType, +}; + +/// A session update info. +#[derive(Debug, Clone, Encode, Decode, TypeInfo, MaxEncodedLen, PartialEq, Eq)] +pub struct SessionUpdate { + /// The session id. + pub session: [u8; 32], + /// The nonce for the session generated by the worker. + pub nonce: [u8; 32], + /// The account address that used to receive the settlement payment. + pub recipient: BoundedVec, +} + +impl SessionUpdate { + /// Calculate the session id from the seed and nonce. + /// + /// The session id is calculated as `blake2b_256(nonce || metrics_nonce)` where `nonce` is generated + /// on-the-fly by the worker and `metrics_nonce` should be the last metrics nonce submitted to the chain. + pub fn calc_session_id( + nonce: [u8; 32], + metrics_nonce: &[u8], + ) -> [u8; 32] { + Crypto::blake2b_256(&[&nonce, metrics_nonce].concat()) + } + + /// Create a new session update. + pub fn new( + nonce: [u8; 32], + metrics_nonce: &[u8], + recipient: Address, + ) -> Self { + let session = Self::calc_session_id::(nonce, metrics_nonce); + Self { + session, + nonce, + recipient: recipient.to_vec().into(), + } + } +} + +/// A signed session update. +#[derive(Debug, Clone, Encode, Decode, TypeInfo, PartialEq, Eq)] +pub struct SignedSessionUpdate { + /// The session update data. + pub update: SessionUpdate, + /// The signature of the update. + pub signature: Signature, + /// The public key of the worker that signed the update. + pub public_key: WorkerPubkey, +} + +impl Verifiable for SignedSessionUpdate { + fn verify(&self) -> bool { + let message = self.update.encode(); + verify_message::( + ContentType::SessionUpdate, + &message, + &self.signature, + &self.public_key, + ) + } +} diff --git a/wapod-types/src/ticket.rs b/wapod-types/src/ticket.rs new file mode 100644 index 0000000..dd2135f --- /dev/null +++ b/wapod-types/src/ticket.rs @@ -0,0 +1,168 @@ +//! Types related to the ticket system. + +use alloc::string::String; +use alloc::vec::Vec; + +use scale::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use serde::{Deserialize, Serialize}; + +use crate::{ + crypto::{ + verify::{verify_message, Verifiable}, + CryptoProvider, Signature, + }, + helpers::scale::TrailingZeroInput, + metrics::AppMetrics, + primitives::{BoundedString, WorkerPubkey}, + ContentType, +}; + +/// The ticket id type. +pub type TicketId = u64; +/// The balance type. +pub type Balance = u128; + +/// The manifest of an application. +#[derive(Decode, Encode, TypeInfo, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct AppManifest { + /// The spec version of the manifest. + pub version: u32, + /// The hash of the app's code. + /// Example: "sha256:1234567812345678123456781234567812345678123456781234567812345678" + pub code_hash: String, + /// The arguments of the app. + pub args: Vec, + /// The environment variables of the app. + pub env_vars: Vec<(String, String)>, + /// The start mode of the app. + pub on_demand: bool, + /// Whether the app can run multiple instances in a single worker. + pub resizable: bool, + /// The maximum size of the query payload. + pub max_query_size: u32, + /// The optional label of the app. + pub label: String, + /// The blobs that the app required to run. + /// + /// Pair of (hash, cid). + pub required_blobs: Vec<(String, String)>, +} + +impl AppManifest { + /// Calculate the address of the application. + pub fn address(&self, blake2_256_fn: fn(&[u8]) -> [u8; 32]) -> [u8; 32] { + blake2_256_fn(&self.encode()) + } +} + +/// Resource prices. +#[derive(Encode, Decode, TypeInfo, Default, MaxEncodedLen, Debug, Clone, PartialEq, Eq)] +pub struct Prices { + /// The general fee per second. + pub general_fee_per_second: Option, + /// The gas price. (balance per gas) + pub gas_price: Option, + /// The network ingress price. (balance per byte) + pub net_ingress_price: Option, + /// The network egress price. (balance per byte) + pub net_egress_price: Option, + /// The storage read price. (balance per byte) + pub storage_read_price: Option, + /// The storage write price. (balance per byte) + pub storage_write_price: Option, + /// The storage price. (balance per MB*second) + pub storage_price: Option, + /// The memory price. (balance per KB*second) + pub memory_price: Option, + /// The tip price. (balance per tip) + pub tip_price: Option, +} + +impl Prices { + /// Check if the prices are empty. + pub fn is_empty(&self) -> bool { + self == &Self::default() + } + + /// Calculate the cost of the given metrics. + pub fn cost_of(&self, rhs: &AppMetrics) -> Balance { + let mut total: Balance = 0; + macro_rules! add_mul { + ($price: expr, $usage: expr) => { + if let Some(price) = $price { + let cost = price.saturating_mul($usage as Balance); + total = total.saturating_add(cost); + } + }; + } + let running_time = rhs.running_time_ms / 1000; + add_mul!(self.general_fee_per_second, running_time); + add_mul!(self.gas_price, rhs.gas_consumed); + add_mul!(self.net_ingress_price, rhs.network_ingress); + add_mul!(self.net_egress_price, rhs.network_egress); + add_mul!(self.storage_read_price, rhs.storage_read); + add_mul!(self.storage_write_price, rhs.storage_write); + add_mul!(self.storage_price, rhs.storage_used); + add_mul!(self.memory_price, rhs.memory_used); + add_mul!(self.tip_price, rhs.tip); + total + } + + /// Merge two prices together. If a field is present in both, the one in `self` will be used. + pub fn merge(self, other: &Self) -> Self { + Self { + general_fee_per_second: self.general_fee_per_second.or(other.general_fee_per_second), + gas_price: self.gas_price.or(other.gas_price), + net_ingress_price: self.net_ingress_price.or(other.net_ingress_price), + net_egress_price: self.net_egress_price.or(other.net_egress_price), + storage_read_price: self.storage_read_price.or(other.storage_read_price), + storage_write_price: self.storage_write_price.or(other.storage_write_price), + storage_price: self.storage_price.or(other.storage_price), + memory_price: self.memory_price.or(other.memory_price), + tip_price: self.tip_price.or(other.tip_price), + } + } +} + +/// A worker description. +#[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] +pub struct WorkerDescription { + /// The resource prices of the worker. + pub prices: Prices, + /// The description text of the worker. + pub description: BoundedString<1024>, +} + +/// A signed worker description. +#[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq, MaxEncodedLen)] +pub struct SignedWorkerDescription { + /// The description content. + pub worker_description: WorkerDescription, + /// The signature of the description. + pub signature: Signature, + /// The public key of the worker. + pub worker_pubkey: WorkerPubkey, +} + +impl Verifiable for SignedWorkerDescription { + fn verify(&self) -> bool { + let encoded_message = self.worker_description.encode(); + verify_message::( + ContentType::WorkerDescription, + &encoded_message, + &self.signature, + &self.worker_pubkey, + ) + } +} + +/// Calculate the deposit account id of a ticket. +pub fn ticket_account_address(ticket_id: TicketId, blake2_256_fn: fn(&[u8]) -> [u8; 32]) -> T +where + T: Encode + Decode, +{ + let hash = blake2_256_fn(&(b"wapod/ticket/", ticket_id).encode()); + T::decode(&mut TrailingZeroInput::new(&hash)) + .expect("Decoding zero-padded account id should always succeed; qed") +} diff --git a/wapod-types/src/worker.rs b/wapod-types/src/worker.rs new file mode 100644 index 0000000..7a227a1 --- /dev/null +++ b/wapod-types/src/worker.rs @@ -0,0 +1,63 @@ +//! Worker registration info and attestation report. + +use alloc::string::String; +use alloc::vec::Vec; +use scale::{Decode, Encode}; +use scale_info::TypeInfo; + +use crate::primitives::{Address, Hash, WorkerPubkey}; + +/// Worker registration info. +#[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq)] +pub struct WorkerRegistrationInfoV2 { + /// The version of the worker. + pub version: u32, + /// The worker's machine ID. (deprecated) + pub machine_id: Vec, + /// The worker's public key. + pub pubkey: WorkerPubkey, + /// The worker's ECDH public key. + pub ecdh_pubkey: WorkerPubkey, + /// The blockchain genesis block hash used to initialize the worker. + pub genesis_block_hash: Hash, + /// The worker's features. (deprecated) + pub features: Vec, + /// The operator account ID that can control the worker. + pub operator: Option
, + /// The parachain ID that the worker is registered to. + pub para_id: u32, + /// The maximum consensus version that the worker supports. (deprecated) + pub max_consensus_version: u32, +} + +/// An attestation report. +#[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq)] +pub enum AttestationReport { + /// An IAS attestation report. (deprecated) + SgxIas, + /// A DCAP attestation report. + SgxDcap { + /// The sgx quote generated by the worker. + quote: Vec, + /// The collateral got from a PCCS server. + collateral: Option<()>, + }, +} + +/// Endpoints payload. +#[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq)] +pub enum VersionedWorkerEndpoints { + /// V1 + V1(Vec), +} + +/// Payload of a worker endpoint message. +#[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq)] +pub struct WorkerEndpointPayload { + /// Worker public key. + pub pubkey: WorkerPubkey, + /// Worker versioned endpoints. + pub versioned_endpoints: VersionedWorkerEndpoints, + /// The time when the message was signed. + pub signing_time: u64, +} From c793a75319368bf2ab3096f68b4e8fb42daf5ae0 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Thu, 18 Jul 2024 10:34:14 +0800 Subject: [PATCH 3/8] Remove log --- examples/benchmark/src/bench.rs | 6 +++--- examples/benchmark/src/main.rs | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/examples/benchmark/src/bench.rs b/examples/benchmark/src/bench.rs index b6ee757..bd5dfb3 100644 --- a/examples/benchmark/src/bench.rs +++ b/examples/benchmark/src/bench.rs @@ -6,12 +6,12 @@ fn sha256(data: &[u8]) -> [u8; 32] { } pub async fn benchmark() { - let mut init = sha256(b"init"); + let mut buffer = sha256(b"init"); loop { for _ in 0..10000 { - init = sha256(&init); + buffer = sha256(&buffer); } - std::hint::black_box(&init); + std::hint::black_box(&buffer); wapo::time::breath().await; } } diff --git a/examples/benchmark/src/main.rs b/examples/benchmark/src/main.rs index 38bd4d1..86acf1e 100644 --- a/examples/benchmark/src/main.rs +++ b/examples/benchmark/src/main.rs @@ -6,8 +6,6 @@ mod query; #[wapo::main] async fn main() { wapo::logger::init(); - let filter_str = std::env::var("RUST_LOG").unwrap_or_else(|_| "info".to_string()); - log::info!("benchmark app started, log filter: {filter_str}"); tokio::select! { _ = bench::benchmark() => {} _ = query::query_serve() => {} From 79f71d611b41b0f1c5d1f0d498ca894619d48561 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Thu, 18 Jul 2024 10:34:14 +0800 Subject: [PATCH 4/8] Remove log --- examples/benchmark/src/bench.rs | 6 +++--- examples/benchmark/src/main.rs | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/examples/benchmark/src/bench.rs b/examples/benchmark/src/bench.rs index b6ee757..bd5dfb3 100644 --- a/examples/benchmark/src/bench.rs +++ b/examples/benchmark/src/bench.rs @@ -6,12 +6,12 @@ fn sha256(data: &[u8]) -> [u8; 32] { } pub async fn benchmark() { - let mut init = sha256(b"init"); + let mut buffer = sha256(b"init"); loop { for _ in 0..10000 { - init = sha256(&init); + buffer = sha256(&buffer); } - std::hint::black_box(&init); + std::hint::black_box(&buffer); wapo::time::breath().await; } } diff --git a/examples/benchmark/src/main.rs b/examples/benchmark/src/main.rs index 38bd4d1..86acf1e 100644 --- a/examples/benchmark/src/main.rs +++ b/examples/benchmark/src/main.rs @@ -6,8 +6,6 @@ mod query; #[wapo::main] async fn main() { wapo::logger::init(); - let filter_str = std::env::var("RUST_LOG").unwrap_or_else(|_| "info".to_string()); - log::info!("benchmark app started, log filter: {filter_str}"); tokio::select! { _ = bench::benchmark() => {} _ = query::query_serve() => {} From 85626ff60cb9ccb60ea8968a866d5c96ab6b665d Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Thu, 18 Jul 2024 10:44:43 +0800 Subject: [PATCH 5/8] bench: Use warn instead of info for net time failures --- examples/benchmark/src/query.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/benchmark/src/query.rs b/examples/benchmark/src/query.rs index 91db6ae..769b5ff 100644 --- a/examples/benchmark/src/query.rs +++ b/examples/benchmark/src/query.rs @@ -1,7 +1,7 @@ use anyhow::{bail, Result}; use futures::stream::FuturesUnordered; use futures::StreamExt as _; -use log::{debug, info}; +use log::{debug, info, warn}; use std::time::{Duration, Instant, SystemTime}; use tokio::sync::mpsc::Sender; @@ -59,7 +59,7 @@ async fn score_update(tx: Sender) { wapo::ocall::app_gas_consumed().expect("failed to get gas consumed"); debug!("net_start_time: {:?}", net_start_time); debug!("gas_at_start: {:?}", gas_at_start); - wapo::time::sleep(Duration::from_secs(30)).await; + wapo::time::sleep(Duration::from_secs(60)).await; let (gas_at_end, token) = wapo::ocall::app_gas_consumed().expect("failed to get gas consumed"); let local_elapsed = local_start_time.elapsed(); @@ -67,14 +67,14 @@ async fn score_update(tx: Sender) { debug!("net_end_time: {:?}", net_end_time); debug!("gas_at_end: {:?}", gas_at_end); match (&net_start_time, &net_end_time) { - (Ok(start_time), Ok(end_time)) => { - let Ok(net_elapsed) = end_time.duration_since(*start_time) else { - info!("invalid net time, skipping score update"); + (Ok(net_start_time), Ok(net_end_time)) => { + let Ok(net_elapsed) = net_end_time.duration_since(*net_start_time) else { + warn!("invalid net time, skipping score update"); continue; }; let diff = local_elapsed.as_secs_f64() - net_elapsed.as_secs_f64(); - if diff.abs() > 10_f64 { - info!("time diff between local and net is too large: {diff}"); + if diff.abs() > 5_f64 { + warn!("time diff between local and net is too large: {diff}"); continue; } let gas_diff = gas_at_end.saturating_sub(gas_at_start); @@ -83,7 +83,7 @@ async fn score_update(tx: Sender) { let score = BenchScore { gas_per_second: score, gas_consumed: gas_at_end, - timestamp_secs: end_time + timestamp_secs: net_end_time .duration_since(SystemTime::UNIX_EPOCH) .expect("failed to get timestamp") .as_secs(), @@ -92,7 +92,7 @@ async fn score_update(tx: Sender) { tx.send(score).await.expect("failed to send score"); } _ => { - info!("failed to get net time, skipping score update"); + warn!("failed to get net time, skipping score update"); } } } From 561e59bc96e1b81512f5de738d34c391bca5ae38 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Thu, 18 Jul 2024 10:44:43 +0800 Subject: [PATCH 6/8] bench: Use warn instead of info for net time failures --- examples/benchmark/src/query.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/benchmark/src/query.rs b/examples/benchmark/src/query.rs index 91db6ae..769b5ff 100644 --- a/examples/benchmark/src/query.rs +++ b/examples/benchmark/src/query.rs @@ -1,7 +1,7 @@ use anyhow::{bail, Result}; use futures::stream::FuturesUnordered; use futures::StreamExt as _; -use log::{debug, info}; +use log::{debug, info, warn}; use std::time::{Duration, Instant, SystemTime}; use tokio::sync::mpsc::Sender; @@ -59,7 +59,7 @@ async fn score_update(tx: Sender) { wapo::ocall::app_gas_consumed().expect("failed to get gas consumed"); debug!("net_start_time: {:?}", net_start_time); debug!("gas_at_start: {:?}", gas_at_start); - wapo::time::sleep(Duration::from_secs(30)).await; + wapo::time::sleep(Duration::from_secs(60)).await; let (gas_at_end, token) = wapo::ocall::app_gas_consumed().expect("failed to get gas consumed"); let local_elapsed = local_start_time.elapsed(); @@ -67,14 +67,14 @@ async fn score_update(tx: Sender) { debug!("net_end_time: {:?}", net_end_time); debug!("gas_at_end: {:?}", gas_at_end); match (&net_start_time, &net_end_time) { - (Ok(start_time), Ok(end_time)) => { - let Ok(net_elapsed) = end_time.duration_since(*start_time) else { - info!("invalid net time, skipping score update"); + (Ok(net_start_time), Ok(net_end_time)) => { + let Ok(net_elapsed) = net_end_time.duration_since(*net_start_time) else { + warn!("invalid net time, skipping score update"); continue; }; let diff = local_elapsed.as_secs_f64() - net_elapsed.as_secs_f64(); - if diff.abs() > 10_f64 { - info!("time diff between local and net is too large: {diff}"); + if diff.abs() > 5_f64 { + warn!("time diff between local and net is too large: {diff}"); continue; } let gas_diff = gas_at_end.saturating_sub(gas_at_start); @@ -83,7 +83,7 @@ async fn score_update(tx: Sender) { let score = BenchScore { gas_per_second: score, gas_consumed: gas_at_end, - timestamp_secs: end_time + timestamp_secs: net_end_time .duration_since(SystemTime::UNIX_EPOCH) .expect("failed to get timestamp") .as_secs(), @@ -92,7 +92,7 @@ async fn score_update(tx: Sender) { tx.send(score).await.expect("failed to send score"); } _ => { - info!("failed to get net time, skipping score update"); + warn!("failed to get net time, skipping score update"); } } } From 131de7d48147ed9f13833a60e9e8d5e541f3a22c Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Thu, 18 Jul 2024 10:54:03 +0800 Subject: [PATCH 7/8] code style --- examples/benchmark/src/query.rs | 56 ++++++++++++++++----------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/examples/benchmark/src/query.rs b/examples/benchmark/src/query.rs index 769b5ff..a82e852 100644 --- a/examples/benchmark/src/query.rs +++ b/examples/benchmark/src/query.rs @@ -59,42 +59,42 @@ async fn score_update(tx: Sender) { wapo::ocall::app_gas_consumed().expect("failed to get gas consumed"); debug!("net_start_time: {:?}", net_start_time); debug!("gas_at_start: {:?}", gas_at_start); + wapo::time::sleep(Duration::from_secs(60)).await; + let (gas_at_end, token) = wapo::ocall::app_gas_consumed().expect("failed to get gas consumed"); let local_elapsed = local_start_time.elapsed(); let net_end_time = net_now().await; debug!("net_end_time: {:?}", net_end_time); debug!("gas_at_end: {:?}", gas_at_end); - match (&net_start_time, &net_end_time) { - (Ok(net_start_time), Ok(net_end_time)) => { - let Ok(net_elapsed) = net_end_time.duration_since(*net_start_time) else { - warn!("invalid net time, skipping score update"); - continue; - }; - let diff = local_elapsed.as_secs_f64() - net_elapsed.as_secs_f64(); - if diff.abs() > 5_f64 { - warn!("time diff between local and net is too large: {diff}"); - continue; - } - let gas_diff = gas_at_end.saturating_sub(gas_at_start); - let score = gas_diff.saturating_div(local_elapsed.as_secs()); - debug!("score: {:?}", score); - let score = BenchScore { - gas_per_second: score, - gas_consumed: gas_at_end, - timestamp_secs: net_end_time - .duration_since(SystemTime::UNIX_EPOCH) - .expect("failed to get timestamp") - .as_secs(), - metrics_token: token, - }; - tx.send(score).await.expect("failed to send score"); - } - _ => { - warn!("failed to get net time, skipping score update"); - } + + let (Ok(net_start_time), Ok(net_end_time)) = (&net_start_time, &net_end_time) else { + warn!("failed to get net time, skipping score update"); + continue; + }; + let Ok(net_elapsed) = net_end_time.duration_since(*net_start_time) else { + warn!("invalid net time, skipping score update"); + continue; + }; + let diff = local_elapsed.as_secs_f64() - net_elapsed.as_secs_f64(); + if diff.abs() > 5_f64 { + warn!("time diff between local and net is too large: {diff}"); + continue; } + let gas_diff = gas_at_end.saturating_sub(gas_at_start); + let score = gas_diff.saturating_div(local_elapsed.as_secs()); + debug!("score: {:?}", score); + let score = BenchScore { + gas_per_second: score, + gas_consumed: gas_at_end, + timestamp_secs: net_end_time + .duration_since(SystemTime::UNIX_EPOCH) + .expect("failed to get timestamp") + .as_secs(), + metrics_token: token, + }; + tx.send(score).await.expect("failed to send score"); } } From 7c3848fbb8fecd88b227cb723c10d21d081cb36c Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Thu, 18 Jul 2024 10:54:03 +0800 Subject: [PATCH 8/8] code style --- examples/benchmark/src/query.rs | 56 ++++++++++++++++----------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/examples/benchmark/src/query.rs b/examples/benchmark/src/query.rs index 769b5ff..a82e852 100644 --- a/examples/benchmark/src/query.rs +++ b/examples/benchmark/src/query.rs @@ -59,42 +59,42 @@ async fn score_update(tx: Sender) { wapo::ocall::app_gas_consumed().expect("failed to get gas consumed"); debug!("net_start_time: {:?}", net_start_time); debug!("gas_at_start: {:?}", gas_at_start); + wapo::time::sleep(Duration::from_secs(60)).await; + let (gas_at_end, token) = wapo::ocall::app_gas_consumed().expect("failed to get gas consumed"); let local_elapsed = local_start_time.elapsed(); let net_end_time = net_now().await; debug!("net_end_time: {:?}", net_end_time); debug!("gas_at_end: {:?}", gas_at_end); - match (&net_start_time, &net_end_time) { - (Ok(net_start_time), Ok(net_end_time)) => { - let Ok(net_elapsed) = net_end_time.duration_since(*net_start_time) else { - warn!("invalid net time, skipping score update"); - continue; - }; - let diff = local_elapsed.as_secs_f64() - net_elapsed.as_secs_f64(); - if diff.abs() > 5_f64 { - warn!("time diff between local and net is too large: {diff}"); - continue; - } - let gas_diff = gas_at_end.saturating_sub(gas_at_start); - let score = gas_diff.saturating_div(local_elapsed.as_secs()); - debug!("score: {:?}", score); - let score = BenchScore { - gas_per_second: score, - gas_consumed: gas_at_end, - timestamp_secs: net_end_time - .duration_since(SystemTime::UNIX_EPOCH) - .expect("failed to get timestamp") - .as_secs(), - metrics_token: token, - }; - tx.send(score).await.expect("failed to send score"); - } - _ => { - warn!("failed to get net time, skipping score update"); - } + + let (Ok(net_start_time), Ok(net_end_time)) = (&net_start_time, &net_end_time) else { + warn!("failed to get net time, skipping score update"); + continue; + }; + let Ok(net_elapsed) = net_end_time.duration_since(*net_start_time) else { + warn!("invalid net time, skipping score update"); + continue; + }; + let diff = local_elapsed.as_secs_f64() - net_elapsed.as_secs_f64(); + if diff.abs() > 5_f64 { + warn!("time diff between local and net is too large: {diff}"); + continue; } + let gas_diff = gas_at_end.saturating_sub(gas_at_start); + let score = gas_diff.saturating_div(local_elapsed.as_secs()); + debug!("score: {:?}", score); + let score = BenchScore { + gas_per_second: score, + gas_consumed: gas_at_end, + timestamp_secs: net_end_time + .duration_since(SystemTime::UNIX_EPOCH) + .expect("failed to get timestamp") + .as_secs(), + metrics_token: token, + }; + tx.send(score).await.expect("failed to send score"); } }