From 640809cec66368de32a9f466b4a1c1e17147a0d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Tue, 16 Jul 2024 17:21:37 +0000 Subject: [PATCH 01/38] fix(polka-storage): remove unused primitives cli --- primitives/cli/Cargo.toml | 13 ------------- primitives/cli/src/lib.rs | 1 - 2 files changed, 14 deletions(-) delete mode 100644 primitives/cli/Cargo.toml delete mode 100644 primitives/cli/src/lib.rs diff --git a/primitives/cli/Cargo.toml b/primitives/cli/Cargo.toml deleted file mode 100644 index 6d9288b86..000000000 --- a/primitives/cli/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -authors.workspace = true -edition.workspace = true -homepage.workspace = true -license-file.workspace = true -name = "cli-primitives" -repository.workspace = true -version = "0.1.0" - -[dependencies] - -[lints] -workspace = true diff --git a/primitives/cli/src/lib.rs b/primitives/cli/src/lib.rs deleted file mode 100644 index 4534a2c5a..000000000 --- a/primitives/cli/src/lib.rs +++ /dev/null @@ -1 +0,0 @@ -#![deny(unused_crate_dependencies)] From a3f2f743ee7bbe75ea0b085f8f138b656868602e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Thu, 18 Jul 2024 12:32:38 +0000 Subject: [PATCH 02/38] feat(polka-storage): extrinsics cli --- .vscode/settings.json | 1 + Cargo.lock | 29 ++- Cargo.toml | 7 +- cli/artifacts/metadata.scale | Bin 0 -> 135134 bytes .../artifacts/metadata.scale | Bin 116799 -> 0 bytes cli/polka-storage-provider/src/substrate.rs | 2 +- cli/polka-storage/storagext/Cargo.toml | 43 ++++ cli/polka-storage/storagext/src/cmd/market.rs | 61 +++++ cli/polka-storage/storagext/src/cmd/mod.rs | 1 + cli/polka-storage/storagext/src/lib.rs | 92 +++++++ cli/polka-storage/storagext/src/main.rs | 126 ++++++++++ cli/polka-storage/storagext/src/market.rs | 225 ++++++++++++++++++ cli/polka-storage/storagext/src/runtime.rs | 6 + node/src/chain_spec.rs | 9 +- pallets/market/.gitkeep | 0 runtime/Cargo.toml | 4 +- 16 files changed, 596 insertions(+), 10 deletions(-) create mode 100644 cli/artifacts/metadata.scale delete mode 100644 cli/polka-storage-provider/artifacts/metadata.scale create mode 100644 cli/polka-storage/storagext/Cargo.toml create mode 100644 cli/polka-storage/storagext/src/cmd/market.rs create mode 100644 cli/polka-storage/storagext/src/cmd/mod.rs create mode 100644 cli/polka-storage/storagext/src/lib.rs create mode 100644 cli/polka-storage/storagext/src/main.rs create mode 100644 cli/polka-storage/storagext/src/market.rs create mode 100644 cli/polka-storage/storagext/src/runtime.rs delete mode 100644 pallets/market/.gitkeep diff --git a/.vscode/settings.json b/.vscode/settings.json index 02b56871b..04a750baf 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "rust-analyzer.rustfmt.extraArgs": ["+nightly"], + "rust-analyzer.checkOnSave": false, "coverage-gutters.coverageBaseDir": "coverage", "coverage-gutters.coverageFileNames": [ "pallet-storage-provider.lcov.info", diff --git a/Cargo.lock b/Cargo.lock index 1b82d16c2..0cdc6bead 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1585,10 +1585,6 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" -[[package]] -name = "cli-primitives" -version = "0.1.0" - [[package]] name = "coarsetime" version = "0.1.34" @@ -14178,6 +14174,31 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "storagext" +version = "0.1.0" +dependencies = [ + "async-trait", + "chrono", + "cid 0.11.1", + "clap", + "frame-support", + "futures", + "hex", + "jsonrpsee", + "primitives-proofs", + "serde", + "serde_json", + "subxt", + "subxt-signer", + "thiserror", + "tokio", + "tracing", + "tracing-subscriber", + "url", + "uuid", +] + [[package]] name = "str0m" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index 1967152d3..7cf848dfb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,10 +8,10 @@ repository = "https://github.com/eigerco/polka-storage" [workspace] members = [ "cli/polka-storage-provider", + "cli/polka-storage/storagext", "node", "pallets/market", "pallets/storage-provider", - "primitives/cli", "primitives/proofs", "runtime", "storage/mater", @@ -92,6 +92,7 @@ tracing = "0.1.40" tracing-subscriber = "0.3.18" url = "2.5.0" uuid = "1.8.0" +hex = "0.4.3" # Local @@ -142,7 +143,9 @@ substrate-prometheus-endpoint = { git = "https://github.com/paritytech/polkadot- # Polkadot pallet-xcm = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.13.0", default-features = false } -polkadot-cli = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.13.0", features = ["rococo-native"] } +polkadot-cli = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.13.0", features = [ + "rococo-native", +] } polkadot-parachain-primitives = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.13.0", default-features = false } polkadot-primitives = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.13.0" } polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.13.0", default-features = false } diff --git a/cli/artifacts/metadata.scale b/cli/artifacts/metadata.scale new file mode 100644 index 0000000000000000000000000000000000000000..f3602b324266362e2b053a833deea7c6ccf172d6 GIT binary patch literal 135134 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 u$Kv$wQFE4= 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 diff --git a/cli/polka-storage-provider/src/substrate.rs b/cli/polka-storage-provider/src/substrate.rs index 97c73fcdc..447a98293 100644 --- a/cli/polka-storage-provider/src/substrate.rs +++ b/cli/polka-storage-provider/src/substrate.rs @@ -2,7 +2,7 @@ use polkadot::runtime_types::{frame_system::AccountInfo, pallet_balances::types: use subxt::{utils::AccountId32, Error, OnlineClient, PolkadotConfig}; use tracing::info; -#[subxt::subxt(runtime_metadata_path = "artifacts/metadata.scale")] +#[subxt::subxt(runtime_metadata_path = "../artifacts/metadata.scale")] pub mod polkadot {} // PolkadotConfig or SubstrateConfig will suffice for this example at the moment, diff --git a/cli/polka-storage/storagext/Cargo.toml b/cli/polka-storage/storagext/Cargo.toml new file mode 100644 index 000000000..66f490a27 --- /dev/null +++ b/cli/polka-storage/storagext/Cargo.toml @@ -0,0 +1,43 @@ +[package] +name = "storagext" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +homepage.workspace = true +license-file.workspace = true +repository.workspace = true + +[lib] +path = "src/lib.rs" + +[features] +default = [] +insecure_url = [] + +[dependencies] +async-trait = { workspace = true } +chrono = { workspace = true, features = ["serde"] } +clap = { workspace = true, features = ["derive"] } +futures = { workspace = true } +jsonrpsee = { workspace = true, features = [ + "http-client", + "server", + "ws-client", +] } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } +subxt = { workspace = true, features = ["jsonrpsee"] } +subxt-signer = { workspace = true, features = ["subxt"] } +thiserror = { workspace = true } +tokio = { workspace = true } +tracing = { workspace = true } +tracing-subscriber = { workspace = true, features = ["env-filter"] } +url = { workspace = true } +uuid = { workspace = true, features = ["v4"] } +primitives-proofs = { workspace = true } +frame-support = { workspace = true, features = ["std"] } +cid = { workspace = true, features = ["serde"] } +hex.workspace = true + +[lints] +workspace = true diff --git a/cli/polka-storage/storagext/src/cmd/market.rs b/cli/polka-storage/storagext/src/cmd/market.rs new file mode 100644 index 000000000..4b219ec98 --- /dev/null +++ b/cli/polka-storage/storagext/src/cmd/market.rs @@ -0,0 +1,61 @@ +use std::{error::Error, str::FromStr}; + +use clap::Subcommand; +use frame_support::sp_runtime::MultiSigner; +use storagext::market::MarketClient; +use subxt::{tx::Signer, utils::AccountId32, OnlineClient, SubstrateConfig}; +use subxt_signer::{ + sr25519::{dev, Keypair}, + SecretUri, +}; +use url::Url; + +#[derive(Debug, Subcommand)] +#[command(name = "market", about = "CLI Client to the Market Pallet", version)] +pub enum MarketCommand { + /// Add balance to an account. + AddBalance { amount: u128 }, + + /// Publish storage deals. + PublishStorageDeals, + + /// Settle deal payments. + SettleDealPayments, + + /// Withdraw balance from an account. + WithdrawBalance { amount: u128 }, +} + +impl MarketCommand { + pub async fn run( + self, + node_rpc: Url, + account_keypair: Keypair, + ) -> Result<(), Box> + where + Keypair: subxt::tx::Signer, + { + let client = MarketClient::::new(node_rpc).await?; + match self { + MarketCommand::AddBalance { amount } => { + let block_hash = client.add_balance(&account_keypair, amount).await?; + tracing::info!( + "[{}] Successfully added {} to Market Balance", + block_hash, + amount + ); + } + MarketCommand::PublishStorageDeals => todo!(), + MarketCommand::SettleDealPayments => todo!(), + MarketCommand::WithdrawBalance { amount } => { + let block_hash = client.withdraw_balance(&account_keypair, amount).await?; + tracing::info!( + "[{}] Successfully withdrew {} from Market Balance", + block_hash, + amount + ); + } + } + Ok(()) + } +} diff --git a/cli/polka-storage/storagext/src/cmd/mod.rs b/cli/polka-storage/storagext/src/cmd/mod.rs new file mode 100644 index 000000000..60e5a3fee --- /dev/null +++ b/cli/polka-storage/storagext/src/cmd/mod.rs @@ -0,0 +1 @@ +pub mod market; diff --git a/cli/polka-storage/storagext/src/lib.rs b/cli/polka-storage/storagext/src/lib.rs new file mode 100644 index 000000000..3d79d8908 --- /dev/null +++ b/cli/polka-storage/storagext/src/lib.rs @@ -0,0 +1,92 @@ +use std::str::FromStr; + +use cid::Cid; +use subxt::utils::{AccountId32, MultiSignature}; + +pub mod market; +pub mod runtime; + +/// Address as specified by the SCALE-encoded runtime. +type Address = AccountId32; + +struct AccountId32Visitor; + +impl<'v> serde::de::Visitor<'v> for AccountId32Visitor { + type Value = AccountId32; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("expected an ss58 string") + } + + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + AccountId32::from_str(v) + .map_err(|err| serde::de::Error::invalid_value(serde::de::Unexpected::Str(v), &self)) + } +} + +// struct MultiSignatureVisitor; + +// impl<'v> serde::de::Visitor<'v> for MultiSignatureVisitor { +// type Value = MultiSignature; + +// fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { +// formatter.write_str("expected a valid hex-formatted key (sr25518, ed25519, ecdsa)") +// } + +// fn visit_str(self, v: &str) -> Result +// where +// E: serde::de::Error, +// { +// let secret_key_bytes = hex::decode(v).map_err(|err| serde::de::Unexpected::Str(v), &self)?; +// let multi_signature = if let Ok(keypair) = sr25519::Keypair::from_secret_key(secret_key_bytes) { +// MultiSignature::Sr25519(keypair.sign(message)) +// } +// else if let Ok(keypair) = ed25519::Keypair::from_secret_key(secret_key_bytes) {} +// else if let Ok(keypair) = ecdsa::Keypair::from_secret_key(secret_key_bytes) {} + +// MultiSignature::from_str(v) +// .map_err(|err| serde::de::Error::invalid_value(serde::de::Unexpected::Str(v), &self)) +// } +// } + +/// Currency as specified by the SCALE-encoded runtime. +type Currency = u128; + +/// BlockNumber as specified by the SCALE-encoded runtime. +type BlockNumber = u32; + +#[derive(Debug, serde::Deserialize)] +struct ActiveDealState { + pub sector_number: u64, + pub sector_start_block: BlockNumber, + pub last_updated_block: Option, + pub slash_block: Option, +} + +#[derive(Debug, serde::Deserialize)] +enum DealState { + Published, + Active(ActiveDealState), +} + +#[derive(Debug, serde::Deserialize)] +struct DealProposal { + pub piece_cid: Cid, + pub piece_size: u64, + pub client: Address, + pub provider: Address, + pub label: String, + pub start_block: BlockNumber, + pub end_block: BlockNumber, + pub storage_price_per_block: Currency, + pub provider_collateral: Currency, + pub state: DealState, +} + +struct ClientDealProposal { + pub proposal: DealProposal, + pub client: MultiSignature, // OffchainSignature +} diff --git a/cli/polka-storage/storagext/src/main.rs b/cli/polka-storage/storagext/src/main.rs new file mode 100644 index 000000000..4cb72e219 --- /dev/null +++ b/cli/polka-storage/storagext/src/main.rs @@ -0,0 +1,126 @@ +#![warn(unused_crate_dependencies)] +#![deny(clippy::unwrap_used)] + +mod cmd; + +use std::error::Error; + +use clap::{ArgGroup, Parser, Subcommand}; +use cmd::market::MarketCommand; +use storagext::runtime::balances::storage::types::account; +use subxt::{OnlineClient, SubstrateConfig}; +use subxt_signer::{ecdsa, sr25519}; +use tracing::level_filters::LevelFilter; +use tracing_subscriber::{ + filter, fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer, +}; +use url::Url; + +pub(crate) const FULL_NODE_DEFAULT_RPC_ADDR: &str = "ws://127.0.0.1:9944"; + +#[tokio::main] +async fn main() -> Result<(), Box> { + // TODO: replace the box/dyn + // Logger initialization. + tracing_subscriber::registry() + .with( + fmt::layer() + .with_filter( + EnvFilter::builder() + .with_default_directive(LevelFilter::INFO.into()) + .from_env()?, + ) + .with_filter(filter::filter_fn(|metadata| { + if let Some(module_path) = metadata.module_path() { + module_path.starts_with("storagext") + } else { + true + } + })), + ) + .init(); + + let cli_arguments = Cli::parse(); + + match (cli_arguments.sr25519_key, cli_arguments.ecdsa_key) { + (Some(account_keypair), _) => { + run_cmd_with_keypair( + cli_arguments.node_rpc, + account_keypair, + cli_arguments.subcommand, + ) + .await? + } + (_, Some(account_keypair)) => { + run_cmd_with_keypair( + cli_arguments.node_rpc, + account_keypair, + cli_arguments.subcommand, + ) + .await? + } + _ => unreachable!("should be handled by clap::ArgGroup"), + } + + Ok(()) +} + +async fn run_cmd_with_keypair( + node_rpc: Url, + account_keypair: Keypair, + cmd: SubCommand, +) -> Result<(), Box> +where + Keypair: subxt::tx::Signer, +{ + match cmd { + SubCommand::Market(cmd) => { + cmd.run(node_rpc, account_keypair).await?; + } + } + + Ok(()) +} + +fn parse_sr25519_keypair(mut src: &str) -> Result { + if src.starts_with("0x") { + src = &src[2..] + } + let mut key_bytes = [0u8; 32]; + hex::decode_to_slice(src, &mut key_bytes).unwrap(); + Ok(sr25519::Keypair::from_secret_key(key_bytes).unwrap()) +} + +fn parse_ecdsa_keypair(mut src: &str) -> Result { + if src.starts_with("0x") { + src = &src[2..] + } + let mut key_bytes = [0u8; 32]; + hex::decode_to_slice(src, &mut key_bytes).unwrap(); + Ok(ecdsa::Keypair::from_secret_key(key_bytes).unwrap()) +} + +#[derive(Debug, Parser)] +#[command(group(ArgGroup::new("key").required(true).args(&["sr25519_key", "ecdsa_key"])))] +struct Cli { + #[command(subcommand)] + pub subcommand: SubCommand, + + /// URL of the providers RPC server. + #[arg(long, default_value = FULL_NODE_DEFAULT_RPC_ADDR)] + pub node_rpc: Url, + + /// An hex encoded Sr25519 key + #[arg(long, value_parser = parse_sr25519_keypair)] + pub sr25519_key: Option, + + #[arg(long, value_parser = parse_ecdsa_keypair)] + pub ecdsa_key: Option, +} + +#[derive(Debug, Subcommand)] +pub enum SubCommand { + // Perform market operations. + #[command(subcommand)] + Market(MarketCommand), +} diff --git a/cli/polka-storage/storagext/src/market.rs b/cli/polka-storage/storagext/src/market.rs new file mode 100644 index 000000000..db98d636c --- /dev/null +++ b/cli/polka-storage/storagext/src/market.rs @@ -0,0 +1,225 @@ +use primitives_proofs::DealId; +use subxt::{config::ExtrinsicParams, Config as SubxtConfig, OnlineClient}; + +use crate::{ + runtime::{self}, + ClientDealProposal, +}; + +/// The maximum number of deal IDs supported. +// NOTE(@jmg-duarte,17/07/2024): ideally, should be read from the primitives or something +const MAX_N_DEALS: usize = 128; + +#[derive(Debug, thiserror::Error)] +pub enum MarketClientError { + #[error(transparent)] + SubxtError(#[from] subxt::Error), +} + +pub struct MarketClient +where + Config: SubxtConfig, +{ + client: OnlineClient, +} + +impl MarketClient +where + Config: SubxtConfig, + >::Params: Default, +{ + /// Create a new [`MarketClient`] from a target `rpc_address`. + pub async fn new(rpc_address: impl AsRef) -> Result { + let client = if cfg!(feature = "insecure_url") { + OnlineClient::::from_insecure_url(rpc_address).await? + } else { + OnlineClient::::from_url(rpc_address).await? + }; + + Ok(Self { client }) + } + + #[tracing::instrument(skip(self, account_keypair))] + pub async fn withdraw_balance( + &self, + account_keypair: &Keypair, + amount: u128, + ) -> Result + where + Keypair: subxt::tx::Signer, + { + Ok(extrinsics::withdraw_balance(&self.client, account_keypair, amount).await?) + } + + #[tracing::instrument(skip(self, account_keypair))] + pub async fn add_balance( + &self, + account_keypair: &Keypair, + amount: u128, + ) -> Result + where + Keypair: subxt::tx::Signer, + { + Ok(extrinsics::add_balance(&self.client, account_keypair, amount).await?) + } + + /// Settle deal payments for the provided [`DealId`]s. + /// + /// If `deal_ids` length is bigger than [`MAX_DEAL_IDS`], it will get truncated. + #[tracing::instrument(skip(self, account_keypair))] + pub async fn settle_deal_payments( + &self, + account_keypair: &Keypair, + mut deal_ids: Vec, // Using the vec so we can print the contents + ) -> Result + where + Keypair: subxt::tx::Signer, + { + if deal_ids.len() > MAX_N_DEALS { + tracing::warn!("more than {} deal ids, truncating", MAX_N_DEALS); + deal_ids.truncate(MAX_N_DEALS); + } + // `deal_ids` has been truncated to fit the proper bound, however, + // the `BoundedVec` defined in the `runtime::runtime_types` is actually just a newtype + // making the `BoundedVec` actually unbounded + let bounded_unbounded_deal_ids = + runtime::runtime_types::bounded_collections::bounded_vec::BoundedVec(deal_ids); + + Ok(extrinsics::settle_deal_payments( + &self.client, + account_keypair, + bounded_unbounded_deal_ids, + ) + .await?) + } + + // TODO remove skip_all + #[tracing::instrument(skip_all)] + pub async fn publish_storage_deals( + &self, + account_keypair: &Keypair, + mut deals: Vec, + ) -> Result + where + Keypair: subxt::tx::Signer, + { + if deals.len() > MAX_N_DEALS { + tracing::warn!("more than {} deals, truncating", MAX_N_DEALS); + deals.truncate(MAX_N_DEALS); + } + // `deals` has been truncated to fit the proper bound, however, + // the `BoundedVec` defined in the `runtime::runtime_types` is actually just a newtype + // making the `BoundedVec` actually unbounded + let bounded_unbounded_deals = + runtime::runtime_types::bounded_collections::bounded_vec::BoundedVec(deals); + + Ok(extrinsics::publish_storage_deals(&self.client, account_keypair, todo!()).await?) + } +} + +/// Module containing thin-wrappers around signing and submitting an extrinsinc. +/// +/// Separated to isolate the conversion from app types to runtime types from these calls. +pub mod extrinsics { + use hex::ToHex; + use subxt::{config::ExtrinsicParams, OnlineClient}; + use tracing::{instrument, trace_span, Instrument}; + + use super::MarketClientError; + use crate::runtime::{ + self, + market::calls::types::{publish_storage_deals::Deals, settle_deal_payments::DealIds}, + }; + + pub async fn withdraw_balance( + client: &OnlineClient, + account_keypair: &Keypair, + amount: u128, + ) -> Result + where + Config: subxt::Config, + Keypair: subxt::tx::Signer, + >::Params: Default, + { + let payload = runtime::tx().market().withdraw_balance(amount); + traced_submission(client, &payload, account_keypair).await + } + + #[instrument(skip_all, account_address = account_keypair.address())] + pub async fn add_balance( + client: &OnlineClient, + account_keypair: &Keypair, + amount: u128, + ) -> Result + where + Config: subxt::Config, + Keypair: subxt::tx::Signer, + >::Params: Default, + { + let payload = runtime::tx().market().add_balance(amount); + traced_submission(client, &payload, account_keypair).await + } + + pub async fn settle_deal_payments( + client: &OnlineClient, + account_keypair: &Keypair, + mut deal_ids: DealIds, + ) -> Result + where + Config: subxt::Config, + Keypair: subxt::tx::Signer, + >::Params: Default, + { + let payload = runtime::tx().market().settle_deal_payments(deal_ids); + traced_submission(client, &payload, account_keypair).await + } + + pub async fn publish_storage_deals( + client: &OnlineClient, + account_keypair: &Keypair, + deals: Deals, + ) -> Result + where + Config: subxt::Config, + Keypair: subxt::tx::Signer, + >::Params: Default, + { + let payload = runtime::tx().market().publish_storage_deals(deals); + traced_submission(client, &payload, account_keypair).await + } + + /// Submit an extrinsic and wait for finalization, returning the block hash it was included in. + /// + /// Equivalent to performing [`OnlineClient::sign_and_submit_then_watch_default`], + /// followed by [`TxInBlock::wait_for_finalized`]. + async fn traced_submission( + client: &OnlineClient, + call: &Call, + account_keypair: &Keypair, + ) -> Result + where + Call: subxt::tx::Payload, + Config: subxt::Config, + Keypair: subxt::tx::Signer, + >::Params: Default, + { + tracing::info!("submitting extrinsic"); + let submission_progress = client + .tx() + .sign_and_submit_then_watch_default(call, account_keypair) + .await?; + + tracing::trace!( + extrinsic_hash = submission_progress.extrinsic_hash().encode_hex::(), + "waiting for finalization" + ); + let finalized_xt = submission_progress.wait_for_finalized().await?; + + let block_hash = finalized_xt.block_hash(); + tracing::info!( + block_hash = block_hash.encode_hex::(), + "successfully submitted extrinsic" + ); + Ok(block_hash) + } +} diff --git a/cli/polka-storage/storagext/src/runtime.rs b/cli/polka-storage/storagext/src/runtime.rs new file mode 100644 index 000000000..5741e725c --- /dev/null +++ b/cli/polka-storage/storagext/src/runtime.rs @@ -0,0 +1,6 @@ +///! Runtime API extracted from SCALE-encoded runtime. + +#[subxt::subxt(runtime_metadata_path = "../../artifacts/metadata.scale")] +mod polka_storage_runtime {} + +pub use polka_storage_runtime::*; diff --git a/node/src/chain_spec.rs b/node/src/chain_spec.rs index 73f23feea..2cb7d328a 100644 --- a/node/src/chain_spec.rs +++ b/node/src/chain_spec.rs @@ -4,8 +4,11 @@ use runtime::{AccountId, AuraId, Signature, EXISTENTIAL_DEPOSIT}; use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup}; use sc_service::ChainType; use serde::{Deserialize, Serialize}; -use sp_core::{sr25519, Pair, Public}; -use sp_runtime::traits::{IdentifyAccount, Verify}; +use sp_core::{crypto::Ss58Codec, sr25519, Pair, Public}; +use sp_runtime::{ + traits::{IdentifyAccount, Verify}, + AccountId32, +}; /// Specialized `ChainSpec` for the normal parachain runtime. pub type ChainSpec = sc_service::GenericChainSpec; @@ -155,6 +158,8 @@ pub fn local_testnet_config() -> ChainSpec { get_account_id_from_seed::("Dave//stash"), get_account_id_from_seed::("Eve//stash"), get_account_id_from_seed::("Ferdie//stash"), + AccountId32::from_ss58check("5GvHnpY1433RytXW66r77iL4CyewAAErDU6fAouoaPKvcvLU") + .unwrap(), ], get_account_id_from_seed::("Alice"), 1000.into(), diff --git a/pallets/market/.gitkeep b/pallets/market/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 12ded1cf1..3b21e46eb 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -25,7 +25,9 @@ pallet-storage-provider = { workspace = true, default-features = false } codec = { workspace = true, default-features = false, features = ["derive"] } hex-literal = { workspace = true, optional = true } log = { workspace = true } -scale-info = { workspace = true, default-features = false, features = ["derive"] } +scale-info = { workspace = true, default-features = false, features = [ + "derive", +] } smallvec = { workspace = true } # Substrate / FRAME From 0235dcf340310b6b1a21aacfd4dae62fb6c2e918 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Thu, 18 Jul 2024 17:39:10 +0000 Subject: [PATCH 03/38] feat(polka-storage): more methods for the extrinsics cli `add_balance` and `withdraw_balance` are working --- Cargo.lock | 2 + Cargo.toml | 1 + cli/polka-storage/storagext/Cargo.toml | 4 +- cli/polka-storage/storagext/deals.json | 26 +++++ cli/polka-storage/storagext/src/cmd/market.rs | 47 ++++++-- cli/polka-storage/storagext/src/lib.rs | 92 ++++++++------- cli/polka-storage/storagext/src/main.rs | 109 +++++++++--------- cli/polka-storage/storagext/src/market.rs | 47 ++++++-- cli/polka-storage/storagext/src/runtime.rs | 61 ++++++++++ 9 files changed, 268 insertions(+), 121 deletions(-) create mode 100644 cli/polka-storage/storagext/deals.json diff --git a/Cargo.lock b/Cargo.lock index 0cdc6bead..902e51836 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14178,6 +14178,7 @@ dependencies = [ name = "storagext" version = "0.1.0" dependencies = [ + "anyhow", "async-trait", "chrono", "cid 0.11.1", @@ -14186,6 +14187,7 @@ dependencies = [ "futures", "hex", "jsonrpsee", + "parity-scale-codec", "primitives-proofs", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index 7cf848dfb..5d9c582f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -93,6 +93,7 @@ tracing-subscriber = "0.3.18" url = "2.5.0" uuid = "1.8.0" hex = "0.4.3" +anyhow = "1.0.86" # Local diff --git a/cli/polka-storage/storagext/Cargo.toml b/cli/polka-storage/storagext/Cargo.toml index 66f490a27..94df3f88b 100644 --- a/cli/polka-storage/storagext/Cargo.toml +++ b/cli/polka-storage/storagext/Cargo.toml @@ -36,8 +36,10 @@ url = { workspace = true } uuid = { workspace = true, features = ["v4"] } primitives-proofs = { workspace = true } frame-support = { workspace = true, features = ["std"] } -cid = { workspace = true, features = ["serde"] } +cid = { workspace = true, features = ["scale-codec"] } hex.workspace = true +codec.workspace = true +anyhow.workspace = true [lints] workspace = true diff --git a/cli/polka-storage/storagext/deals.json b/cli/polka-storage/storagext/deals.json new file mode 100644 index 000000000..068b0bcc9 --- /dev/null +++ b/cli/polka-storage/storagext/deals.json @@ -0,0 +1,26 @@ +[ + { + "piece_cid": "bafkreibme22gw2h7y2h7tg2fhqotaqjucnbc24deqo72b6mkl2egezxhvy", + "piece_size": 1, + "client": "5GvHnpY1433RytXW66r77iL4CyewAAErDU6fAouoaPKvcvLU", + "provider": "5GvHnpY1433RytXW66r77iL4CyewAAErDU6fAouoaPKvcvLU", + "label": "heyyy", + "start_block": 30, + "end_block": 55, + "storage_price_per_block": 1, + "provider_collateral": 1, + "state": "Published" + }, + { + "piece_cid": "bafkreibme22gw2h7y2h7tg2fhqotaqjucnbc24deqo72b6mkl2egezxhvy", + "piece_size": 4, + "client": "5GvHnpY1433RytXW66r77iL4CyewAAErDU6fAouoaPKvcvLU", + "provider": "5GvHnpY1433RytXW66r77iL4CyewAAErDU6fAouoaPKvcvLU", + "label": "heyyy", + "start_block": 10, + "end_block": 55, + "storage_price_per_block": 1, + "provider_collateral": 1, + "state": "Published" + } +] diff --git a/cli/polka-storage/storagext/src/cmd/market.rs b/cli/polka-storage/storagext/src/cmd/market.rs index 4b219ec98..166aee890 100644 --- a/cli/polka-storage/storagext/src/cmd/market.rs +++ b/cli/polka-storage/storagext/src/cmd/market.rs @@ -1,15 +1,31 @@ -use std::{error::Error, str::FromStr}; +use std::{error::Error, path::PathBuf, str::FromStr}; use clap::Subcommand; -use frame_support::sp_runtime::MultiSigner; -use storagext::market::MarketClient; -use subxt::{tx::Signer, utils::AccountId32, OnlineClient, SubstrateConfig}; +use frame_support::sp_runtime::{MultiSigner, AccountId32}; +use primitives_proofs::DealId; +use storagext::{market::MarketClient, DealProposal}; +use subxt::{tx::Signer, , OnlineClient, SubstrateConfig}; use subxt_signer::{ sr25519::{dev, Keypair}, SecretUri, }; use url::Url; +#[derive(Debug, Clone, serde::Deserialize)] +struct DealProposals(Vec); + +impl DealProposals { + fn parse(src: &str) -> Result { + Ok(if src.starts_with('@') { + let path = PathBuf::from_str(&src[1..])?; + let mut file = std::fs::File::open(path)?; + serde_json::from_reader(&mut file) + } else { + serde_json::from_str(src) + }?) + } +} + #[derive(Debug, Subcommand)] #[command(name = "market", about = "CLI Client to the Market Pallet", version)] pub enum MarketCommand { @@ -17,10 +33,13 @@ pub enum MarketCommand { AddBalance { amount: u128 }, /// Publish storage deals. - PublishStorageDeals, + PublishStorageDeals { + #[arg(value_parser = DealProposals::parse)] + deals: DealProposals, + }, /// Settle deal payments. - SettleDealPayments, + SettleDealPayments { deal_ids: Vec }, /// Withdraw balance from an account. WithdrawBalance { amount: u128 }, @@ -31,7 +50,7 @@ impl MarketCommand { self, node_rpc: Url, account_keypair: Keypair, - ) -> Result<(), Box> + ) -> Result<(), anyhow::Error> where Keypair: subxt::tx::Signer, { @@ -45,8 +64,18 @@ impl MarketCommand { amount ); } - MarketCommand::PublishStorageDeals => todo!(), - MarketCommand::SettleDealPayments => todo!(), + MarketCommand::PublishStorageDeals { deals } => { + let block_hash = client + .publish_storage_deals(&account_keypair, deals.0) + .await?; + tracing::info!("[{}] Successfully published storage deals", block_hash); + } + MarketCommand::SettleDealPayments { deal_ids } => { + let block_hash = client + .settle_deal_payments(&account_keypair, deal_ids) + .await?; + tracing::info!("[{}] Successfully settled deal payments", block_hash); + } MarketCommand::WithdrawBalance { amount } => { let block_hash = client.withdraw_balance(&account_keypair, amount).await?; tracing::info!( diff --git a/cli/polka-storage/storagext/src/lib.rs b/cli/polka-storage/storagext/src/lib.rs index 3d79d8908..616494475 100644 --- a/cli/polka-storage/storagext/src/lib.rs +++ b/cli/polka-storage/storagext/src/lib.rs @@ -1,7 +1,7 @@ -use std::str::FromStr; - use cid::Cid; -use subxt::utils::{AccountId32, MultiSignature}; +use codec::Encode; +use frame_support::sp_runtime::{AccountId32, MultiSignature}; +use subxt::tx::Signer; pub mod market; pub mod runtime; @@ -9,48 +9,28 @@ pub mod runtime; /// Address as specified by the SCALE-encoded runtime. type Address = AccountId32; -struct AccountId32Visitor; - -impl<'v> serde::de::Visitor<'v> for AccountId32Visitor { - type Value = AccountId32; +#[derive(Debug, Clone, codec::Encode)] +struct CidWrapper(Cid); - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("expected an ss58 string") - } - - fn visit_str(self, v: &str) -> Result +// The CID has some issues that require a workaround for strings. +// For more details, see: +impl<'de> serde::de::Deserialize<'de> for CidWrapper { + fn deserialize(deserializer: D) -> Result where - E: serde::de::Error, + D: serde::Deserializer<'de>, { - AccountId32::from_str(v) - .map_err(|err| serde::de::Error::invalid_value(serde::de::Unexpected::Str(v), &self)) + let s = String::deserialize(deserializer)?; + Ok(Self( + Cid::try_from(s.as_str()).map_err(|e| serde::de::Error::custom(format!("{e:?}")))?, + )) } } -// struct MultiSignatureVisitor; - -// impl<'v> serde::de::Visitor<'v> for MultiSignatureVisitor { -// type Value = MultiSignature; - -// fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { -// formatter.write_str("expected a valid hex-formatted key (sr25518, ed25519, ecdsa)") -// } - -// fn visit_str(self, v: &str) -> Result -// where -// E: serde::de::Error, -// { -// let secret_key_bytes = hex::decode(v).map_err(|err| serde::de::Unexpected::Str(v), &self)?; -// let multi_signature = if let Ok(keypair) = sr25519::Keypair::from_secret_key(secret_key_bytes) { -// MultiSignature::Sr25519(keypair.sign(message)) -// } -// else if let Ok(keypair) = ed25519::Keypair::from_secret_key(secret_key_bytes) {} -// else if let Ok(keypair) = ecdsa::Keypair::from_secret_key(secret_key_bytes) {} - -// MultiSignature::from_str(v) -// .map_err(|err| serde::de::Error::invalid_value(serde::de::Unexpected::Str(v), &self)) -// } -// } +impl Into for CidWrapper { + fn into(self) -> Cid { + self.0 + } +} /// Currency as specified by the SCALE-encoded runtime. type Currency = u128; @@ -58,23 +38,23 @@ type Currency = u128; /// BlockNumber as specified by the SCALE-encoded runtime. type BlockNumber = u32; -#[derive(Debug, serde::Deserialize)] -struct ActiveDealState { +#[derive(Debug, Clone, serde::Deserialize, codec::Encode)] +pub struct ActiveDealState { pub sector_number: u64, pub sector_start_block: BlockNumber, pub last_updated_block: Option, pub slash_block: Option, } -#[derive(Debug, serde::Deserialize)] -enum DealState { +#[derive(Debug, Clone, serde::Deserialize, codec::Encode)] +pub enum DealState { Published, Active(ActiveDealState), } -#[derive(Debug, serde::Deserialize)] -struct DealProposal { - pub piece_cid: Cid, +#[derive(Debug, Clone, serde::Deserialize, codec::Encode)] +pub struct DealProposal { + pub piece_cid: CidWrapper, pub piece_size: u64, pub client: Address, pub provider: Address, @@ -86,7 +66,25 @@ struct DealProposal { pub state: DealState, } -struct ClientDealProposal { +impl DealProposal { + fn sign(self, keypair: &Keypair) -> ClientDealProposal + where + Keypair: Signer, + Config: subxt::Config, + { + let encoded_deal_proposal = self.encode(); + + let signature = keypair.sign(&encoded_deal_proposal); + let client = MultiSignature::from(signature); + + ClientDealProposal { + proposal: self, + client, + } + } +} + +pub struct ClientDealProposal { pub proposal: DealProposal, pub client: MultiSignature, // OffchainSignature } diff --git a/cli/polka-storage/storagext/src/main.rs b/cli/polka-storage/storagext/src/main.rs index 4cb72e219..c8d1420cb 100644 --- a/cli/polka-storage/storagext/src/main.rs +++ b/cli/polka-storage/storagext/src/main.rs @@ -5,6 +5,7 @@ mod cmd; use std::error::Error; +use cid::{Cid, CidGeneric}; use clap::{ArgGroup, Parser, Subcommand}; use cmd::market::MarketCommand; use storagext::runtime::balances::storage::types::account; @@ -18,8 +19,52 @@ use url::Url; pub(crate) const FULL_NODE_DEFAULT_RPC_ADDR: &str = "ws://127.0.0.1:9944"; +#[derive(Debug, Parser)] +#[command(group(ArgGroup::new("key").required(true).args(&["sr25519_key", "ecdsa_key"])))] +struct Cli { + #[command(subcommand)] + pub subcommand: SubCommand, + + /// URL of the providers RPC server. + #[arg(long, default_value = FULL_NODE_DEFAULT_RPC_ADDR)] + pub node_rpc: Url, + + /// An hex encoded Sr25519 key + #[arg(long, value_parser = parse_sr25519_keypair)] + pub sr25519_key: Option, + + #[arg(long, value_parser = parse_ecdsa_keypair)] + pub ecdsa_key: Option, +} + +#[derive(Debug, Subcommand)] +pub enum SubCommand { + // Perform market operations. + #[command(subcommand)] + Market(MarketCommand), +} + +impl SubCommand { + async fn run_with_keypair( + self, + node_rpc: Url, + account_keypair: Keypair, + ) -> Result<(), anyhow::Error> + where + Keypair: subxt::tx::Signer, + { + match self { + SubCommand::Market(cmd) => { + cmd.run(node_rpc, account_keypair).await?; + } + } + + Ok(()) + } +} + #[tokio::main] -async fn main() -> Result<(), Box> { +async fn main() -> Result<(), anyhow::Error> { // TODO: replace the box/dyn // Logger initialization. tracing_subscriber::registry() @@ -44,20 +89,16 @@ async fn main() -> Result<(), Box> { match (cli_arguments.sr25519_key, cli_arguments.ecdsa_key) { (Some(account_keypair), _) => { - run_cmd_with_keypair( - cli_arguments.node_rpc, - account_keypair, - cli_arguments.subcommand, - ) - .await? + cli_arguments + .subcommand + .run_with_keypair(cli_arguments.node_rpc, account_keypair) + .await? } (_, Some(account_keypair)) => { - run_cmd_with_keypair( - cli_arguments.node_rpc, - account_keypair, - cli_arguments.subcommand, - ) - .await? + cli_arguments + .subcommand + .run_with_keypair(cli_arguments.node_rpc, account_keypair) + .await? } _ => unreachable!("should be handled by clap::ArgGroup"), } @@ -65,23 +106,6 @@ async fn main() -> Result<(), Box> { Ok(()) } -async fn run_cmd_with_keypair( - node_rpc: Url, - account_keypair: Keypair, - cmd: SubCommand, -) -> Result<(), Box> -where - Keypair: subxt::tx::Signer, -{ - match cmd { - SubCommand::Market(cmd) => { - cmd.run(node_rpc, account_keypair).await?; - } - } - - Ok(()) -} - fn parse_sr25519_keypair(mut src: &str) -> Result { if src.starts_with("0x") { src = &src[2..] @@ -99,28 +123,3 @@ fn parse_ecdsa_keypair(mut src: &str) -> Result { hex::decode_to_slice(src, &mut key_bytes).unwrap(); Ok(ecdsa::Keypair::from_secret_key(key_bytes).unwrap()) } - -#[derive(Debug, Parser)] -#[command(group(ArgGroup::new("key").required(true).args(&["sr25519_key", "ecdsa_key"])))] -struct Cli { - #[command(subcommand)] - pub subcommand: SubCommand, - - /// URL of the providers RPC server. - #[arg(long, default_value = FULL_NODE_DEFAULT_RPC_ADDR)] - pub node_rpc: Url, - - /// An hex encoded Sr25519 key - #[arg(long, value_parser = parse_sr25519_keypair)] - pub sr25519_key: Option, - - #[arg(long, value_parser = parse_ecdsa_keypair)] - pub ecdsa_key: Option, -} - -#[derive(Debug, Subcommand)] -pub enum SubCommand { - // Perform market operations. - #[command(subcommand)] - Market(MarketCommand), -} diff --git a/cli/polka-storage/storagext/src/market.rs b/cli/polka-storage/storagext/src/market.rs index db98d636c..de6b1a3e9 100644 --- a/cli/polka-storage/storagext/src/market.rs +++ b/cli/polka-storage/storagext/src/market.rs @@ -1,9 +1,10 @@ +use frame_support::sp_runtime::AccountId32; use primitives_proofs::DealId; use subxt::{config::ExtrinsicParams, Config as SubxtConfig, OnlineClient}; use crate::{ runtime::{self}, - ClientDealProposal, + DealProposal, }; /// The maximum number of deal IDs supported. @@ -39,6 +40,7 @@ where Ok(Self { client }) } + /// Withdraw the given `amount` of balance. #[tracing::instrument(skip(self, account_keypair))] pub async fn withdraw_balance( &self, @@ -51,6 +53,7 @@ where Ok(extrinsics::withdraw_balance(&self.client, account_keypair, amount).await?) } + /// Add the given `amount` of balance. #[tracing::instrument(skip(self, account_keypair))] pub async fn add_balance( &self, @@ -70,7 +73,7 @@ where pub async fn settle_deal_payments( &self, account_keypair: &Keypair, - mut deal_ids: Vec, // Using the vec so we can print the contents + mut deal_ids: Vec, ) -> Result where Keypair: subxt::tx::Signer, @@ -98,34 +101,56 @@ where pub async fn publish_storage_deals( &self, account_keypair: &Keypair, - mut deals: Vec, + mut deals: Vec, ) -> Result where Keypair: subxt::tx::Signer, + Config: subxt::Config, { if deals.len() > MAX_N_DEALS { tracing::warn!("more than {} deals, truncating", MAX_N_DEALS); deals.truncate(MAX_N_DEALS); } + + let signed_deal_proposals = deals + .into_iter() + .map(|deal| { + let client_deal_proposal = deal.sign(account_keypair); + runtime::runtime_types::pallet_market::pallet::ClientDealProposal::< + AccountId32, + u128, + u32, + runtime::runtime_types::sp_runtime::MultiSignature, + >::from(client_deal_proposal) + }) + .collect(); + // `deals` has been truncated to fit the proper bound, however, // the `BoundedVec` defined in the `runtime::runtime_types` is actually just a newtype // making the `BoundedVec` actually unbounded let bounded_unbounded_deals = - runtime::runtime_types::bounded_collections::bounded_vec::BoundedVec(deals); + runtime::runtime_types::bounded_collections::bounded_vec::BoundedVec( + signed_deal_proposals, + ); - Ok(extrinsics::publish_storage_deals(&self.client, account_keypair, todo!()).await?) + Ok(extrinsics::publish_storage_deals( + &self.client, + account_keypair, + bounded_unbounded_deals, + ) + .await?) } } /// Module containing thin-wrappers around signing and submitting an extrinsinc. /// /// Separated to isolate the conversion from app types to runtime types from these calls. +/// In other words, [`crate::runtime`] types should not be used outside of this module. pub mod extrinsics { use hex::ToHex; use subxt::{config::ExtrinsicParams, OnlineClient}; - use tracing::{instrument, trace_span, Instrument}; + use tracing::instrument; - use super::MarketClientError; use crate::runtime::{ self, market::calls::types::{publish_storage_deals::Deals, settle_deal_payments::DealIds}, @@ -145,7 +170,11 @@ pub mod extrinsics { traced_submission(client, &payload, account_keypair).await } - #[instrument(skip_all, account_address = account_keypair.address())] + #[instrument( + skip_all, fields( + account_address = ?account_keypair.address() + ) + )] pub async fn add_balance( client: &OnlineClient, account_keypair: &Keypair, @@ -163,7 +192,7 @@ pub mod extrinsics { pub async fn settle_deal_payments( client: &OnlineClient, account_keypair: &Keypair, - mut deal_ids: DealIds, + deal_ids: DealIds, ) -> Result where Config: subxt::Config, diff --git a/cli/polka-storage/storagext/src/runtime.rs b/cli/polka-storage/storagext/src/runtime.rs index 5741e725c..cdfe4c99d 100644 --- a/cli/polka-storage/storagext/src/runtime.rs +++ b/cli/polka-storage/storagext/src/runtime.rs @@ -3,4 +3,65 @@ #[subxt::subxt(runtime_metadata_path = "../../artifacts/metadata.scale")] mod polka_storage_runtime {} +use cid::Cid; +use frame_support::sp_runtime::AccountId32; pub use polka_storage_runtime::*; +use runtime_types::pallet_market::pallet::ClientDealProposal; +use subxt::utils::MultiSignature; + +impl From + for runtime_types::pallet_market::pallet::DealProposal +{ + fn from(value: crate::DealProposal) -> Self { + Self { + piece_cid: value.piece_cid.0.into_bounded_byte_vec(), + piece_size: value.piece_size, + client: value.client, + provider: value.provider, + label: value.label.into_bounded_byte_vec(), + start_block: value.start_block, + end_block: value.end_block, + storage_price_per_block: value.storage_price_per_block, + provider_collateral: value.provider_collateral, + state: value.state, + } + } +} + +impl From + for ClientDealProposal< + AccountId32, + u128, + u32, + MultiSignature, // hmmmm + > +{ + fn from(value: crate::ClientDealProposal) -> Self { + Self { + proposal: value.proposal, + client_signature: value.client.into(), + } + } +} + +trait IntoBoundedByteVec { + fn into_bounded_byte_vec( + self, + ) -> runtime_types::bounded_collections::bounded_vec::BoundedVec; +} + +impl IntoBoundedByteVec for Cid { + fn into_bounded_byte_vec( + self, + ) -> runtime_types::bounded_collections::bounded_vec::BoundedVec { + runtime_types::bounded_collections::bounded_vec::BoundedVec(self.to_bytes()) + } +} + +impl IntoBoundedByteVec for String { + fn into_bounded_byte_vec( + self, + ) -> runtime_types::bounded_collections::bounded_vec::BoundedVec { + runtime_types::bounded_collections::bounded_vec::BoundedVec(self.into_bytes()) + } +} From 4f0f2a6d5c6be730ff81e9b11ebd2ccf713248c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Fri, 19 Jul 2024 13:13:04 +0000 Subject: [PATCH 04/38] feat(polka-storage): subxt magic currently doesn't build, trying to figure out how to best handle some things --- Cargo.lock | 5 - cli/polka-storage/storagext/Cargo.toml | 30 ++--- .../storagext/src/{ => bin/cli}/cmd/market.rs | 14 +-- .../storagext/src/bin/cli/cmd/mod.rs | 3 + .../storagext/src/bin/cli/mod.rs | 103 ++++++++++++++++++ .../src/{main.rs => bin/storagext_cli.rs} | 13 +-- cli/polka-storage/storagext/src/cmd/mod.rs | 1 - cli/polka-storage/storagext/src/lib.rs | 82 +++++++------- cli/polka-storage/storagext/src/market.rs | 30 +++-- cli/polka-storage/storagext/src/runtime.rs | 67 ------------ .../storagext/src/runtime/bounded_vec.rs | 28 +++++ .../storagext/src/runtime/mod.rs | 83 ++++++++++++++ 12 files changed, 296 insertions(+), 163 deletions(-) rename cli/polka-storage/storagext/src/{ => bin/cli}/cmd/market.rs (85%) create mode 100644 cli/polka-storage/storagext/src/bin/cli/cmd/mod.rs create mode 100644 cli/polka-storage/storagext/src/bin/cli/mod.rs rename cli/polka-storage/storagext/src/{main.rs => bin/storagext_cli.rs} (92%) delete mode 100644 cli/polka-storage/storagext/src/cmd/mod.rs delete mode 100644 cli/polka-storage/storagext/src/runtime.rs create mode 100644 cli/polka-storage/storagext/src/runtime/bounded_vec.rs create mode 100644 cli/polka-storage/storagext/src/runtime/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 902e51836..a058de906 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14179,14 +14179,10 @@ name = "storagext" version = "0.1.0" dependencies = [ "anyhow", - "async-trait", - "chrono", "cid 0.11.1", "clap", "frame-support", - "futures", "hex", - "jsonrpsee", "parity-scale-codec", "primitives-proofs", "serde", @@ -14198,7 +14194,6 @@ dependencies = [ "tracing", "tracing-subscriber", "url", - "uuid", ] [[package]] diff --git a/cli/polka-storage/storagext/Cargo.toml b/cli/polka-storage/storagext/Cargo.toml index 94df3f88b..602aba6db 100644 --- a/cli/polka-storage/storagext/Cargo.toml +++ b/cli/polka-storage/storagext/Cargo.toml @@ -1,45 +1,33 @@ [package] -name = "storagext" -version = "0.1.0" authors.workspace = true edition.workspace = true homepage.workspace = true license-file.workspace = true +name = "storagext" repository.workspace = true - -[lib] -path = "src/lib.rs" +version = "0.1.0" [features] default = [] insecure_url = [] [dependencies] -async-trait = { workspace = true } -chrono = { workspace = true, features = ["serde"] } +anyhow.workspace = true +cid = { workspace = true, features = ["scale-codec"] } clap = { workspace = true, features = ["derive"] } -futures = { workspace = true } -jsonrpsee = { workspace = true, features = [ - "http-client", - "server", - "ws-client", -] } +codec.workspace = true +frame-support = { workspace = true, features = ["std"] } +hex.workspace = true +primitives-proofs = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } subxt = { workspace = true, features = ["jsonrpsee"] } subxt-signer = { workspace = true, features = ["subxt"] } thiserror = { workspace = true } -tokio = { workspace = true } +tokio = { workspace = true, features = ["rt-multi-thread"] } tracing = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter"] } url = { workspace = true } -uuid = { workspace = true, features = ["v4"] } -primitives-proofs = { workspace = true } -frame-support = { workspace = true, features = ["std"] } -cid = { workspace = true, features = ["scale-codec"] } -hex.workspace = true -codec.workspace = true -anyhow.workspace = true [lints] workspace = true diff --git a/cli/polka-storage/storagext/src/cmd/market.rs b/cli/polka-storage/storagext/src/bin/cli/cmd/market.rs similarity index 85% rename from cli/polka-storage/storagext/src/cmd/market.rs rename to cli/polka-storage/storagext/src/bin/cli/cmd/market.rs index 166aee890..2dc304caf 100644 --- a/cli/polka-storage/storagext/src/cmd/market.rs +++ b/cli/polka-storage/storagext/src/bin/cli/cmd/market.rs @@ -1,14 +1,8 @@ -use std::{error::Error, path::PathBuf, str::FromStr}; +use std::{path::PathBuf, str::FromStr}; use clap::Subcommand; -use frame_support::sp_runtime::{MultiSigner, AccountId32}; use primitives_proofs::DealId; -use storagext::{market::MarketClient, DealProposal}; -use subxt::{tx::Signer, , OnlineClient, SubstrateConfig}; -use subxt_signer::{ - sr25519::{dev, Keypair}, - SecretUri, -}; +use storagext::{market::MarketClient, DealProposal, PolkaStorageConfig}; use url::Url; #[derive(Debug, Clone, serde::Deserialize)] @@ -52,9 +46,9 @@ impl MarketCommand { account_keypair: Keypair, ) -> Result<(), anyhow::Error> where - Keypair: subxt::tx::Signer, + Keypair: subxt::tx::Signer, { - let client = MarketClient::::new(node_rpc).await?; + let client = MarketClient::::new(node_rpc).await?; match self { MarketCommand::AddBalance { amount } => { let block_hash = client.add_balance(&account_keypair, amount).await?; diff --git a/cli/polka-storage/storagext/src/bin/cli/cmd/mod.rs b/cli/polka-storage/storagext/src/bin/cli/cmd/mod.rs new file mode 100644 index 000000000..960a174cc --- /dev/null +++ b/cli/polka-storage/storagext/src/bin/cli/cmd/mod.rs @@ -0,0 +1,3 @@ +use frame_support::sp_runtime::AccountId32; + +pub mod market; diff --git a/cli/polka-storage/storagext/src/bin/cli/mod.rs b/cli/polka-storage/storagext/src/bin/cli/mod.rs new file mode 100644 index 000000000..bc9541bd6 --- /dev/null +++ b/cli/polka-storage/storagext/src/bin/cli/mod.rs @@ -0,0 +1,103 @@ +//! Contains the types required to parse the CLI arguments. +//! +//! Separated from the library ones as these ones are specific while the library ones are generic +//! and ensuring the generic ones are parseable is problematic (to say the least). + +use std::sync::Arc; + +mod cmd; + +/// Currency as specified by the SCALE-encoded runtime. +type Currency = u128; + +/// BlockNumber as specified by the SCALE-encoded runtime. +type BlockNumber = u32; + +/// CID wrapper to get deserialization. +#[derive(Debug, Clone)] +pub struct CidWrapper(Cid); + +impl Deref for CidWrapper { + type Target = Cid; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl Into for CidWrapper { + fn into(self) -> Cid { + self.0 + } +} + +// The CID has some issues that require a workaround for strings. +// For more details, see: +impl<'de> serde::de::Deserialize<'de> for CidWrapper { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + Ok(Self( + Cid::try_from(s.as_str()).map_err(|e| serde::de::Error::custom(format!("{e:?}")))?, + )) + } +} + +#[derive(Debug, Clone, serde::Deserialize)] +pub struct ActiveDealState { + pub sector_number: u64, + pub sector_start_block: BlockNumber, + pub last_updated_block: Option, + pub slash_block: Option, +} + +impl Into> for ActiveDealState { + fn into(self) -> storagext::ActiveDealState { + storagext::ActiveDealState { + sector_number: self.sector_number, + sector_start_block: self.sector_start_block, + last_updated_block: self.last_updated_block, + slash_block: self.slash_block, + } + } +} + +#[derive(Debug, Clone, serde::Deserialize)] +pub enum DealState { + Published, + Active(ActiveDealState), +} + +#[derive(Debug, Clone, serde::Deserialize)] +pub struct DealProposal { + pub piece_cid: CidWrapper, + pub piece_size: u64, + pub client: AccountId32, + pub provider: AccountId32, + pub label: String, + pub start_block: BlockNumber, + pub end_block: BlockNumber, + pub storage_price_per_block: Currency, + pub provider_collateral: Currency, + pub state: DealState, +} + +// impl DealProposal { +// fn sign(self, keypair: &Keypair) -> ClientDealProposal +// where +// Keypair: Signer, +// Config: subxt::Config, +// { +// let encoded_deal_proposal = self.encode(); + +// let signature = keypair.sign(&encoded_deal_proposal); +// let client = MultiSignature::from(signature); + +// ClientDealProposal { +// proposal: self, +// client, +// } +// } +// } diff --git a/cli/polka-storage/storagext/src/main.rs b/cli/polka-storage/storagext/src/bin/storagext_cli.rs similarity index 92% rename from cli/polka-storage/storagext/src/main.rs rename to cli/polka-storage/storagext/src/bin/storagext_cli.rs index c8d1420cb..b125d2f0c 100644 --- a/cli/polka-storage/storagext/src/main.rs +++ b/cli/polka-storage/storagext/src/bin/storagext_cli.rs @@ -1,15 +1,10 @@ -#![warn(unused_crate_dependencies)] #![deny(clippy::unwrap_used)] -mod cmd; +mod cli; -use std::error::Error; - -use cid::{Cid, CidGeneric}; use clap::{ArgGroup, Parser, Subcommand}; -use cmd::market::MarketCommand; -use storagext::runtime::balances::storage::types::account; -use subxt::{OnlineClient, SubstrateConfig}; +use cli::cmd::market::MarketCommand; +use storagext::PolkaStorageConfig; use subxt_signer::{ecdsa, sr25519}; use tracing::level_filters::LevelFilter; use tracing_subscriber::{ @@ -51,7 +46,7 @@ impl SubCommand { account_keypair: Keypair, ) -> Result<(), anyhow::Error> where - Keypair: subxt::tx::Signer, + Keypair: subxt::tx::Signer, { match self { SubCommand::Market(cmd) => { diff --git a/cli/polka-storage/storagext/src/cmd/mod.rs b/cli/polka-storage/storagext/src/cmd/mod.rs deleted file mode 100644 index 60e5a3fee..000000000 --- a/cli/polka-storage/storagext/src/cmd/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod market; diff --git a/cli/polka-storage/storagext/src/lib.rs b/cli/polka-storage/storagext/src/lib.rs index 616494475..c6d098cdf 100644 --- a/cli/polka-storage/storagext/src/lib.rs +++ b/cli/polka-storage/storagext/src/lib.rs @@ -1,35 +1,33 @@ use cid::Cid; use codec::Encode; -use frame_support::sp_runtime::{AccountId32, MultiSignature}; -use subxt::tx::Signer; +use frame_support::sp_runtime::{traits::BlakeTwo256, MultiAddress, MultiSignature}; +use subxt::{ + config::{polkadot::AccountId32, substrate::SubstrateHeader, DefaultExtrinsicParams}, + tx::Signer, + utils::H256, + Config, +}; pub mod market; pub mod runtime; -/// Address as specified by the SCALE-encoded runtime. -type Address = AccountId32; +pub enum PolkaStorageConfig {} -#[derive(Debug, Clone, codec::Encode)] -struct CidWrapper(Cid); +type AccountIndex = u32; -// The CID has some issues that require a workaround for strings. -// For more details, see: -impl<'de> serde::de::Deserialize<'de> for CidWrapper { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let s = String::deserialize(deserializer)?; - Ok(Self( - Cid::try_from(s.as_str()).map_err(|e| serde::de::Error::custom(format!("{e:?}")))?, - )) - } -} - -impl Into for CidWrapper { - fn into(self) -> Cid { - self.0 - } +// Types are fully qualified ON PURPOSE! +// It's not fun to find out where in your config a type comes from subxt or frame_support +// going up and down, in and out the files, this helps! +impl Config for PolkaStorageConfig { + type Hash = subxt::utils::H256; + type AccountId = subxt::config::polkadot::AccountId32; + type Address = subxt::config::polkadot::MultiAddress; + type Signature = frame_support::sp_runtime::MultiSignature; + type Hasher = subxt::config::substrate::BlakeTwo256; + type Header = + subxt::config::substrate::SubstrateHeader; + type ExtrinsicParams = subxt::config::DefaultExtrinsicParams; + type AssetId = u32; } /// Currency as specified by the SCALE-encoded runtime. @@ -39,7 +37,7 @@ type Currency = u128; type BlockNumber = u32; #[derive(Debug, Clone, serde::Deserialize, codec::Encode)] -pub struct ActiveDealState { +pub struct ActiveDealState { pub sector_number: u64, pub sector_start_block: BlockNumber, pub last_updated_block: Option, @@ -47,30 +45,35 @@ pub struct ActiveDealState { } #[derive(Debug, Clone, serde::Deserialize, codec::Encode)] -pub enum DealState { +pub enum DealState { Published, - Active(ActiveDealState), + Active(ActiveDealState), } #[derive(Debug, Clone, serde::Deserialize, codec::Encode)] -pub struct DealProposal { - pub piece_cid: CidWrapper, +pub struct DealProposal +where + Config: subxt::Config, +{ + pub piece_cid: Cid, pub piece_size: u64, - pub client: Address, - pub provider: Address, + pub client: Config::Address, + pub provider: Config::Address, pub label: String, pub start_block: BlockNumber, pub end_block: BlockNumber, pub storage_price_per_block: Currency, pub provider_collateral: Currency, - pub state: DealState, + pub state: DealState, } -impl DealProposal { - fn sign(self, keypair: &Keypair) -> ClientDealProposal +impl DealProposal +where + Config: subxt::Config, +{ + fn sign(self, keypair: &Keypair) -> ClientDealProposal where Keypair: Signer, - Config: subxt::Config, { let encoded_deal_proposal = self.encode(); @@ -84,7 +87,10 @@ impl DealProposal { } } -pub struct ClientDealProposal { - pub proposal: DealProposal, - pub client: MultiSignature, // OffchainSignature +pub struct ClientDealProposal +where + Config: subxt::Config, +{ + pub proposal: DealProposal, + pub client: Config::Signature, // OffchainSignature } diff --git a/cli/polka-storage/storagext/src/market.rs b/cli/polka-storage/storagext/src/market.rs index de6b1a3e9..0b2b56bdc 100644 --- a/cli/polka-storage/storagext/src/market.rs +++ b/cli/polka-storage/storagext/src/market.rs @@ -1,6 +1,10 @@ -use frame_support::sp_runtime::AccountId32; +use frame_support::sp_runtime::MultiSignature; use primitives_proofs::DealId; -use subxt::{config::ExtrinsicParams, Config as SubxtConfig, OnlineClient}; +use subxt::{ + config::{polkadot::AccountId32, ExtrinsicParams}, + utils::Static, + Config as SubxtConfig, OnlineClient, +}; use crate::{ runtime::{self}, @@ -17,6 +21,7 @@ pub enum MarketClientError { SubxtError(#[from] subxt::Error), } +/// Client to interact with the market pallet extrinsics. pub struct MarketClient where Config: SubxtConfig, @@ -30,6 +35,9 @@ where >::Params: Default, { /// Create a new [`MarketClient`] from a target `rpc_address`. + /// + /// By default, this function does not support insecure URLs, + /// to enable support for them, use the `insecure_url` feature. pub async fn new(rpc_address: impl AsRef) -> Result { let client = if cfg!(feature = "insecure_url") { OnlineClient::::from_insecure_url(rpc_address).await? @@ -98,14 +106,14 @@ where // TODO remove skip_all #[tracing::instrument(skip_all)] - pub async fn publish_storage_deals( + pub async fn publish_storage_deals( &self, account_keypair: &Keypair, - mut deals: Vec, + mut deals: Vec>, ) -> Result where Keypair: subxt::tx::Signer, - Config: subxt::Config, + Config: subxt::Config, { if deals.len() > MAX_N_DEALS { tracing::warn!("more than {} deals, truncating", MAX_N_DEALS); @@ -120,7 +128,7 @@ where AccountId32, u128, u32, - runtime::runtime_types::sp_runtime::MultiSignature, + Static, >::from(client_deal_proposal) }) .collect(); @@ -149,13 +157,13 @@ where pub mod extrinsics { use hex::ToHex; use subxt::{config::ExtrinsicParams, OnlineClient}; - use tracing::instrument; use crate::runtime::{ self, market::calls::types::{publish_storage_deals::Deals, settle_deal_payments::DealIds}, }; + /// Withdraw `amount` of balance from an account. pub async fn withdraw_balance( client: &OnlineClient, account_keypair: &Keypair, @@ -170,11 +178,7 @@ pub mod extrinsics { traced_submission(client, &payload, account_keypair).await } - #[instrument( - skip_all, fields( - account_address = ?account_keypair.address() - ) - )] + /// Add `amount` of balance to an account. pub async fn add_balance( client: &OnlineClient, account_keypair: &Keypair, @@ -189,6 +193,7 @@ pub mod extrinsics { traced_submission(client, &payload, account_keypair).await } + /// Settle deal payments for the given `deal_ids`. pub async fn settle_deal_payments( client: &OnlineClient, account_keypair: &Keypair, @@ -203,6 +208,7 @@ pub mod extrinsics { traced_submission(client, &payload, account_keypair).await } + /// Publish the given `deals`. pub async fn publish_storage_deals( client: &OnlineClient, account_keypair: &Keypair, diff --git a/cli/polka-storage/storagext/src/runtime.rs b/cli/polka-storage/storagext/src/runtime.rs deleted file mode 100644 index cdfe4c99d..000000000 --- a/cli/polka-storage/storagext/src/runtime.rs +++ /dev/null @@ -1,67 +0,0 @@ -///! Runtime API extracted from SCALE-encoded runtime. - -#[subxt::subxt(runtime_metadata_path = "../../artifacts/metadata.scale")] -mod polka_storage_runtime {} - -use cid::Cid; -use frame_support::sp_runtime::AccountId32; -pub use polka_storage_runtime::*; -use runtime_types::pallet_market::pallet::ClientDealProposal; -use subxt::utils::MultiSignature; - -impl From - for runtime_types::pallet_market::pallet::DealProposal -{ - fn from(value: crate::DealProposal) -> Self { - Self { - piece_cid: value.piece_cid.0.into_bounded_byte_vec(), - piece_size: value.piece_size, - client: value.client, - provider: value.provider, - label: value.label.into_bounded_byte_vec(), - start_block: value.start_block, - end_block: value.end_block, - storage_price_per_block: value.storage_price_per_block, - provider_collateral: value.provider_collateral, - state: value.state, - } - } -} - -impl From - for ClientDealProposal< - AccountId32, - u128, - u32, - MultiSignature, // hmmmm - > -{ - fn from(value: crate::ClientDealProposal) -> Self { - Self { - proposal: value.proposal, - client_signature: value.client.into(), - } - } -} - -trait IntoBoundedByteVec { - fn into_bounded_byte_vec( - self, - ) -> runtime_types::bounded_collections::bounded_vec::BoundedVec; -} - -impl IntoBoundedByteVec for Cid { - fn into_bounded_byte_vec( - self, - ) -> runtime_types::bounded_collections::bounded_vec::BoundedVec { - runtime_types::bounded_collections::bounded_vec::BoundedVec(self.to_bytes()) - } -} - -impl IntoBoundedByteVec for String { - fn into_bounded_byte_vec( - self, - ) -> runtime_types::bounded_collections::bounded_vec::BoundedVec { - runtime_types::bounded_collections::bounded_vec::BoundedVec(self.into_bytes()) - } -} diff --git a/cli/polka-storage/storagext/src/runtime/bounded_vec.rs b/cli/polka-storage/storagext/src/runtime/bounded_vec.rs new file mode 100644 index 000000000..3ea4526ed --- /dev/null +++ b/cli/polka-storage/storagext/src/runtime/bounded_vec.rs @@ -0,0 +1,28 @@ +//! This module implements utilities for [`BoundedVec`](runtime_types::bounded_collections::bounded_vec::BoundedVec), +//! such as conversion traits and others. + +use cid::CidGeneric; + +use super::runtime_types::bounded_collections::bounded_vec; + +/// Trait to convert `T` into a bounded vector of bytes. +/// +/// Due to Rust's orphan rule, we cannot implement `Into> for T` +/// where we don't own `T`, which turns out to be most of the useful cases; +/// much like [`Cid`] or [`String`], which don't have official representations in Substrate. +pub(crate) trait IntoBoundedByteVec { + /// Convert [`Self`] into a bounded vector of bytes. + fn into_bounded_byte_vec(self) -> bounded_vec::BoundedVec; +} + +impl IntoBoundedByteVec for CidGeneric<64> { + fn into_bounded_byte_vec(self) -> bounded_vec::BoundedVec { + bounded_vec::BoundedVec(self.to_bytes()) + } +} + +impl IntoBoundedByteVec for String { + fn into_bounded_byte_vec(self) -> bounded_vec::BoundedVec { + bounded_vec::BoundedVec(self.into_bytes()) + } +} diff --git a/cli/polka-storage/storagext/src/runtime/mod.rs b/cli/polka-storage/storagext/src/runtime/mod.rs new file mode 100644 index 000000000..9a942ca32 --- /dev/null +++ b/cli/polka-storage/storagext/src/runtime/mod.rs @@ -0,0 +1,83 @@ +//! This module covers the Runtime API extracted from SCALE-encoded runtime and extra goodies +//! to interface with the runtime. +//! +//! This module wasn't designed to be exposed to the final user of the crate. + +mod bounded_vec; + +#[subxt::subxt( + runtime_metadata_path = "../../artifacts/metadata.scale", + substitute_type( + path = "sp_runtime::MultiSignature", + with = "::subxt::utils::Static<::frame_support::sp_runtime::MultiSignature>" + ) +)] +mod polka_storage_runtime {} + +use frame_support::sp_runtime::MultiSignature; +use subxt::{config::polkadot::AccountId32, utils::Static}; + +// Using self keeps the import separate from the others +pub use self::polka_storage_runtime::*; +use self::{ + bounded_vec::IntoBoundedByteVec, runtime_types::pallet_market::pallet as market_pallet_types, +}; + +type BlockNumber = u32; + +impl From for market_pallet_types::ActiveDealState { + fn from(value: crate::ActiveDealState) -> Self { + Self { + sector_number: value.sector_number, + sector_start_block: value.sector_start_block, + last_updated_block: value.last_updated_block, + slash_block: value.slash_block, + } + } +} + +impl From for market_pallet_types::DealState { + fn from(value: crate::DealState) -> Self { + match value { + crate::DealState::Active(value) => market_pallet_types::DealState::Active( + market_pallet_types::ActiveDealState::from(value), + ), + crate::DealState::Published => market_pallet_types::DealState::Published, + } + } +} + +impl From + for market_pallet_types::DealProposal +{ + fn from(value: crate::DealProposal) -> Self { + Self { + piece_cid: value.piece_cid.0.into_bounded_byte_vec(), + piece_size: value.piece_size, + client: AccountId32::from(value.client), + provider: AccountId32::from(value.provider), + label: value.label.into_bounded_byte_vec(), + start_block: value.start_block, + end_block: value.end_block, + storage_price_per_block: value.storage_price_per_block, + provider_collateral: value.provider_collateral, + state: market_pallet_types::DealState::from(value.state), + } + } +} + +impl From + for market_pallet_types::ClientDealProposal< + AccountId32, + u128, + BlockNumber, + Static, + > +{ + fn from(value: crate::ClientDealProposal) -> Self { + Self { + proposal: market_pallet_types::DealProposal::from(value.proposal), + client_signature: Static(value.client.into()), + } + } +} From 9d8347a2ff6a6ffd4e12c042ccf9dd5853763845 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Fri, 19 Jul 2024 16:30:56 +0000 Subject: [PATCH 05/38] feat(polka-storage): more subxt magic library now builds --- Cargo.lock | 21 ++++ Cargo.toml | 2 + cli/polka-storage/storagext-cli/Cargo.toml | 34 +++++ .../cli => storagext-cli/src}/cmd/market.rs | 0 .../storagext-cli/src/cmd/mod.rs | 1 + .../src/main.rs} | 79 +++++++++++- cli/polka-storage/storagext/Cargo.toml | 2 - .../storagext/src/bin/cli/cmd/mod.rs | 3 - .../storagext/src/bin/cli/mod.rs | 103 ---------------- cli/polka-storage/storagext/src/lib.rs | 114 ++++++++++------- cli/polka-storage/storagext/src/market.rs | 116 +++++++----------- .../storagext/src/runtime/mod.rs | 70 +---------- 12 files changed, 253 insertions(+), 292 deletions(-) create mode 100644 cli/polka-storage/storagext-cli/Cargo.toml rename cli/polka-storage/{storagext/src/bin/cli => storagext-cli/src}/cmd/market.rs (100%) create mode 100644 cli/polka-storage/storagext-cli/src/cmd/mod.rs rename cli/polka-storage/{storagext/src/bin/storagext_cli.rs => storagext-cli/src/main.rs} (62%) delete mode 100644 cli/polka-storage/storagext/src/bin/cli/cmd/mod.rs delete mode 100644 cli/polka-storage/storagext/src/bin/cli/mod.rs diff --git a/Cargo.lock b/Cargo.lock index a058de906..803157814 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14177,6 +14177,26 @@ dependencies = [ [[package]] name = "storagext" version = "0.1.0" +dependencies = [ + "anyhow", + "cid 0.11.1", + "clap", + "frame-support", + "hex", + "parity-scale-codec", + "primitives-proofs", + "subxt", + "subxt-signer", + "thiserror", + "tokio", + "tracing", + "tracing-subscriber", + "url", +] + +[[package]] +name = "storagext-cli" +version = "0.1.0" dependencies = [ "anyhow", "cid 0.11.1", @@ -14187,6 +14207,7 @@ dependencies = [ "primitives-proofs", "serde", "serde_json", + "storagext", "subxt", "subxt-signer", "thiserror", diff --git a/Cargo.toml b/Cargo.toml index 5d9c582f7..e2f4c2d88 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ repository = "https://github.com/eigerco/polka-storage" members = [ "cli/polka-storage-provider", "cli/polka-storage/storagext", + "cli/polka-storage/storagext-cli", "node", "pallets/market", "pallets/storage-provider", @@ -103,6 +104,7 @@ pallet-market = { path = "pallets/market", default-features = false } pallet-storage-provider = { path = "pallets/storage-provider", default-features = false } polka-storage-runtime = { path = "runtime" } primitives-proofs = { path = "primitives/proofs", default-features = false } +storagext = { path = "cli/polka-storage/storagext" } # Substrate pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.13.0" } diff --git a/cli/polka-storage/storagext-cli/Cargo.toml b/cli/polka-storage/storagext-cli/Cargo.toml new file mode 100644 index 000000000..dcaef5b97 --- /dev/null +++ b/cli/polka-storage/storagext-cli/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "storagext-cli" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +homepage.workspace = true +license-file.workspace = true +repository.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +storagext.workspace = true + +anyhow.workspace = true +cid = { workspace = true, features = ["scale-codec"] } +clap = { workspace = true, features = ["derive"] } +codec.workspace = true +frame-support = { workspace = true, features = ["std"] } +hex.workspace = true +primitives-proofs = { workspace = true } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } +subxt = { workspace = true, features = ["jsonrpsee"] } +subxt-signer = { workspace = true, features = ["subxt"] } +thiserror = { workspace = true } +tokio = { workspace = true, features = ["rt-multi-thread"] } +tracing = { workspace = true } +tracing-subscriber = { workspace = true, features = ["env-filter"] } +url = { workspace = true } + + +[lints] +workspace = true diff --git a/cli/polka-storage/storagext/src/bin/cli/cmd/market.rs b/cli/polka-storage/storagext-cli/src/cmd/market.rs similarity index 100% rename from cli/polka-storage/storagext/src/bin/cli/cmd/market.rs rename to cli/polka-storage/storagext-cli/src/cmd/market.rs diff --git a/cli/polka-storage/storagext-cli/src/cmd/mod.rs b/cli/polka-storage/storagext-cli/src/cmd/mod.rs new file mode 100644 index 000000000..60e5a3fee --- /dev/null +++ b/cli/polka-storage/storagext-cli/src/cmd/mod.rs @@ -0,0 +1 @@ +pub mod market; diff --git a/cli/polka-storage/storagext/src/bin/storagext_cli.rs b/cli/polka-storage/storagext-cli/src/main.rs similarity index 62% rename from cli/polka-storage/storagext/src/bin/storagext_cli.rs rename to cli/polka-storage/storagext-cli/src/main.rs index b125d2f0c..1168be1c1 100644 --- a/cli/polka-storage/storagext/src/bin/storagext_cli.rs +++ b/cli/polka-storage/storagext-cli/src/main.rs @@ -1,6 +1,6 @@ #![deny(clippy::unwrap_used)] -mod cli; +mod cmd; use clap::{ArgGroup, Parser, Subcommand}; use cli::cmd::market::MarketCommand; @@ -118,3 +118,80 @@ fn parse_ecdsa_keypair(mut src: &str) -> Result { hex::decode_to_slice(src, &mut key_bytes).unwrap(); Ok(ecdsa::Keypair::from_secret_key(key_bytes).unwrap()) } + +/// Currency as specified by the SCALE-encoded runtime. +type Currency = u128; + +/// BlockNumber as specified by the SCALE-encoded runtime. +type BlockNumber = u32; + +/// CID wrapper to get deserialization. +#[derive(Debug, Clone)] +pub struct CidWrapper(Cid); + +impl Deref for CidWrapper { + type Target = Cid; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl Into for CidWrapper { + fn into(self) -> Cid { + self.0 + } +} + +// The CID has some issues that require a workaround for strings. +// For more details, see: +impl<'de> serde::de::Deserialize<'de> for CidWrapper { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + Ok(Self( + Cid::try_from(s.as_str()).map_err(|e| serde::de::Error::custom(format!("{e:?}")))?, + )) + } +} + +#[derive(Debug, Clone, serde::Deserialize)] +pub struct ActiveDealState { + pub sector_number: u64, + pub sector_start_block: BlockNumber, + pub last_updated_block: Option, + pub slash_block: Option, +} + +impl Into> for ActiveDealState { + fn into(self) -> storagext::ActiveDealState { + storagext::ActiveDealState { + sector_number: self.sector_number, + sector_start_block: self.sector_start_block, + last_updated_block: self.last_updated_block, + slash_block: self.slash_block, + } + } +} + +#[derive(Debug, Clone, serde::Deserialize)] +pub enum DealState { + Published, + Active(ActiveDealState), +} + +#[derive(Debug, Clone, serde::Deserialize)] +pub struct DealProposal { + pub piece_cid: CidWrapper, + pub piece_size: u64, + pub client: AccountId32, + pub provider: AccountId32, + pub label: String, + pub start_block: BlockNumber, + pub end_block: BlockNumber, + pub storage_price_per_block: Currency, + pub provider_collateral: Currency, + pub state: DealState, +} diff --git a/cli/polka-storage/storagext/Cargo.toml b/cli/polka-storage/storagext/Cargo.toml index 602aba6db..685b5800b 100644 --- a/cli/polka-storage/storagext/Cargo.toml +++ b/cli/polka-storage/storagext/Cargo.toml @@ -19,8 +19,6 @@ codec.workspace = true frame-support = { workspace = true, features = ["std"] } hex.workspace = true primitives-proofs = { workspace = true } -serde = { workspace = true, features = ["derive"] } -serde_json = { workspace = true } subxt = { workspace = true, features = ["jsonrpsee"] } subxt-signer = { workspace = true, features = ["subxt"] } thiserror = { workspace = true } diff --git a/cli/polka-storage/storagext/src/bin/cli/cmd/mod.rs b/cli/polka-storage/storagext/src/bin/cli/cmd/mod.rs deleted file mode 100644 index 960a174cc..000000000 --- a/cli/polka-storage/storagext/src/bin/cli/cmd/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -use frame_support::sp_runtime::AccountId32; - -pub mod market; diff --git a/cli/polka-storage/storagext/src/bin/cli/mod.rs b/cli/polka-storage/storagext/src/bin/cli/mod.rs deleted file mode 100644 index bc9541bd6..000000000 --- a/cli/polka-storage/storagext/src/bin/cli/mod.rs +++ /dev/null @@ -1,103 +0,0 @@ -//! Contains the types required to parse the CLI arguments. -//! -//! Separated from the library ones as these ones are specific while the library ones are generic -//! and ensuring the generic ones are parseable is problematic (to say the least). - -use std::sync::Arc; - -mod cmd; - -/// Currency as specified by the SCALE-encoded runtime. -type Currency = u128; - -/// BlockNumber as specified by the SCALE-encoded runtime. -type BlockNumber = u32; - -/// CID wrapper to get deserialization. -#[derive(Debug, Clone)] -pub struct CidWrapper(Cid); - -impl Deref for CidWrapper { - type Target = Cid; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl Into for CidWrapper { - fn into(self) -> Cid { - self.0 - } -} - -// The CID has some issues that require a workaround for strings. -// For more details, see: -impl<'de> serde::de::Deserialize<'de> for CidWrapper { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let s = String::deserialize(deserializer)?; - Ok(Self( - Cid::try_from(s.as_str()).map_err(|e| serde::de::Error::custom(format!("{e:?}")))?, - )) - } -} - -#[derive(Debug, Clone, serde::Deserialize)] -pub struct ActiveDealState { - pub sector_number: u64, - pub sector_start_block: BlockNumber, - pub last_updated_block: Option, - pub slash_block: Option, -} - -impl Into> for ActiveDealState { - fn into(self) -> storagext::ActiveDealState { - storagext::ActiveDealState { - sector_number: self.sector_number, - sector_start_block: self.sector_start_block, - last_updated_block: self.last_updated_block, - slash_block: self.slash_block, - } - } -} - -#[derive(Debug, Clone, serde::Deserialize)] -pub enum DealState { - Published, - Active(ActiveDealState), -} - -#[derive(Debug, Clone, serde::Deserialize)] -pub struct DealProposal { - pub piece_cid: CidWrapper, - pub piece_size: u64, - pub client: AccountId32, - pub provider: AccountId32, - pub label: String, - pub start_block: BlockNumber, - pub end_block: BlockNumber, - pub storage_price_per_block: Currency, - pub provider_collateral: Currency, - pub state: DealState, -} - -// impl DealProposal { -// fn sign(self, keypair: &Keypair) -> ClientDealProposal -// where -// Keypair: Signer, -// Config: subxt::Config, -// { -// let encoded_deal_proposal = self.encode(); - -// let signature = keypair.sign(&encoded_deal_proposal); -// let client = MultiSignature::from(signature); - -// ClientDealProposal { -// proposal: self, -// client, -// } -// } -// } diff --git a/cli/polka-storage/storagext/src/lib.rs b/cli/polka-storage/storagext/src/lib.rs index c6d098cdf..d927c12ad 100644 --- a/cli/polka-storage/storagext/src/lib.rs +++ b/cli/polka-storage/storagext/src/lib.rs @@ -1,24 +1,31 @@ use cid::Cid; use codec::Encode; -use frame_support::sp_runtime::{traits::BlakeTwo256, MultiAddress, MultiSignature}; -use subxt::{ - config::{polkadot::AccountId32, substrate::SubstrateHeader, DefaultExtrinsicParams}, - tx::Signer, - utils::H256, - Config, -}; +use frame_support::CloneNoBound; +use subxt::{tx::Signer, utils::Static}; pub mod market; pub mod runtime; -pub enum PolkaStorageConfig {} +use crate::runtime::bounded_vec::IntoBoundedByteVec; +pub use crate::runtime::runtime_types::pallet_market::{ + pallet as market_pallet_types, + pallet::{ActiveDealState, DealState}, +}; + +/// Currency as specified by the SCALE-encoded runtime. +type Currency = u128; + +/// BlockNumber as specified by the SCALE-encoded runtime. +type BlockNumber = u32; type AccountIndex = u32; +pub enum PolkaStorageConfig {} + // Types are fully qualified ON PURPOSE! // It's not fun to find out where in your config a type comes from subxt or frame_support // going up and down, in and out the files, this helps! -impl Config for PolkaStorageConfig { +impl subxt::Config for PolkaStorageConfig { type Hash = subxt::utils::H256; type AccountId = subxt::config::polkadot::AccountId32; type Address = subxt::config::polkadot::MultiAddress; @@ -30,35 +37,16 @@ impl Config for PolkaStorageConfig { type AssetId = u32; } -/// Currency as specified by the SCALE-encoded runtime. -type Currency = u128; - -/// BlockNumber as specified by the SCALE-encoded runtime. -type BlockNumber = u32; - -#[derive(Debug, Clone, serde::Deserialize, codec::Encode)] -pub struct ActiveDealState { - pub sector_number: u64, - pub sector_start_block: BlockNumber, - pub last_updated_block: Option, - pub slash_block: Option, -} - -#[derive(Debug, Clone, serde::Deserialize, codec::Encode)] -pub enum DealState { - Published, - Active(ActiveDealState), -} - -#[derive(Debug, Clone, serde::Deserialize, codec::Encode)] -pub struct DealProposal +// We need this type because of the CID & label ergonomics. +#[derive(CloneNoBound)] +pub struct DealProposal where Config: subxt::Config, { pub piece_cid: Cid, pub piece_size: u64, - pub client: Config::Address, - pub provider: Config::Address, + pub client: Config::AccountId, + pub provider: Config::AccountId, pub label: String, pub start_block: BlockNumber, pub end_block: BlockNumber, @@ -67,30 +55,68 @@ where pub state: DealState, } -impl DealProposal +impl From> + for market_pallet_types::DealProposal +where + Config: subxt::Config, +{ + fn from(value: DealProposal) -> Self { + Self { + piece_cid: value.piece_cid.into_bounded_byte_vec(), + piece_size: value.piece_size, + client: value.client, + provider: value.provider, + label: value.label.into_bounded_byte_vec(), + start_block: value.start_block, + end_block: value.end_block, + storage_price_per_block: value.storage_price_per_block, + provider_collateral: value.provider_collateral, + state: value.state, + } + } +} + +impl DealProposal where - Config: subxt::Config, + Config: subxt::Config, { - fn sign(self, keypair: &Keypair) -> ClientDealProposal + fn sign(self, keypair: &Keypair) -> ClientDealProposal where Keypair: Signer, + Self: Into>, { - let encoded_deal_proposal = self.encode(); - - let signature = keypair.sign(&encoded_deal_proposal); - let client = MultiSignature::from(signature); + let market_deal_proposal: market_pallet_types::DealProposal<_, _, _> = self.clone().into(); + let encoded_deal_proposal = market_deal_proposal.encode(); ClientDealProposal { proposal: self, - client, + client: keypair.sign(&encoded_deal_proposal), } } } -pub struct ClientDealProposal +pub struct ClientDealProposal where Config: subxt::Config, { - pub proposal: DealProposal, - pub client: Config::Signature, // OffchainSignature + pub proposal: DealProposal, + pub client: Config::Signature, +} + +impl From> + for market_pallet_types::ClientDealProposal< + Config::AccountId, + Currency, + BlockNumber, + Static, + > +where + Config: subxt::Config, +{ + fn from(value: ClientDealProposal) -> Self { + Self { + proposal: market_pallet_types::DealProposal::from(value.proposal), + client_signature: Static(value.client), + } + } } diff --git a/cli/polka-storage/storagext/src/market.rs b/cli/polka-storage/storagext/src/market.rs index 0b2b56bdc..6bf127084 100644 --- a/cli/polka-storage/storagext/src/market.rs +++ b/cli/polka-storage/storagext/src/market.rs @@ -1,14 +1,9 @@ -use frame_support::sp_runtime::MultiSignature; use primitives_proofs::DealId; -use subxt::{ - config::{polkadot::AccountId32, ExtrinsicParams}, - utils::Static, - Config as SubxtConfig, OnlineClient, -}; +use subxt::{config::ExtrinsicParams, utils::Static, OnlineClient}; use crate::{ runtime::{self}, - DealProposal, + DealProposal, PolkaStorageConfig, }; /// The maximum number of deal IDs supported. @@ -22,27 +17,20 @@ pub enum MarketClientError { } /// Client to interact with the market pallet extrinsics. -pub struct MarketClient -where - Config: SubxtConfig, -{ - client: OnlineClient, +pub struct MarketClient { + client: OnlineClient, } -impl MarketClient -where - Config: SubxtConfig, - >::Params: Default, -{ +impl MarketClient { /// Create a new [`MarketClient`] from a target `rpc_address`. /// /// By default, this function does not support insecure URLs, /// to enable support for them, use the `insecure_url` feature. pub async fn new(rpc_address: impl AsRef) -> Result { let client = if cfg!(feature = "insecure_url") { - OnlineClient::::from_insecure_url(rpc_address).await? + OnlineClient::<_>::from_insecure_url(rpc_address).await? } else { - OnlineClient::::from_url(rpc_address).await? + OnlineClient::<_>::from_url(rpc_address).await? }; Ok(Self { client }) @@ -54,9 +42,9 @@ where &self, account_keypair: &Keypair, amount: u128, - ) -> Result + ) -> Result<::Hash, MarketClientError> where - Keypair: subxt::tx::Signer, + Keypair: subxt::tx::Signer, { Ok(extrinsics::withdraw_balance(&self.client, account_keypair, amount).await?) } @@ -67,9 +55,9 @@ where &self, account_keypair: &Keypair, amount: u128, - ) -> Result + ) -> Result<::Hash, MarketClientError> where - Keypair: subxt::tx::Signer, + Keypair: subxt::tx::Signer, { Ok(extrinsics::add_balance(&self.client, account_keypair, amount).await?) } @@ -82,9 +70,9 @@ where &self, account_keypair: &Keypair, mut deal_ids: Vec, - ) -> Result + ) -> Result<::Hash, MarketClientError> where - Keypair: subxt::tx::Signer, + Keypair: subxt::tx::Signer, { if deal_ids.len() > MAX_N_DEALS { tracing::warn!("more than {} deal ids, truncating", MAX_N_DEALS); @@ -106,14 +94,13 @@ where // TODO remove skip_all #[tracing::instrument(skip_all)] - pub async fn publish_storage_deals( + pub async fn publish_storage_deals( &self, account_keypair: &Keypair, - mut deals: Vec>, - ) -> Result + mut deals: Vec>, + ) -> Result<::Hash, MarketClientError> where - Keypair: subxt::tx::Signer, - Config: subxt::Config, + Keypair: subxt::tx::Signer, { if deals.len() > MAX_N_DEALS { tracing::warn!("more than {} deals, truncating", MAX_N_DEALS); @@ -122,15 +109,7 @@ where let signed_deal_proposals = deals .into_iter() - .map(|deal| { - let client_deal_proposal = deal.sign(account_keypair); - runtime::runtime_types::pallet_market::pallet::ClientDealProposal::< - AccountId32, - u128, - u32, - Static, - >::from(client_deal_proposal) - }) + .map(|deal| deal.sign(account_keypair).into()) .collect(); // `deals` has been truncated to fit the proper bound, however, @@ -158,66 +137,61 @@ pub mod extrinsics { use hex::ToHex; use subxt::{config::ExtrinsicParams, OnlineClient}; - use crate::runtime::{ - self, - market::calls::types::{publish_storage_deals::Deals, settle_deal_payments::DealIds}, + use crate::{ + runtime::{ + self, + market::calls::types::{publish_storage_deals::Deals, settle_deal_payments::DealIds}, + }, + PolkaStorageConfig, }; /// Withdraw `amount` of balance from an account. - pub async fn withdraw_balance( - client: &OnlineClient, + pub async fn withdraw_balance( + client: &OnlineClient, account_keypair: &Keypair, amount: u128, - ) -> Result + ) -> Result<::Hash, subxt::Error> where - Config: subxt::Config, - Keypair: subxt::tx::Signer, - >::Params: Default, + Keypair: subxt::tx::Signer, { let payload = runtime::tx().market().withdraw_balance(amount); traced_submission(client, &payload, account_keypair).await } /// Add `amount` of balance to an account. - pub async fn add_balance( - client: &OnlineClient, + pub async fn add_balance( + client: &OnlineClient, account_keypair: &Keypair, amount: u128, - ) -> Result + ) -> Result<::Hash, subxt::Error> where - Config: subxt::Config, - Keypair: subxt::tx::Signer, - >::Params: Default, + Keypair: subxt::tx::Signer, { let payload = runtime::tx().market().add_balance(amount); traced_submission(client, &payload, account_keypair).await } /// Settle deal payments for the given `deal_ids`. - pub async fn settle_deal_payments( - client: &OnlineClient, + pub async fn settle_deal_payments( + client: &OnlineClient, account_keypair: &Keypair, deal_ids: DealIds, - ) -> Result + ) -> Result<::Hash, subxt::Error> where - Config: subxt::Config, - Keypair: subxt::tx::Signer, - >::Params: Default, + Keypair: subxt::tx::Signer, { let payload = runtime::tx().market().settle_deal_payments(deal_ids); traced_submission(client, &payload, account_keypair).await } /// Publish the given `deals`. - pub async fn publish_storage_deals( - client: &OnlineClient, + pub async fn publish_storage_deals( + client: &OnlineClient, account_keypair: &Keypair, deals: Deals, - ) -> Result + ) -> Result<::Hash, subxt::Error> where - Config: subxt::Config, - Keypair: subxt::tx::Signer, - >::Params: Default, + Keypair: subxt::tx::Signer, { let payload = runtime::tx().market().publish_storage_deals(deals); traced_submission(client, &payload, account_keypair).await @@ -227,16 +201,14 @@ pub mod extrinsics { /// /// Equivalent to performing [`OnlineClient::sign_and_submit_then_watch_default`], /// followed by [`TxInBlock::wait_for_finalized`]. - async fn traced_submission( - client: &OnlineClient, + async fn traced_submission( + client: &OnlineClient, call: &Call, account_keypair: &Keypair, - ) -> Result + ) -> Result<::Hash, subxt::Error> where Call: subxt::tx::Payload, - Config: subxt::Config, - Keypair: subxt::tx::Signer, - >::Params: Default, + Keypair: subxt::tx::Signer, { tracing::info!("submitting extrinsic"); let submission_progress = client diff --git a/cli/polka-storage/storagext/src/runtime/mod.rs b/cli/polka-storage/storagext/src/runtime/mod.rs index 9a942ca32..59beeb358 100644 --- a/cli/polka-storage/storagext/src/runtime/mod.rs +++ b/cli/polka-storage/storagext/src/runtime/mod.rs @@ -3,81 +3,17 @@ //! //! This module wasn't designed to be exposed to the final user of the crate. -mod bounded_vec; +pub(crate) mod bounded_vec; #[subxt::subxt( runtime_metadata_path = "../../artifacts/metadata.scale", substitute_type( path = "sp_runtime::MultiSignature", with = "::subxt::utils::Static<::frame_support::sp_runtime::MultiSignature>" - ) + ), + derive_for_all_types = "Clone" )] mod polka_storage_runtime {} -use frame_support::sp_runtime::MultiSignature; -use subxt::{config::polkadot::AccountId32, utils::Static}; - // Using self keeps the import separate from the others pub use self::polka_storage_runtime::*; -use self::{ - bounded_vec::IntoBoundedByteVec, runtime_types::pallet_market::pallet as market_pallet_types, -}; - -type BlockNumber = u32; - -impl From for market_pallet_types::ActiveDealState { - fn from(value: crate::ActiveDealState) -> Self { - Self { - sector_number: value.sector_number, - sector_start_block: value.sector_start_block, - last_updated_block: value.last_updated_block, - slash_block: value.slash_block, - } - } -} - -impl From for market_pallet_types::DealState { - fn from(value: crate::DealState) -> Self { - match value { - crate::DealState::Active(value) => market_pallet_types::DealState::Active( - market_pallet_types::ActiveDealState::from(value), - ), - crate::DealState::Published => market_pallet_types::DealState::Published, - } - } -} - -impl From - for market_pallet_types::DealProposal -{ - fn from(value: crate::DealProposal) -> Self { - Self { - piece_cid: value.piece_cid.0.into_bounded_byte_vec(), - piece_size: value.piece_size, - client: AccountId32::from(value.client), - provider: AccountId32::from(value.provider), - label: value.label.into_bounded_byte_vec(), - start_block: value.start_block, - end_block: value.end_block, - storage_price_per_block: value.storage_price_per_block, - provider_collateral: value.provider_collateral, - state: market_pallet_types::DealState::from(value.state), - } - } -} - -impl From - for market_pallet_types::ClientDealProposal< - AccountId32, - u128, - BlockNumber, - Static, - > -{ - fn from(value: crate::ClientDealProposal) -> Self { - Self { - proposal: market_pallet_types::DealProposal::from(value.proposal), - client_signature: Static(value.client.into()), - } - } -} From c76d256221099dc9b7cd0ec926f40add389d9efd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Fri, 19 Jul 2024 16:38:15 +0000 Subject: [PATCH 06/38] feat(polka-storage): simplify --- cli/polka-storage/storagext/src/market.rs | 103 ++++------------------ 1 file changed, 18 insertions(+), 85 deletions(-) diff --git a/cli/polka-storage/storagext/src/market.rs b/cli/polka-storage/storagext/src/market.rs index 6bf127084..e9f09f2c2 100644 --- a/cli/polka-storage/storagext/src/market.rs +++ b/cli/polka-storage/storagext/src/market.rs @@ -1,5 +1,6 @@ +use hex::ToHex; use primitives_proofs::DealId; -use subxt::{config::ExtrinsicParams, utils::Static, OnlineClient}; +use subxt::OnlineClient; use crate::{ runtime::{self}, @@ -46,7 +47,8 @@ impl MarketClient { where Keypair: subxt::tx::Signer, { - Ok(extrinsics::withdraw_balance(&self.client, account_keypair, amount).await?) + let payload = runtime::tx().market().withdraw_balance(amount); + Ok(self.traced_submission(&payload, account_keypair).await?) } /// Add the given `amount` of balance. @@ -59,7 +61,8 @@ impl MarketClient { where Keypair: subxt::tx::Signer, { - Ok(extrinsics::add_balance(&self.client, account_keypair, amount).await?) + let payload = runtime::tx().market().add_balance(amount); + Ok(self.traced_submission(&payload, account_keypair).await?) } /// Settle deal payments for the provided [`DealId`]s. @@ -84,12 +87,11 @@ impl MarketClient { let bounded_unbounded_deal_ids = runtime::runtime_types::bounded_collections::bounded_vec::BoundedVec(deal_ids); - Ok(extrinsics::settle_deal_payments( - &self.client, - account_keypair, - bounded_unbounded_deal_ids, - ) - .await?) + let payload = runtime::tx() + .market() + .settle_deal_payments(bounded_unbounded_deal_ids); + + Ok(self.traced_submission(&payload, account_keypair).await?) } // TODO remove skip_all @@ -120,81 +122,11 @@ impl MarketClient { signed_deal_proposals, ); - Ok(extrinsics::publish_storage_deals( - &self.client, - account_keypair, - bounded_unbounded_deals, - ) - .await?) - } -} - -/// Module containing thin-wrappers around signing and submitting an extrinsinc. -/// -/// Separated to isolate the conversion from app types to runtime types from these calls. -/// In other words, [`crate::runtime`] types should not be used outside of this module. -pub mod extrinsics { - use hex::ToHex; - use subxt::{config::ExtrinsicParams, OnlineClient}; - - use crate::{ - runtime::{ - self, - market::calls::types::{publish_storage_deals::Deals, settle_deal_payments::DealIds}, - }, - PolkaStorageConfig, - }; - - /// Withdraw `amount` of balance from an account. - pub async fn withdraw_balance( - client: &OnlineClient, - account_keypair: &Keypair, - amount: u128, - ) -> Result<::Hash, subxt::Error> - where - Keypair: subxt::tx::Signer, - { - let payload = runtime::tx().market().withdraw_balance(amount); - traced_submission(client, &payload, account_keypair).await - } - - /// Add `amount` of balance to an account. - pub async fn add_balance( - client: &OnlineClient, - account_keypair: &Keypair, - amount: u128, - ) -> Result<::Hash, subxt::Error> - where - Keypair: subxt::tx::Signer, - { - let payload = runtime::tx().market().add_balance(amount); - traced_submission(client, &payload, account_keypair).await - } - - /// Settle deal payments for the given `deal_ids`. - pub async fn settle_deal_payments( - client: &OnlineClient, - account_keypair: &Keypair, - deal_ids: DealIds, - ) -> Result<::Hash, subxt::Error> - where - Keypair: subxt::tx::Signer, - { - let payload = runtime::tx().market().settle_deal_payments(deal_ids); - traced_submission(client, &payload, account_keypair).await - } + let payload = runtime::tx() + .market() + .publish_storage_deals(bounded_unbounded_deals); - /// Publish the given `deals`. - pub async fn publish_storage_deals( - client: &OnlineClient, - account_keypair: &Keypair, - deals: Deals, - ) -> Result<::Hash, subxt::Error> - where - Keypair: subxt::tx::Signer, - { - let payload = runtime::tx().market().publish_storage_deals(deals); - traced_submission(client, &payload, account_keypair).await + Ok(self.traced_submission(&payload, account_keypair).await?) } /// Submit an extrinsic and wait for finalization, returning the block hash it was included in. @@ -202,7 +134,7 @@ pub mod extrinsics { /// Equivalent to performing [`OnlineClient::sign_and_submit_then_watch_default`], /// followed by [`TxInBlock::wait_for_finalized`]. async fn traced_submission( - client: &OnlineClient, + &self, call: &Call, account_keypair: &Keypair, ) -> Result<::Hash, subxt::Error> @@ -211,7 +143,8 @@ pub mod extrinsics { Keypair: subxt::tx::Signer, { tracing::info!("submitting extrinsic"); - let submission_progress = client + let submission_progress = self + .client .tx() .sign_and_submit_then_watch_default(call, account_keypair) .await?; From 7138932f02a5819c3c31a7dba53fd4aba930938a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Fri, 19 Jul 2024 16:51:12 +0000 Subject: [PATCH 07/38] feat(polka-storage): simplify more --- cli/polka-storage/storagext/src/lib.rs | 59 +++++++++++------------ cli/polka-storage/storagext/src/market.rs | 2 +- 2 files changed, 29 insertions(+), 32 deletions(-) diff --git a/cli/polka-storage/storagext/src/lib.rs b/cli/polka-storage/storagext/src/lib.rs index d927c12ad..178b12e88 100644 --- a/cli/polka-storage/storagext/src/lib.rs +++ b/cli/polka-storage/storagext/src/lib.rs @@ -1,7 +1,7 @@ use cid::Cid; use codec::Encode; use frame_support::CloneNoBound; -use subxt::{tx::Signer, utils::Static}; +use subxt::{self, tx::Signer, utils::Static}; pub mod market; pub mod runtime; @@ -39,14 +39,11 @@ impl subxt::Config for PolkaStorageConfig { // We need this type because of the CID & label ergonomics. #[derive(CloneNoBound)] -pub struct DealProposal -where - Config: subxt::Config, -{ +pub struct DealProposal { pub piece_cid: Cid, pub piece_size: u64, - pub client: Config::AccountId, - pub provider: Config::AccountId, + pub client: ::AccountId, + pub provider: ::AccountId, pub label: String, pub start_block: BlockNumber, pub end_block: BlockNumber, @@ -55,12 +52,14 @@ where pub state: DealState, } -impl From> - for market_pallet_types::DealProposal -where - Config: subxt::Config, +impl From + for market_pallet_types::DealProposal< + ::AccountId, + Currency, + BlockNumber, + > { - fn from(value: DealProposal) -> Self { + fn from(value: DealProposal) -> Self { Self { piece_cid: value.piece_cid.into_bounded_byte_vec(), piece_size: value.piece_size, @@ -76,14 +75,17 @@ where } } -impl DealProposal -where - Config: subxt::Config, -{ - fn sign(self, keypair: &Keypair) -> ClientDealProposal +impl DealProposal { + fn sign(self, keypair: &Keypair) -> ClientDealProposal where - Keypair: Signer, - Self: Into>, + Keypair: Signer, + Self: Into< + market_pallet_types::DealProposal< + ::AccountId, + Currency, + BlockNumber, + >, + >, { let market_deal_proposal: market_pallet_types::DealProposal<_, _, _> = self.clone().into(); let encoded_deal_proposal = market_deal_proposal.encode(); @@ -95,25 +97,20 @@ where } } -pub struct ClientDealProposal -where - Config: subxt::Config, -{ - pub proposal: DealProposal, - pub client: Config::Signature, +pub struct ClientDealProposal { + pub proposal: DealProposal, + pub client: ::Signature, } -impl From> +impl From for market_pallet_types::ClientDealProposal< - Config::AccountId, + ::AccountId, Currency, BlockNumber, - Static, + Static<::Signature>, > -where - Config: subxt::Config, { - fn from(value: ClientDealProposal) -> Self { + fn from(value: ClientDealProposal) -> Self { Self { proposal: market_pallet_types::DealProposal::from(value.proposal), client_signature: Static(value.client), diff --git a/cli/polka-storage/storagext/src/market.rs b/cli/polka-storage/storagext/src/market.rs index e9f09f2c2..b0379c6fe 100644 --- a/cli/polka-storage/storagext/src/market.rs +++ b/cli/polka-storage/storagext/src/market.rs @@ -99,7 +99,7 @@ impl MarketClient { pub async fn publish_storage_deals( &self, account_keypair: &Keypair, - mut deals: Vec>, + mut deals: Vec, ) -> Result<::Hash, MarketClientError> where Keypair: subxt::tx::Signer, From 74d3d3abcab903523dffc10ff34fbb42eb9f1cb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Sun, 21 Jul 2024 12:52:25 +0000 Subject: [PATCH 08/38] feat(polka-storage): finish basic cli methods being successfully submitted, just need proper testing --- Cargo.lock | 1633 +++++++++++------ cli/polka-storage/storagext-cli/Cargo.toml | 6 +- .../{storagext => storagext-cli}/deals.json | 4 +- .../storagext-cli/src/cmd/market.rs | 15 +- cli/polka-storage/storagext-cli/src/main.rs | 106 +- cli/polka-storage/storagext/README.md | 8 + cli/polka-storage/storagext/src/lib.rs | 2 +- .../storagext/src/runtime/mod.rs | 2 +- 8 files changed, 1142 insertions(+), 634 deletions(-) rename cli/polka-storage/{storagext => storagext-cli}/deals.json (94%) create mode 100644 cli/polka-storage/storagext/README.md diff --git a/Cargo.lock b/Cargo.lock index 803157814..a35b438b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -71,6 +71,17 @@ dependencies = [ "subtle 2.6.0", ] +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom 0.2.15", + "once_cell", + "version_check", +] + [[package]] name = "ahash" version = "0.8.11" @@ -1217,8 +1228,8 @@ source = "git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0#d5 dependencies = [ "parity-scale-codec", "scale-info", - "sp-core", - "sp-runtime", + "sp-core 28.0.0", + "sp-runtime 31.0.1", ] [[package]] @@ -2065,8 +2076,8 @@ dependencies = [ "sc-client-api", "sc-service", "sp-blockchain", - "sp-core", - "sp-runtime", + "sp-core 28.0.0", + "sp-runtime 31.0.1", "url", ] @@ -2088,8 +2099,8 @@ dependencies = [ "sc-client-api", "sp-api", "sp-consensus", - "sp-core", - "sp-runtime", + "sp-core 28.0.0", + "sp-runtime 31.0.1", "tracing", ] @@ -2120,16 +2131,16 @@ dependencies = [ "sc-telemetry", "schnellru", "sp-api", - "sp-application-crypto", + "sp-application-crypto 30.0.0", "sp-block-builder", "sp-blockchain", "sp-consensus", "sp-consensus-aura", - "sp-core", + "sp-core 28.0.0", "sp-inherents", - "sp-keystore", - "sp-runtime", - "sp-state-machine", + "sp-keystore 0.34.0", + "sp-runtime 31.0.1", + "sp-state-machine 0.35.0", "sp-timestamp", "substrate-prometheus-endpoint", "tracing", @@ -2156,10 +2167,10 @@ dependencies = [ "sp-blockchain", "sp-consensus", "sp-consensus-slots", - "sp-core", - "sp-runtime", + "sp-core 28.0.0", + "sp-runtime 31.0.1", "sp-timestamp", - "sp-trie", + "sp-trie 29.0.0", "substrate-prometheus-endpoint", "tracing", ] @@ -2174,8 +2185,8 @@ dependencies = [ "cumulus-primitives-parachain-inherent", "sp-consensus", "sp-inherents", - "sp-runtime", - "sp-state-machine", + "sp-runtime 31.0.1", + "sp-state-machine 0.35.0", "thiserror", ] @@ -2196,9 +2207,9 @@ dependencies = [ "sc-client-api", "sp-blockchain", "sp-consensus", - "sp-core", - "sp-runtime", - "sp-state-machine", + "sp-core 28.0.0", + "sp-runtime 31.0.1", + "sp-state-machine 0.35.0", "tracing", ] @@ -2218,11 +2229,11 @@ dependencies = [ "sp-api", "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-inherents", - "sp-runtime", - "sp-state-machine", + "sp-runtime 31.0.1", + "sp-state-machine 0.35.0", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-trie", + "sp-trie 29.0.0", "tracing", ] @@ -2246,7 +2257,7 @@ dependencies = [ "sc-consensus", "sp-consensus", "sp-maybe-compressed-blob", - "sp-runtime", + "sp-runtime 31.0.1", "tracing", ] @@ -2281,9 +2292,9 @@ dependencies = [ "sp-api", "sp-blockchain", "sp-consensus", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-transaction-pool", ] @@ -2299,9 +2310,9 @@ dependencies = [ "pallet-timestamp", "parity-scale-codec", "scale-info", - "sp-application-crypto", + "sp-application-crypto 30.0.0", "sp-consensus-aura", - "sp-runtime", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -2327,18 +2338,18 @@ dependencies = [ "polkadot-runtime-common", "polkadot-runtime-parachains", "scale-info", - "sp-core", + "sp-core 28.0.0", "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-inherents", - "sp-io", - "sp-runtime", - "sp-state-machine", + "sp-io 30.0.0", + "sp-runtime 31.0.1", + "sp-state-machine 0.35.0", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-trie", + "sp-trie 29.0.0", "sp-version", "staging-xcm", "staging-xcm-builder", - "trie-db", + "trie-db 0.29.1", ] [[package]] @@ -2362,7 +2373,7 @@ dependencies = [ "frame-system", "pallet-session", "parity-scale-codec", - "sp-runtime", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -2376,8 +2387,8 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-io", - "sp-runtime", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "staging-xcm", ] @@ -2399,9 +2410,9 @@ dependencies = [ "polkadot-runtime-common", "polkadot-runtime-parachains", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "staging-xcm", "staging-xcm-builder", @@ -2418,7 +2429,7 @@ dependencies = [ "polkadot-primitives", "sp-api", "sp-consensus-aura", - "sp-runtime", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -2433,9 +2444,9 @@ dependencies = [ "polkadot-primitives", "scale-info", "sp-api", - "sp-runtime", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-trie", + "sp-trie 29.0.0", "staging-xcm", ] @@ -2448,12 +2459,12 @@ dependencies = [ "cumulus-primitives-core", "parity-scale-codec", "scale-info", - "sp-core", + "sp-core 28.0.0", "sp-inherents", - "sp-runtime", - "sp-state-machine", + "sp-runtime 31.0.1", + "sp-state-machine 0.35.0", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-trie", + "sp-trie 29.0.0", ] [[package]] @@ -2463,7 +2474,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0#d5 dependencies = [ "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-trie", + "sp-trie 29.0.0", ] [[package]] @@ -2479,7 +2490,7 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-runtime", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -2495,8 +2506,8 @@ dependencies = [ "parity-scale-codec", "polkadot-runtime-common", "polkadot-runtime-parachains", - "sp-io", - "sp-runtime", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "staging-xcm", "staging-xcm-builder", @@ -2522,9 +2533,9 @@ dependencies = [ "sc-tracing", "sp-api", "sp-consensus", - "sp-core", - "sp-runtime", - "sp-state-machine", + "sp-core 28.0.0", + "sp-runtime 31.0.1", + "sp-state-machine 0.35.0", ] [[package]] @@ -2541,7 +2552,7 @@ dependencies = [ "sc-client-api", "sp-api", "sp-blockchain", - "sp-state-machine", + "sp-state-machine 0.35.0", "thiserror", ] @@ -2581,7 +2592,7 @@ dependencies = [ "sp-blockchain", "sp-consensus", "sp-consensus-babe", - "sp-runtime", + "sp-runtime 31.0.1", "substrate-prometheus-endpoint", "tokio", "tracing", @@ -2614,9 +2625,9 @@ dependencies = [ "sp-api", "sp-authority-discovery", "sp-consensus-babe", - "sp-core", - "sp-runtime", - "sp-state-machine", + "sp-core 28.0.0", + "sp-runtime 31.0.1", + "sp-state-machine 0.35.0", "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-version", "thiserror", @@ -2634,10 +2645,10 @@ dependencies = [ "cumulus-primitives-core", "parity-scale-codec", "polkadot-primitives", - "sp-runtime", - "sp-state-machine", + "sp-runtime 31.0.1", + "sp-state-machine 0.35.0", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-trie", + "sp-trie 29.0.0", ] [[package]] @@ -3176,6 +3187,20 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ed25519-zebra" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" +dependencies = [ + "curve25519-dalek 3.2.0", + "hashbrown 0.12.3", + "hex", + "rand_core 0.6.4", + "sha2 0.9.9", + "zeroize", +] + [[package]] name = "ed25519-zebra" version = "4.0.3" @@ -3672,10 +3697,10 @@ dependencies = [ "scale-info", "serde", "sp-api", - "sp-application-crypto", - "sp-core", - "sp-io", - "sp-runtime", + "sp-application-crypto 30.0.0", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", @@ -3716,17 +3741,17 @@ dependencies = [ "serde_json", "sp-api", "sp-blockchain", - "sp-core", + "sp-core 28.0.0", "sp-database", "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-genesis-builder", "sp-inherents", - "sp-io", - "sp-keystore", - "sp-runtime", - "sp-state-machine", + "sp-io 30.0.0", + "sp-keystore 0.34.0", + "sp-runtime 31.0.1", + "sp-state-machine 0.35.0", "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-trie", + "sp-trie 29.0.0", "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "thiserror", "thousands", @@ -3753,10 +3778,10 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-arithmetic", - "sp-core", + "sp-arithmetic 23.0.0", + "sp-core 28.0.0", "sp-npos-elections", - "sp-runtime", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -3772,9 +3797,9 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -3814,7 +3839,7 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-runtime", + "sp-runtime 31.0.1", ] [[package]] @@ -3840,20 +3865,20 @@ dependencies = [ "serde_json", "smallvec", "sp-api", - "sp-arithmetic", - "sp-core", + "sp-arithmetic 23.0.0", + "sp-core 28.0.0", "sp-crypto-hashing-proc-macro", "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-genesis-builder", "sp-inherents", - "sp-io", + "sp-io 30.0.0", "sp-metadata-ir", - "sp-runtime", + "sp-runtime 31.0.1", "sp-staking", - "sp-state-machine", + "sp-state-machine 0.35.0", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-weights", + "sp-weights 27.0.0", "static_assertions", "tt-call", ] @@ -3911,12 +3936,12 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-version", - "sp-weights", + "sp-weights 27.0.0", ] [[package]] @@ -3929,8 +3954,8 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-core", - "sp-runtime", + "sp-core 28.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -3951,7 +3976,7 @@ dependencies = [ "frame-support", "parity-scale-codec", "sp-api", - "sp-runtime", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -4333,6 +4358,9 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash 0.7.8", +] [[package]] name = "hashbrown" @@ -4340,7 +4368,7 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "ahash", + "ahash 0.8.11", ] [[package]] @@ -4349,7 +4377,7 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "ahash", + "ahash 0.8.11", "allocator-api2", "serde", ] @@ -5942,6 +5970,15 @@ 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" @@ -6145,9 +6182,9 @@ dependencies = [ "sp-blockchain", "sp-consensus", "sp-consensus-beefy", - "sp-core", + "sp-core 28.0.0", "sp-mmr-primitives", - "sp-runtime", + "sp-runtime 31.0.1", ] [[package]] @@ -6160,9 +6197,9 @@ dependencies = [ "serde", "sp-api", "sp-blockchain", - "sp-core", + "sp-core 28.0.0", "sp-mmr-primitives", - "sp-runtime", + "sp-runtime 31.0.1", ] [[package]] @@ -6854,10 +6891,10 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api", - "sp-arithmetic", - "sp-core", - "sp-io", - "sp-runtime", + "sp-arithmetic 23.0.0", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -6871,8 +6908,8 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-core", - "sp-runtime", + "sp-core 28.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -6888,9 +6925,9 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -6905,8 +6942,8 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core", - "sp-runtime", + "sp-core 28.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -6921,9 +6958,9 @@ dependencies = [ "pallet-timestamp", "parity-scale-codec", "scale-info", - "sp-application-crypto", + "sp-application-crypto 30.0.0", "sp-consensus-aura", - "sp-runtime", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -6937,9 +6974,9 @@ dependencies = [ "pallet-session", "parity-scale-codec", "scale-info", - "sp-application-crypto", + "sp-application-crypto 30.0.0", "sp-authority-discovery", - "sp-runtime", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -6953,7 +6990,7 @@ dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", "scale-info", - "sp-runtime", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -6971,11 +7008,11 @@ dependencies = [ "pallet-timestamp", "parity-scale-codec", "scale-info", - "sp-application-crypto", + "sp-application-crypto 30.0.0", "sp-consensus-babe", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-session", "sp-staking", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", @@ -6996,9 +7033,9 @@ dependencies = [ "pallet-balances", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7015,7 +7052,7 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-runtime", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7033,7 +7070,7 @@ dependencies = [ "scale-info", "serde", "sp-consensus-beefy", - "sp-runtime", + "sp-runtime 31.0.1", "sp-session", "sp-staking", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", @@ -7057,10 +7094,10 @@ dependencies = [ "serde", "sp-api", "sp-consensus-beefy", - "sp-core", - "sp-io", - "sp-runtime", - "sp-state-machine", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", + "sp-state-machine 0.35.0", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7076,9 +7113,9 @@ dependencies = [ "pallet-treasury", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7095,9 +7132,9 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api", - "sp-arithmetic", - "sp-core", - "sp-runtime", + "sp-arithmetic 23.0.0", + "sp-core 28.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7114,9 +7151,9 @@ dependencies = [ "pallet-treasury", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7135,7 +7172,7 @@ dependencies = [ "parity-scale-codec", "rand 0.8.5", "scale-info", - "sp-runtime", + "sp-runtime 31.0.1", "sp-staking", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7151,9 +7188,9 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7169,8 +7206,8 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-io", - "sp-runtime", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7183,7 +7220,7 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-runtime", + "sp-runtime 31.0.1", "sp-staking", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7200,9 +7237,9 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7220,11 +7257,11 @@ dependencies = [ "parity-scale-codec", "rand 0.8.5", "scale-info", - "sp-arithmetic", - "sp-core", - "sp-io", + "sp-arithmetic 23.0.0", + "sp-core 28.0.0", + "sp-io 30.0.0", "sp-npos-elections", - "sp-runtime", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "strum 0.26.2", ] @@ -7239,7 +7276,7 @@ dependencies = [ "frame-system", "parity-scale-codec", "sp-npos-elections", - "sp-runtime", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7254,10 +7291,10 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", + "sp-core 28.0.0", + "sp-io 30.0.0", "sp-npos-elections", - "sp-runtime", + "sp-runtime 31.0.1", "sp-staking", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7275,8 +7312,8 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-io", - "sp-runtime", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-staking", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7294,11 +7331,11 @@ dependencies = [ "pallet-session", "parity-scale-codec", "scale-info", - "sp-application-crypto", + "sp-application-crypto 30.0.0", "sp-consensus-grandpa", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-session", "sp-staking", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", @@ -7316,8 +7353,8 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-io", - "sp-runtime", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7333,10 +7370,10 @@ dependencies = [ "pallet-authorship", "parity-scale-codec", "scale-info", - "sp-application-crypto", - "sp-core", - "sp-io", - "sp-runtime", + "sp-application-crypto 30.0.0", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-staking", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7351,10 +7388,10 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", + "sp-core 28.0.0", + "sp-io 30.0.0", "sp-keyring", - "sp-runtime", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7374,10 +7411,10 @@ dependencies = [ "parity-scale-codec", "primitives-proofs", "scale-info", - "sp-arithmetic", - "sp-core", - "sp-io", - "sp-runtime", + "sp-arithmetic 23.0.0", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7392,9 +7429,9 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7410,12 +7447,12 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-arithmetic", - "sp-core", - "sp-io", - "sp-runtime", + "sp-arithmetic 23.0.0", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-weights", + "sp-weights 27.0.0", ] [[package]] @@ -7429,10 +7466,10 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", + "sp-core 28.0.0", + "sp-io 30.0.0", "sp-mmr-primitives", - "sp-runtime", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7447,8 +7484,8 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-io", - "sp-runtime", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7462,9 +7499,9 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-arithmetic", - "sp-core", - "sp-runtime", + "sp-arithmetic 23.0.0", + "sp-core 28.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7479,9 +7516,9 @@ dependencies = [ "pallet-balances", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-staking", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", @@ -7502,7 +7539,7 @@ dependencies = [ "pallet-staking", "parity-scale-codec", "scale-info", - "sp-runtime", + "sp-runtime 31.0.1", "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-staking", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", @@ -7531,7 +7568,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-runtime", + "sp-runtime 31.0.1", "sp-staking", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7555,7 +7592,7 @@ dependencies = [ "pallet-staking", "parity-scale-codec", "scale-info", - "sp-runtime", + "sp-runtime 31.0.1", "sp-staking", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7573,8 +7610,8 @@ dependencies = [ "paste", "scale-info", "serde", - "sp-core", - "sp-runtime", + "sp-core 28.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7589,9 +7626,9 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7605,8 +7642,8 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-io", - "sp-runtime", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7622,10 +7659,10 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-arithmetic", - "sp-core", - "sp-io", - "sp-runtime", + "sp-arithmetic 23.0.0", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7639,8 +7676,8 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-io", - "sp-runtime", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7657,9 +7694,9 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-arithmetic", - "sp-io", - "sp-runtime", + "sp-arithmetic 23.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7672,9 +7709,9 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7690,10 +7727,10 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-io", - "sp-runtime", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-weights", + "sp-weights 27.0.0", ] [[package]] @@ -7708,14 +7745,14 @@ dependencies = [ "pallet-timestamp", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-session", "sp-staking", - "sp-state-machine", + "sp-state-machine 0.35.0", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-trie", + "sp-trie 29.0.0", ] [[package]] @@ -7730,7 +7767,7 @@ dependencies = [ "pallet-staking", "parity-scale-codec", "rand 0.8.5", - "sp-runtime", + "sp-runtime 31.0.1", "sp-session", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7747,9 +7784,9 @@ dependencies = [ "parity-scale-codec", "rand_chacha 0.3.1", "scale-info", - "sp-arithmetic", - "sp-io", - "sp-runtime", + "sp-arithmetic 23.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7769,9 +7806,9 @@ dependencies = [ "rand_chacha 0.3.1", "scale-info", "serde", - "sp-application-crypto", - "sp-io", - "sp-runtime", + "sp-application-crypto 30.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-staking", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7793,7 +7830,7 @@ version = "19.0.0" source = "git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0#d5160c1d567cc73c7df6c816d41e21aa3adb188d" dependencies = [ "log", - "sp-arithmetic", + "sp-arithmetic 23.0.0", ] [[package]] @@ -7817,9 +7854,9 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7839,10 +7876,10 @@ dependencies = [ "parity-scale-codec", "primitives-proofs", "scale-info", - "sp-arithmetic", - "sp-core", - "sp-io", - "sp-runtime", + "sp-arithmetic 23.0.0", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", ] [[package]] @@ -7856,8 +7893,8 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-io", - "sp-runtime", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7874,8 +7911,8 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-inherents", - "sp-io", - "sp-runtime", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-timestamp", @@ -7894,9 +7931,9 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7910,9 +7947,9 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7926,10 +7963,10 @@ dependencies = [ "parity-scale-codec", "sp-api", "sp-blockchain", - "sp-core", + "sp-core 28.0.0", "sp-rpc", - "sp-runtime", - "sp-weights", + "sp-runtime 31.0.1", + "sp-weights 27.0.0", ] [[package]] @@ -7940,8 +7977,8 @@ dependencies = [ "pallet-transaction-payment", "parity-scale-codec", "sp-api", - "sp-runtime", - "sp-weights", + "sp-runtime 31.0.1", + "sp-weights 27.0.0", ] [[package]] @@ -7958,8 +7995,8 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core", - "sp-runtime", + "sp-core 28.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7973,9 +8010,9 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -7990,7 +8027,7 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-runtime", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -8005,7 +8042,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api", - "sp-runtime", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -8023,9 +8060,9 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "staging-xcm", "staging-xcm-builder", @@ -8044,8 +8081,8 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-io", - "sp-runtime", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "staging-xcm", "staging-xcm-builder", @@ -8073,9 +8110,9 @@ dependencies = [ "polkadot-primitives", "scale-info", "sp-consensus-aura", - "sp-core", - "sp-io", - "sp-runtime", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "staging-parachain-info", "staging-xcm", @@ -8431,7 +8468,7 @@ dependencies = [ "thiserror", "tokio", "tracing", - "tracing-subscriber", + "tracing-subscriber 0.3.18", "uuid", ] @@ -8482,10 +8519,10 @@ dependencies = [ "sp-block-builder", "sp-blockchain", "sp-consensus-aura", - "sp-core", - "sp-io", - "sp-keystore", - "sp-runtime", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-keystore 0.34.0", + "sp-runtime 31.0.1", "sp-timestamp", "staging-xcm", "substrate-build-script-utils", @@ -8516,7 +8553,7 @@ dependencies = [ "tokio-util", "tower-http 0.5.2", "tracing", - "tracing-subscriber", + "tracing-subscriber 0.3.18", "url", "uuid", ] @@ -8564,11 +8601,11 @@ dependencies = [ "sp-api", "sp-block-builder", "sp-consensus-aura", - "sp-core", + "sp-core 28.0.0", "sp-genesis-builder", "sp-inherents", "sp-offchain", - "sp-runtime", + "sp-runtime 31.0.1", "sp-session", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-transaction-pool", @@ -8634,8 +8671,8 @@ dependencies = [ "rand 0.8.5", "sc-network", "schnellru", - "sp-core", - "sp-keystore", + "sp-core 28.0.0", + "sp-keystore 0.34.0", "thiserror", "tracing-gum", ] @@ -8692,11 +8729,11 @@ dependencies = [ "sc-storage-monitor", "sc-sysinfo", "sc-tracing", - "sp-core", - "sp-io", + "sp-core 28.0.0", + "sp-io 30.0.0", "sp-keyring", "sp-maybe-compressed-blob", - "sp-runtime", + "sp-runtime 31.0.1", "substrate-build-script-utils", "thiserror", ] @@ -8715,9 +8752,9 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "sp-core", - "sp-keystore", - "sp-runtime", + "sp-core 28.0.0", + "sp-keystore 0.34.0", + "sp-runtime 31.0.1", "thiserror", "tokio-util", "tracing-gum", @@ -8730,8 +8767,8 @@ source = "git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0#d5 dependencies = [ "parity-scale-codec", "scale-info", - "sp-core", - "sp-runtime", + "sp-core 28.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -8754,8 +8791,8 @@ dependencies = [ "polkadot-primitives", "sc-network", "schnellru", - "sp-application-crypto", - "sp-keystore", + "sp-application-crypto 30.0.0", + "sp-keystore 0.34.0", "thiserror", "tracing-gum", ] @@ -8769,8 +8806,8 @@ dependencies = [ "polkadot-node-primitives", "polkadot-primitives", "reed-solomon-novelpoly", - "sp-core", - "sp-trie", + "sp-core 28.0.0", + "sp-trie 29.0.0", "thiserror", ] @@ -8789,10 +8826,10 @@ dependencies = [ "rand_chacha 0.3.1", "sc-network", "sc-network-common", - "sp-application-crypto", - "sp-core", + "sp-application-crypto 30.0.0", + "sp-core 28.0.0", "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-keystore", + "sp-keystore 0.34.0", "tracing-gum", ] @@ -8831,7 +8868,7 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "sp-core", + "sp-core 28.0.0", "sp-maybe-compressed-blob", "thiserror", "tracing-gum", @@ -8862,10 +8899,10 @@ dependencies = [ "sc-keystore", "schnellru", "schnorrkel 0.11.4", - "sp-application-crypto", + "sp-application-crypto 30.0.0", "sp-consensus", "sp-consensus-slots", - "sp-runtime", + "sp-runtime 31.0.1", "thiserror", "tracing-gum", ] @@ -8907,7 +8944,7 @@ dependencies = [ "polkadot-primitives", "polkadot-statement-table", "schnellru", - "sp-keystore", + "sp-keystore 0.34.0", "thiserror", "tracing-gum", ] @@ -8921,7 +8958,7 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "sp-keystore", + "sp-keystore 0.34.0", "thiserror", "tracing-gum", "wasm-timer", @@ -9072,7 +9109,7 @@ dependencies = [ "polkadot-primitives", "rand 0.8.5", "slotmap", - "sp-core", + "sp-core 28.0.0", "tempfile", "thiserror", "tokio", @@ -9090,7 +9127,7 @@ dependencies = [ "polkadot-node-subsystem-util", "polkadot-overseer", "polkadot-primitives", - "sp-keystore", + "sp-keystore 0.34.0", "thiserror", "tracing-gum", ] @@ -9112,10 +9149,10 @@ dependencies = [ "sc-executor-common", "sc-executor-wasmtime", "seccompiler", - "sp-core", + "sp-core 28.0.0", "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-io", + "sp-io 30.0.0", "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "thiserror", "tracing-gum", @@ -9150,7 +9187,7 @@ dependencies = [ "polkadot-primitives", "sc-network", "sc-network-types", - "sp-core", + "sp-core 28.0.0", "thiserror", "tokio", ] @@ -9194,7 +9231,7 @@ dependencies = [ "sc-authority-discovery", "sc-network", "sc-network-types", - "sp-runtime", + "sp-runtime 31.0.1", "strum 0.26.2", "thiserror", "tracing-gum", @@ -9213,12 +9250,12 @@ dependencies = [ "polkadot-primitives", "schnorrkel 0.11.4", "serde", - "sp-application-crypto", + "sp-application-crypto 30.0.0", "sp-consensus-babe", - "sp-core", - "sp-keystore", + "sp-core 28.0.0", + "sp-keystore 0.34.0", "sp-maybe-compressed-blob", - "sp-runtime", + "sp-runtime 31.0.1", "thiserror", "zstd 0.12.4", ] @@ -9258,7 +9295,7 @@ dependencies = [ "sp-authority-discovery", "sp-blockchain", "sp-consensus-babe", - "sp-runtime", + "sp-runtime 31.0.1", "substrate-prometheus-endpoint", "thiserror", ] @@ -9292,9 +9329,9 @@ dependencies = [ "rand 0.8.5", "sc-client-api", "schnellru", - "sp-application-crypto", - "sp-core", - "sp-keystore", + "sp-application-crypto 30.0.0", + "sp-core 28.0.0", + "sp-keystore 0.34.0", "thiserror", "tracing-gum", ] @@ -9316,7 +9353,7 @@ dependencies = [ "polkadot-primitives", "sc-client-api", "sp-api", - "sp-core", + "sp-core 28.0.0", "tikv-jemalloc-ctl", "tracing-gum", ] @@ -9332,10 +9369,10 @@ dependencies = [ "polkadot-core-primitives", "scale-info", "serde", - "sp-core", - "sp-runtime", + "sp-core 28.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-weights", + "sp-weights 27.0.0", ] [[package]] @@ -9352,15 +9389,15 @@ dependencies = [ "scale-info", "serde", "sp-api", - "sp-application-crypto", - "sp-arithmetic", + "sp-application-crypto 30.0.0", + "sp-arithmetic 23.0.0", "sp-authority-discovery", "sp-consensus-slots", - "sp-core", + "sp-core 28.0.0", "sp-inherents", - "sp-io", - "sp-keystore", - "sp-runtime", + "sp-io 30.0.0", + "sp-keystore 0.34.0", + "sp-runtime 31.0.1", "sp-staking", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -9388,14 +9425,14 @@ dependencies = [ "sc-sync-state-rpc", "sc-transaction-pool-api", "sp-api", - "sp-application-crypto", + "sp-application-crypto 30.0.0", "sp-block-builder", "sp-blockchain", "sp-consensus", "sp-consensus-babe", "sp-consensus-beefy", - "sp-keystore", - "sp-runtime", + "sp-keystore 0.34.0", + "sp-runtime 31.0.1", "substrate-frame-rpc-system", "substrate-state-trie-migration-rpc", ] @@ -9437,11 +9474,11 @@ dependencies = [ "serde_derive", "slot-range-helper", "sp-api", - "sp-core", + "sp-core 28.0.0", "sp-inherents", - "sp-io", + "sp-io 30.0.0", "sp-npos-elections", - "sp-runtime", + "sp-runtime 31.0.1", "sp-session", "sp-staking", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", @@ -9498,13 +9535,13 @@ dependencies = [ "scale-info", "serde", "sp-api", - "sp-application-crypto", - "sp-arithmetic", - "sp-core", + "sp-application-crypto 30.0.0", + "sp-arithmetic 23.0.0", + "sp-core 28.0.0", "sp-inherents", - "sp-io", - "sp-keystore", - "sp-runtime", + "sp-io 30.0.0", + "sp-keystore 0.34.0", + "sp-runtime 31.0.1", "sp-session", "sp-staking", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", @@ -9611,21 +9648,21 @@ dependencies = [ "sp-consensus-babe", "sp-consensus-beefy", "sp-consensus-grandpa", - "sp-core", + "sp-core 28.0.0", "sp-inherents", - "sp-io", + "sp-io 30.0.0", "sp-keyring", - "sp-keystore", + "sp-keystore 0.34.0", "sp-mmr-primitives", "sp-offchain", - "sp-runtime", + "sp-runtime 31.0.1", "sp-session", - "sp-state-machine", + "sp-state-machine 0.35.0", "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-timestamp", "sp-transaction-pool", "sp-version", - "sp-weights", + "sp-weights 27.0.0", "staging-xcm", "substrate-prometheus-endpoint", "thiserror", @@ -9651,7 +9688,7 @@ dependencies = [ "polkadot-node-subsystem", "polkadot-node-subsystem-util", "polkadot-primitives", - "sp-keystore", + "sp-keystore 0.34.0", "sp-staking", "thiserror", "tracing-gum", @@ -9664,7 +9701,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0#d5 dependencies = [ "parity-scale-codec", "polkadot-primitives", - "sp-core", + "sp-core 28.0.0", "tracing-gum", ] @@ -9677,7 +9714,7 @@ dependencies = [ "libc", "log", "polkavm-assembler", - "polkavm-common", + "polkavm-common 0.9.0", "polkavm-linux-raw", ] @@ -9690,6 +9727,12 @@ dependencies = [ "log", ] +[[package]] +name = "polkavm-common" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92c99f7eee94e7be43ba37eef65ad0ee8cbaf89b7c00001c3f6d2be985cb1817" + [[package]] name = "polkavm-common" version = "0.9.0" @@ -9699,13 +9742,34 @@ dependencies = [ "log", ] +[[package]] +name = "polkavm-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79fa916f7962348bd1bb1a65a83401675e6fc86c51a0fdbcf92a3108e58e6125" +dependencies = [ + "polkavm-derive-impl-macro 0.8.0", +] + [[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", + "polkavm-derive-impl-macro 0.9.0", +] + +[[package]] +name = "polkavm-derive-impl" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c10b2654a8a10a83c260bfb93e97b262cf0017494ab94a65d389e0eda6de6c9c" +dependencies = [ + "polkavm-common 0.8.0", + "proc-macro2", + "quote", + "syn 2.0.66", ] [[package]] @@ -9714,19 +9778,29 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c4fdfc49717fb9a196e74a5d28e0bc764eb394a2c803eb11133a31ac996c60c" dependencies = [ - "polkavm-common", + "polkavm-common 0.9.0", "proc-macro2", "quote", "syn 2.0.66", ] +[[package]] +name = "polkavm-derive-impl-macro" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15e85319a0d5129dc9f021c62607e0804f5fb777a05cdda44d750ac0732def66" +dependencies = [ + "polkavm-derive-impl 0.8.0", + "syn 2.0.66", +] + [[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", + "polkavm-derive-impl 0.9.0", "syn 2.0.66", ] @@ -9740,7 +9814,7 @@ dependencies = [ "hashbrown 0.14.5", "log", "object 0.32.2", - "polkavm-common", + "polkavm-common 0.9.0", "regalloc2 0.9.3", "rustc-demangle", ] @@ -9903,8 +9977,8 @@ dependencies = [ "cid 0.11.1", "parity-scale-codec", "scale-info", - "sp-core", - "sp-runtime", + "sp-core 28.0.0", + "sp-runtime 31.0.1", ] [[package]] @@ -10717,19 +10791,19 @@ dependencies = [ "serde_json", "smallvec", "sp-api", - "sp-arithmetic", + "sp-arithmetic 23.0.0", "sp-authority-discovery", "sp-block-builder", "sp-consensus-babe", "sp-consensus-beefy", "sp-consensus-grandpa", - "sp-core", + "sp-core 28.0.0", "sp-genesis-builder", "sp-inherents", - "sp-io", + "sp-io 30.0.0", "sp-mmr-primitives", "sp-offchain", - "sp-runtime", + "sp-runtime 31.0.1", "sp-session", "sp-staking", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", @@ -10753,9 +10827,9 @@ dependencies = [ "polkadot-primitives", "polkadot-runtime-common", "smallvec", - "sp-core", - "sp-runtime", - "sp-weights", + "sp-core 28.0.0", + "sp-runtime 31.0.1", + "sp-weights 27.0.0", "staging-xcm", "staging-xcm-builder", ] @@ -11057,7 +11131,7 @@ version = "23.0.0" source = "git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0#d5160c1d567cc73c7df6c816d41e21aa3adb188d" dependencies = [ "log", - "sp-core", + "sp-core 28.0.0", "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "thiserror", ] @@ -11086,9 +11160,9 @@ dependencies = [ "sp-api", "sp-authority-discovery", "sp-blockchain", - "sp-core", - "sp-keystore", - "sp-runtime", + "sp-core 28.0.0", + "sp-keystore 0.34.0", + "sp-runtime 31.0.1", "substrate-prometheus-endpoint", "thiserror", ] @@ -11109,9 +11183,9 @@ dependencies = [ "sp-api", "sp-blockchain", "sp-consensus", - "sp-core", + "sp-core 28.0.0", "sp-inherents", - "sp-runtime", + "sp-runtime 31.0.1", "substrate-prometheus-endpoint", ] @@ -11124,10 +11198,10 @@ dependencies = [ "sp-api", "sp-block-builder", "sp-blockchain", - "sp-core", + "sp-core 28.0.0", "sp-inherents", - "sp-runtime", - "sp-trie", + "sp-runtime 31.0.1", + "sp-trie 29.0.0", ] [[package]] @@ -11148,12 +11222,12 @@ dependencies = [ "serde", "serde_json", "sp-blockchain", - "sp-core", + "sp-core 28.0.0", "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-genesis-builder", - "sp-io", - "sp-runtime", - "sp-state-machine", + "sp-io 30.0.0", + "sp-runtime 31.0.1", + "sp-state-machine 0.35.0", "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -11199,11 +11273,11 @@ dependencies = [ "serde", "serde_json", "sp-blockchain", - "sp-core", + "sp-core 28.0.0", "sp-keyring", - "sp-keystore", - "sp-panic-handler", - "sp-runtime", + "sp-keystore 0.34.0", + "sp-panic-handler 13.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", + "sp-runtime 31.0.1", "sp-version", "thiserror", "tokio", @@ -11225,14 +11299,14 @@ dependencies = [ "sp-api", "sp-blockchain", "sp-consensus", - "sp-core", + "sp-core 28.0.0", "sp-database", "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-runtime", - "sp-state-machine", + "sp-runtime 31.0.1", + "sp-state-machine 0.35.0", "sp-statement-store", "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-trie", + "sp-trie 29.0.0", "substrate-prometheus-endpoint", ] @@ -11253,13 +11327,13 @@ dependencies = [ "sc-client-api", "sc-state-db", "schnellru", - "sp-arithmetic", + "sp-arithmetic 23.0.0", "sp-blockchain", - "sp-core", + "sp-core 28.0.0", "sp-database", - "sp-runtime", - "sp-state-machine", - "sp-trie", + "sp-runtime 31.0.1", + "sp-state-machine 0.35.0", + "sp-trie 29.0.0", ] [[package]] @@ -11280,9 +11354,9 @@ dependencies = [ "sp-api", "sp-blockchain", "sp-consensus", - "sp-core", - "sp-runtime", - "sp-state-machine", + "sp-core 28.0.0", + "sp-runtime 31.0.1", + "sp-state-machine 0.35.0", "substrate-prometheus-endpoint", "thiserror", ] @@ -11302,16 +11376,16 @@ dependencies = [ "sc-consensus-slots", "sc-telemetry", "sp-api", - "sp-application-crypto", + "sp-application-crypto 30.0.0", "sp-block-builder", "sp-blockchain", "sp-consensus", "sp-consensus-aura", "sp-consensus-slots", - "sp-core", + "sp-core 28.0.0", "sp-inherents", - "sp-keystore", - "sp-runtime", + "sp-keystore 0.34.0", + "sp-runtime 31.0.1", "substrate-prometheus-endpoint", "thiserror", ] @@ -11337,17 +11411,17 @@ dependencies = [ "sc-telemetry", "sc-transaction-pool-api", "sp-api", - "sp-application-crypto", + "sp-application-crypto 30.0.0", "sp-block-builder", "sp-blockchain", "sp-consensus", "sp-consensus-babe", "sp-consensus-slots", - "sp-core", + "sp-core 28.0.0", "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-inherents", - "sp-keystore", - "sp-runtime", + "sp-keystore 0.34.0", + "sp-runtime 31.0.1", "substrate-prometheus-endpoint", "thiserror", ] @@ -11364,13 +11438,13 @@ dependencies = [ "sc-rpc-api", "serde", "sp-api", - "sp-application-crypto", + "sp-application-crypto 30.0.0", "sp-blockchain", "sp-consensus", "sp-consensus-babe", - "sp-core", - "sp-keystore", - "sp-runtime", + "sp-core 28.0.0", + "sp-keystore 0.34.0", + "sp-runtime 31.0.1", "thiserror", ] @@ -11395,15 +11469,15 @@ dependencies = [ "sc-network-types", "sc-utils", "sp-api", - "sp-application-crypto", - "sp-arithmetic", + "sp-application-crypto 30.0.0", + "sp-arithmetic 23.0.0", "sp-blockchain", "sp-consensus", "sp-consensus-beefy", - "sp-core", + "sp-core 28.0.0", "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-keystore", - "sp-runtime", + "sp-keystore 0.34.0", + "sp-runtime 31.0.1", "substrate-prometheus-endpoint", "thiserror", "tokio", @@ -11423,10 +11497,10 @@ dependencies = [ "sc-consensus-beefy", "sc-rpc", "serde", - "sp-application-crypto", + "sp-application-crypto 30.0.0", "sp-consensus-beefy", - "sp-core", - "sp-runtime", + "sp-core 28.0.0", + "sp-runtime 31.0.1", "thiserror", ] @@ -11440,7 +11514,7 @@ dependencies = [ "sc-client-api", "sc-consensus", "sp-blockchain", - "sp-runtime", + "sp-runtime 31.0.1", ] [[package]] @@ -11448,7 +11522,7 @@ name = "sc-consensus-grandpa" version = "0.19.0" source = "git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0#d5160c1d567cc73c7df6c816d41e21aa3adb188d" dependencies = [ - "ahash", + "ahash 0.8.11", "array-bytes", "async-trait", "dyn-clone", @@ -11474,15 +11548,15 @@ dependencies = [ "sc-utils", "serde_json", "sp-api", - "sp-application-crypto", - "sp-arithmetic", + "sp-application-crypto 30.0.0", + "sp-arithmetic 23.0.0", "sp-blockchain", "sp-consensus", "sp-consensus-grandpa", - "sp-core", + "sp-core 28.0.0", "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-keystore", - "sp-runtime", + "sp-keystore 0.34.0", + "sp-runtime 31.0.1", "substrate-prometheus-endpoint", "thiserror", ] @@ -11502,8 +11576,8 @@ dependencies = [ "sc-rpc", "serde", "sp-blockchain", - "sp-core", - "sp-runtime", + "sp-core 28.0.0", + "sp-runtime 31.0.1", "thiserror", ] @@ -11520,14 +11594,14 @@ dependencies = [ "sc-client-api", "sc-consensus", "sc-telemetry", - "sp-arithmetic", + "sp-arithmetic 23.0.0", "sp-blockchain", "sp-consensus", "sp-consensus-slots", - "sp-core", + "sp-core 28.0.0", "sp-inherents", - "sp-runtime", - "sp-state-machine", + "sp-runtime 31.0.1", + "sp-state-machine 0.35.0", ] [[package]] @@ -11542,12 +11616,12 @@ dependencies = [ "sc-executor-wasmtime", "schnellru", "sp-api", - "sp-core", + "sp-core 28.0.0", "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-io", - "sp-panic-handler", + "sp-io 30.0.0", + "sp-panic-handler 13.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-trie", + "sp-trie 29.0.0", "sp-version", "sp-wasm-interface 20.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "tracing", @@ -11609,7 +11683,7 @@ dependencies = [ "sc-network-common", "sc-network-sync", "sp-blockchain", - "sp-runtime", + "sp-runtime 31.0.1", ] [[package]] @@ -11620,9 +11694,9 @@ dependencies = [ "array-bytes", "parking_lot 0.12.3", "serde_json", - "sp-application-crypto", - "sp-core", - "sp-keystore", + "sp-application-crypto 30.0.0", + "sp-core 28.0.0", + "sp-keystore 0.34.0", "thiserror", ] @@ -11648,10 +11722,10 @@ dependencies = [ "sc-transaction-pool-api", "sp-api", "sp-consensus", - "sp-core", - "sp-keystore", + "sp-core 28.0.0", + "sp-keystore 0.34.0", "sp-mixnet", - "sp-runtime", + "sp-runtime 31.0.1", "thiserror", ] @@ -11692,10 +11766,10 @@ dependencies = [ "serde", "serde_json", "smallvec", - "sp-arithmetic", + "sp-arithmetic 23.0.0", "sp-blockchain", - "sp-core", - "sp-runtime", + "sp-core 28.0.0", + "sp-runtime 31.0.1", "substrate-prometheus-endpoint", "thiserror", "tokio", @@ -11721,7 +11795,7 @@ dependencies = [ "sc-network-types", "sp-consensus", "sp-consensus-grandpa", - "sp-runtime", + "sp-runtime 31.0.1", ] [[package]] @@ -11729,7 +11803,7 @@ name = "sc-network-gossip" version = "0.34.0" source = "git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0#d5160c1d567cc73c7df6c816d41e21aa3adb188d" dependencies = [ - "ahash", + "ahash 0.8.11", "futures", "futures-timer", "libp2p", @@ -11739,7 +11813,7 @@ dependencies = [ "sc-network-sync", "sc-network-types", "schnellru", - "sp-runtime", + "sp-runtime 31.0.1", "substrate-prometheus-endpoint", "tracing", ] @@ -11760,8 +11834,8 @@ dependencies = [ "sc-network", "sc-network-types", "sp-blockchain", - "sp-core", - "sp-runtime", + "sp-core 28.0.0", + "sp-runtime 31.0.1", "thiserror", ] @@ -11790,12 +11864,12 @@ dependencies = [ "sc-utils", "schnellru", "smallvec", - "sp-arithmetic", + "sp-arithmetic 23.0.0", "sp-blockchain", "sp-consensus", "sp-consensus-grandpa", - "sp-core", - "sp-runtime", + "sp-core 28.0.0", + "sp-runtime 31.0.1", "substrate-prometheus-endpoint", "thiserror", "tokio", @@ -11818,7 +11892,7 @@ dependencies = [ "sc-network-types", "sc-utils", "sp-consensus", - "sp-runtime", + "sp-runtime 31.0.1", "substrate-prometheus-endpoint", ] @@ -11864,11 +11938,11 @@ dependencies = [ "sc-transaction-pool-api", "sc-utils", "sp-api", - "sp-core", + "sp-core 28.0.0", "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-keystore", + "sp-keystore 0.34.0", "sp-offchain", - "sp-runtime", + "sp-runtime 31.0.1", "threadpool", "tracing", ] @@ -11903,11 +11977,11 @@ dependencies = [ "serde_json", "sp-api", "sp-blockchain", - "sp-core", - "sp-keystore", + "sp-core 28.0.0", + "sp-keystore 0.34.0", "sp-offchain", "sp-rpc", - "sp-runtime", + "sp-runtime 31.0.1", "sp-session", "sp-statement-store", "sp-version", @@ -11927,9 +12001,9 @@ dependencies = [ "scale-info", "serde", "serde_json", - "sp-core", + "sp-core 28.0.0", "sp-rpc", - "sp-runtime", + "sp-runtime 31.0.1", "sp-version", "thiserror", ] @@ -11977,9 +12051,9 @@ dependencies = [ "serde", "sp-api", "sp-blockchain", - "sp-core", + "sp-core 28.0.0", "sp-rpc", - "sp-runtime", + "sp-runtime 31.0.1", "sp-version", "thiserror", "tokio", @@ -12030,16 +12104,16 @@ dependencies = [ "sp-api", "sp-blockchain", "sp-consensus", - "sp-core", + "sp-core 28.0.0", "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-keystore", - "sp-runtime", + "sp-keystore 0.34.0", + "sp-runtime 31.0.1", "sp-session", - "sp-state-machine", + "sp-state-machine 0.35.0", "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-transaction-pool", "sp-transaction-storage-proof", - "sp-trie", + "sp-trie 29.0.0", "sp-version", "static_init", "substrate-prometheus-endpoint", @@ -12058,7 +12132,7 @@ dependencies = [ "log", "parity-scale-codec", "parking_lot 0.12.3", - "sp-core", + "sp-core 28.0.0", ] [[package]] @@ -12069,7 +12143,7 @@ dependencies = [ "clap", "fs4", "log", - "sp-core", + "sp-core 28.0.0", "thiserror", "tokio", ] @@ -12089,7 +12163,7 @@ dependencies = [ "serde", "serde_json", "sp-blockchain", - "sp-runtime", + "sp-runtime 31.0.1", "thiserror", ] @@ -12108,9 +12182,9 @@ dependencies = [ "sc-telemetry", "serde", "serde_json", - "sp-core", + "sp-core 28.0.0", "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-io", + "sp-io 30.0.0", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -12154,14 +12228,14 @@ dependencies = [ "serde", "sp-api", "sp-blockchain", - "sp-core", + "sp-core 28.0.0", "sp-rpc", - "sp-runtime", + "sp-runtime 31.0.1", "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "thiserror", "tracing", - "tracing-log", - "tracing-subscriber", + "tracing-log 0.2.0", + "tracing-subscriber 0.3.18", ] [[package]] @@ -12193,9 +12267,9 @@ dependencies = [ "serde", "sp-api", "sp-blockchain", - "sp-core", + "sp-core 28.0.0", "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-runtime", + "sp-runtime 31.0.1", "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-transaction-pool", "substrate-prometheus-endpoint", @@ -12213,8 +12287,8 @@ dependencies = [ "parity-scale-codec", "serde", "sp-blockchain", - "sp-core", - "sp-runtime", + "sp-core 28.0.0", + "sp-runtime 31.0.1", "thiserror", ] @@ -12230,7 +12304,7 @@ dependencies = [ "log", "parking_lot 0.12.3", "prometheus", - "sp-arithmetic", + "sp-arithmetic 23.0.0", ] [[package]] @@ -12385,7 +12459,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9a8ef13a93c54d20580de1e5c413e624e53121d42fc7e2c11d10ef7f8b02367" dependencies = [ - "ahash", + "ahash 0.8.11", "cfg-if", "hashbrown 0.13.2", ] @@ -12847,7 +12921,7 @@ dependencies = [ "enumn", "parity-scale-codec", "paste", - "sp-runtime", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -12916,7 +12990,7 @@ dependencies = [ "chacha20", "crossbeam-queue", "derive_more", - "ed25519-zebra", + "ed25519-zebra 4.0.3", "either", "event-listener 2.5.3", "fnv", @@ -12970,7 +13044,7 @@ dependencies = [ "chacha20", "crossbeam-queue", "derive_more", - "ed25519-zebra", + "ed25519-zebra 4.0.3", "either", "event-listener 4.0.3", "fnv", @@ -13151,14 +13225,14 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api-proc-macro", - "sp-core", + "sp-core 28.0.0", "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-metadata-ir", - "sp-runtime", + "sp-runtime 31.0.1", "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-state-machine", + "sp-state-machine 0.35.0", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-trie", + "sp-trie 29.0.0", "sp-version", "thiserror", ] @@ -13185,11 +13259,25 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core", - "sp-io", + "sp-core 28.0.0", + "sp-io 30.0.0", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] +[[package]] +name = "sp-application-crypto" +version = "33.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13ca6121c22c8bd3d1dce1f05c479101fd0d7b159bef2a3e8c834138d839c75c" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", + "sp-core 31.0.0", + "sp-io 33.0.0", + "sp-std 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "sp-arithmetic" version = "23.0.0" @@ -13205,6 +13293,21 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "sp-arithmetic" +version = "25.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "910c07fa263b20bf7271fdd4adcb5d3217dfdac14270592e0780223542e7e114" +dependencies = [ + "integer-sqrt", + "num-traits", + "parity-scale-codec", + "scale-info", + "serde", + "sp-std 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "static_assertions", +] + [[package]] name = "sp-ark-bls12-381" version = "0.4.2" @@ -13231,8 +13334,8 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api", - "sp-application-crypto", - "sp-runtime", + "sp-application-crypto 30.0.0", + "sp-runtime 31.0.1", ] [[package]] @@ -13242,7 +13345,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0#d5 dependencies = [ "sp-api", "sp-inherents", - "sp-runtime", + "sp-runtime 31.0.1", ] [[package]] @@ -13258,8 +13361,8 @@ dependencies = [ "sp-api", "sp-consensus", "sp-database", - "sp-runtime", - "sp-state-machine", + "sp-runtime 31.0.1", + "sp-state-machine 0.35.0", "thiserror", ] @@ -13271,10 +13374,10 @@ dependencies = [ "async-trait", "futures", "log", - "sp-core", + "sp-core 28.0.0", "sp-inherents", - "sp-runtime", - "sp-state-machine", + "sp-runtime 31.0.1", + "sp-state-machine 0.35.0", "thiserror", ] @@ -13287,10 +13390,10 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api", - "sp-application-crypto", + "sp-application-crypto 30.0.0", "sp-consensus-slots", "sp-inherents", - "sp-runtime", + "sp-runtime 31.0.1", "sp-timestamp", ] @@ -13304,11 +13407,11 @@ dependencies = [ "scale-info", "serde", "sp-api", - "sp-application-crypto", + "sp-application-crypto 30.0.0", "sp-consensus-slots", - "sp-core", + "sp-core 28.0.0", "sp-inherents", - "sp-runtime", + "sp-runtime 31.0.1", "sp-timestamp", ] @@ -13322,13 +13425,13 @@ dependencies = [ "scale-info", "serde", "sp-api", - "sp-application-crypto", - "sp-core", + "sp-application-crypto 30.0.0", + "sp-core 28.0.0", "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-io", - "sp-keystore", + "sp-io 30.0.0", + "sp-keystore 0.34.0", "sp-mmr-primitives", - "sp-runtime", + "sp-runtime 31.0.1", "strum 0.26.2", ] @@ -13343,10 +13446,10 @@ dependencies = [ "scale-info", "serde", "sp-api", - "sp-application-crypto", - "sp-core", - "sp-keystore", - "sp-runtime", + "sp-application-crypto 30.0.0", + "sp-core 28.0.0", + "sp-keystore 0.34.0", + "sp-runtime 31.0.1", ] [[package]] @@ -13372,7 +13475,7 @@ dependencies = [ "bounded-collections", "bs58 0.5.1", "dyn-clonable", - "ed25519-zebra", + "ed25519-zebra 4.0.3", "futures", "hash-db", "hash256-std-hasher", @@ -13400,7 +13503,54 @@ dependencies = [ "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "ss58-registry", - "substrate-bip39", + "substrate-bip39 0.4.7", + "thiserror", + "tracing", + "w3f-bls", + "zeroize", +] + +[[package]] +name = "sp-core" +version = "31.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d7a0fd8f16dcc3761198fc83be12872f823b37b749bc72a3a6a1f702509366" +dependencies = [ + "array-bytes", + "bitflags 1.3.2", + "blake2 0.10.6", + "bounded-collections", + "bs58 0.5.1", + "dyn-clonable", + "ed25519-zebra 3.1.0", + "futures", + "hash-db", + "hash256-std-hasher", + "impl-serde", + "itertools 0.10.5", + "k256", + "libsecp256k1", + "log", + "merlin", + "parity-bip39", + "parity-scale-codec", + "parking_lot 0.12.3", + "paste", + "primitive-types", + "rand 0.8.5", + "scale-info", + "schnorrkel 0.11.4", + "secp256k1", + "secrecy", + "serde", + "sp-crypto-hashing 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-debug-derive 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-externalities 0.27.0", + "sp-runtime-interface 26.0.0", + "sp-std 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-storage 20.0.0", + "ss58-registry", + "substrate-bip39 0.5.0", "thiserror", "tracing", "w3f-bls", @@ -13473,6 +13623,17 @@ dependencies = [ "parking_lot 0.12.3", ] +[[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.66", +] + [[package]] name = "sp-debug-derive" version = "14.0.0" @@ -13513,6 +13674,18 @@ dependencies = [ "sp-storage 19.0.0 (git+https://github.com/paritytech/polkadot-sdk)", ] +[[package]] +name = "sp-externalities" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d6a4572eadd4a63cff92509a210bf425501a0c5e76574b30a366ac77653787" +dependencies = [ + "environmental", + "parity-scale-codec", + "sp-std 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-storage 20.0.0", +] + [[package]] name = "sp-genesis-builder" version = "0.8.0" @@ -13522,7 +13695,7 @@ dependencies = [ "scale-info", "serde_json", "sp-api", - "sp-runtime", + "sp-runtime 31.0.1", ] [[package]] @@ -13534,7 +13707,7 @@ dependencies = [ "impl-trait-for-tuples", "parity-scale-codec", "scale-info", - "sp-runtime", + "sp-runtime 31.0.1", "thiserror", ] @@ -13548,18 +13721,45 @@ dependencies = [ "libsecp256k1", "log", "parity-scale-codec", - "polkavm-derive", + "polkavm-derive 0.9.1", "rustversion", "secp256k1", - "sp-core", + "sp-core 28.0.0", "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-keystore", + "sp-keystore 0.34.0", "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-state-machine", + "sp-state-machine 0.35.0", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-tracing 16.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-trie", + "sp-trie 29.0.0", + "tracing", + "tracing-core", +] + +[[package]] +name = "sp-io" +version = "33.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e09bba780b55bd9e67979cd8f654a31e4a6cf45426ff371394a65953d2177f2" +dependencies = [ + "bytes", + "ed25519-dalek 2.1.1", + "libsecp256k1", + "log", + "parity-scale-codec", + "polkavm-derive 0.9.1", + "rustversion", + "secp256k1", + "sp-core 31.0.0", + "sp-crypto-hashing 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-externalities 0.27.0", + "sp-keystore 0.37.0", + "sp-runtime-interface 26.0.0", + "sp-state-machine 0.38.0", + "sp-std 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-tracing 16.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-trie 32.0.0", "tracing", "tracing-core", ] @@ -13569,8 +13769,8 @@ name = "sp-keyring" version = "31.0.0" source = "git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0#d5160c1d567cc73c7df6c816d41e21aa3adb188d" dependencies = [ - "sp-core", - "sp-runtime", + "sp-core 28.0.0", + "sp-runtime 31.0.1", "strum 0.26.2", ] @@ -13581,10 +13781,22 @@ source = "git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0#d5 dependencies = [ "parity-scale-codec", "parking_lot 0.12.3", - "sp-core", + "sp-core 28.0.0", "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] +[[package]] +name = "sp-keystore" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdbab8b61bd61d5f8625a0c75753b5d5a23be55d3445419acd42caf59cf6236b" +dependencies = [ + "parity-scale-codec", + "parking_lot 0.12.3", + "sp-core 31.0.0", + "sp-externalities 0.27.0", +] + [[package]] name = "sp-maybe-compressed-blob" version = "11.0.0" @@ -13612,7 +13824,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api", - "sp-application-crypto", + "sp-application-crypto 30.0.0", ] [[package]] @@ -13626,9 +13838,9 @@ dependencies = [ "scale-info", "serde", "sp-api", - "sp-core", + "sp-core 28.0.0", "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-runtime", + "sp-runtime 31.0.1", "thiserror", ] @@ -13640,9 +13852,9 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-arithmetic", - "sp-core", - "sp-runtime", + "sp-arithmetic 23.0.0", + "sp-core 28.0.0", + "sp-runtime 31.0.1", ] [[package]] @@ -13651,8 +13863,19 @@ version = "26.0.0" source = "git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0#d5160c1d567cc73c7df6c816d41e21aa3adb188d" dependencies = [ "sp-api", - "sp-core", - "sp-runtime", + "sp-core 28.0.0", + "sp-runtime 31.0.1", +] + +[[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]] @@ -13672,7 +13895,7 @@ source = "git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0#d5 dependencies = [ "rustc-hash", "serde", - "sp-core", + "sp-core 28.0.0", ] [[package]] @@ -13692,12 +13915,37 @@ dependencies = [ "scale-info", "serde", "simple-mermaid", - "sp-application-crypto", - "sp-arithmetic", - "sp-core", - "sp-io", + "sp-application-crypto 30.0.0", + "sp-arithmetic 23.0.0", + "sp-core 28.0.0", + "sp-io 30.0.0", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-weights", + "sp-weights 27.0.0", +] + +[[package]] +name = "sp-runtime" +version = "34.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3cb126971e7db2f0fcf8053dce740684c438c7180cfca1959598230f342c58" +dependencies = [ + "docify", + "either", + "hash256-std-hasher", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "paste", + "rand 0.8.5", + "scale-info", + "serde", + "simple-mermaid", + "sp-application-crypto 33.0.0", + "sp-arithmetic 25.0.0", + "sp-core 31.0.0", + "sp-io 33.0.0", + "sp-std 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-weights 30.0.0", ] [[package]] @@ -13708,7 +13956,7 @@ dependencies = [ "bytes", "impl-trait-for-tuples", "parity-scale-codec", - "polkavm-derive", + "polkavm-derive 0.9.1", "primitive-types", "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-runtime-interface-proc-macro 17.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", @@ -13727,7 +13975,7 @@ dependencies = [ "bytes", "impl-trait-for-tuples", "parity-scale-codec", - "polkavm-derive", + "polkavm-derive 0.9.1", "primitive-types", "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk)", "sp-runtime-interface-proc-macro 17.0.0 (git+https://github.com/paritytech/polkadot-sdk)", @@ -13738,6 +13986,26 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "sp-runtime-interface" +version = "26.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a675ea4858333d4d755899ed5ed780174aa34fec15953428d516af5452295" +dependencies = [ + "bytes", + "impl-trait-for-tuples", + "parity-scale-codec", + "polkavm-derive 0.8.0", + "primitive-types", + "sp-externalities 0.27.0", + "sp-runtime-interface-proc-macro 18.0.0", + "sp-std 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-storage 20.0.0", + "sp-tracing 16.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-wasm-interface 20.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "static_assertions", +] + [[package]] name = "sp-runtime-interface-proc-macro" version = "17.0.0" @@ -13764,6 +14032,20 @@ dependencies = [ "syn 2.0.66", ] +[[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.66", +] + [[package]] name = "sp-session" version = "27.0.0" @@ -13772,9 +14054,9 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api", - "sp-core", - "sp-keystore", - "sp-runtime", + "sp-core 28.0.0", + "sp-keystore 0.34.0", + "sp-runtime 31.0.1", "sp-staking", ] @@ -13787,8 +14069,8 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-core", - "sp-runtime", + "sp-core 28.0.0", + "sp-runtime 31.0.1", ] [[package]] @@ -13802,13 +14084,35 @@ dependencies = [ "parking_lot 0.12.3", "rand 0.8.5", "smallvec", - "sp-core", + "sp-core 28.0.0", "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-panic-handler", - "sp-trie", + "sp-panic-handler 13.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", + "sp-trie 29.0.0", + "thiserror", + "tracing", + "trie-db 0.29.1", +] + +[[package]] +name = "sp-state-machine" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1eae0eac8034ba14437e772366336f579398a46d101de13dbb781ab1e35e67c5" +dependencies = [ + "hash-db", + "log", + "parity-scale-codec", + "parking_lot 0.12.3", + "rand 0.8.5", + "smallvec", + "sp-core 31.0.0", + "sp-externalities 0.27.0", + "sp-panic-handler 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-std 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-trie 32.0.0", "thiserror", "tracing", - "trie-db", + "trie-db 0.28.0", ] [[package]] @@ -13825,16 +14129,22 @@ dependencies = [ "scale-info", "sha2 0.10.8", "sp-api", - "sp-application-crypto", - "sp-core", + "sp-application-crypto 30.0.0", + "sp-core 28.0.0", "sp-crypto-hashing 0.1.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-runtime", + "sp-runtime 31.0.1", "sp-runtime-interface 24.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "thiserror", "x25519-dalek 2.0.1", ] +[[package]] +name = "sp-std" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f8ee986414b0a9ad741776762f4083cd3a5128449b982a3919c4df36874834" + [[package]] name = "sp-std" version = "14.0.0" @@ -13869,6 +14179,20 @@ dependencies = [ "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk)", ] +[[package]] +name = "sp-storage" +version = "20.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dba5791cb3978e95daf99dad919ecb3ec35565604e88cd38d805d9d4981e8bd" +dependencies = [ + "impl-serde", + "parity-scale-codec", + "ref-cast", + "serde", + "sp-debug-derive 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-std 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "sp-timestamp" version = "26.0.0" @@ -13877,10 +14201,23 @@ dependencies = [ "async-trait", "parity-scale-codec", "sp-inherents", - "sp-runtime", + "sp-runtime 31.0.1", "thiserror", ] +[[package]] +name = "sp-tracing" +version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0351810b9d074df71c4514c5228ed05c250607cba131c1c9d1526760ab69c05c" +dependencies = [ + "parity-scale-codec", + "sp-std 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tracing", + "tracing-core", + "tracing-subscriber 0.2.25", +] + [[package]] name = "sp-tracing" version = "16.0.0" @@ -13889,7 +14226,7 @@ dependencies = [ "parity-scale-codec", "tracing", "tracing-core", - "tracing-subscriber", + "tracing-subscriber 0.3.18", ] [[package]] @@ -13900,7 +14237,7 @@ dependencies = [ "parity-scale-codec", "tracing", "tracing-core", - "tracing-subscriber", + "tracing-subscriber 0.3.18", ] [[package]] @@ -13909,7 +14246,7 @@ version = "26.0.0" source = "git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0#d5160c1d567cc73c7df6c816d41e21aa3adb188d" dependencies = [ "sp-api", - "sp-runtime", + "sp-runtime 31.0.1", ] [[package]] @@ -13920,10 +14257,10 @@ dependencies = [ "async-trait", "parity-scale-codec", "scale-info", - "sp-core", + "sp-core 28.0.0", "sp-inherents", - "sp-runtime", - "sp-trie", + "sp-runtime 31.0.1", + "sp-trie 29.0.0", ] [[package]] @@ -13931,7 +14268,7 @@ name = "sp-trie" version = "29.0.0" source = "git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0#d5160c1d567cc73c7df6c816d41e21aa3adb188d" dependencies = [ - "ahash", + "ahash 0.8.11", "hash-db", "lazy_static", "memory-db", @@ -13941,11 +14278,36 @@ dependencies = [ "rand 0.8.5", "scale-info", "schnellru", - "sp-core", + "sp-core 28.0.0", "sp-externalities 0.25.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "thiserror", "tracing", - "trie-db", + "trie-db 0.29.1", + "trie-root", +] + +[[package]] +name = "sp-trie" +version = "32.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1aa91ad26c62b93d73e65f9ce7ebd04459c4bad086599348846a81988d6faa4" +dependencies = [ + "ahash 0.8.11", + "hash-db", + "lazy_static", + "memory-db", + "nohash-hasher", + "parity-scale-codec", + "parking_lot 0.12.3", + "rand 0.8.5", + "scale-info", + "schnellru", + "sp-core 31.0.0", + "sp-externalities 0.27.0", + "sp-std 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror", + "tracing", + "trie-db 0.28.0", "trie-root", ] @@ -13960,7 +14322,7 @@ dependencies = [ "scale-info", "serde", "sp-crypto-hashing-proc-macro", - "sp-runtime", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", "sp-version-proc-macro", "thiserror", @@ -13977,6 +14339,20 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "sp-wasm-interface" +version = "20.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ef97172c42eb4c6c26506f325f48463e9bc29b2034a587f1b9e48c751229bee" +dependencies = [ + "anyhow", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "sp-std 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmtime", +] + [[package]] name = "sp-wasm-interface" version = "20.0.0" @@ -14009,10 +14385,26 @@ dependencies = [ "scale-info", "serde", "smallvec", - "sp-arithmetic", + "sp-arithmetic 23.0.0", "sp-debug-derive 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] +[[package]] +name = "sp-weights" +version = "30.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9af6c661fe3066b29f9e1d258000f402ff5cc2529a9191972d214e5871d0ba87" +dependencies = [ + "bounded-collections", + "parity-scale-codec", + "scale-info", + "serde", + "smallvec", + "sp-arithmetic 25.0.0", + "sp-debug-derive 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-std 14.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "spin" version = "0.5.2" @@ -14075,7 +14467,7 @@ dependencies = [ "frame-system", "parity-scale-codec", "scale-info", - "sp-runtime", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", ] @@ -14093,7 +14485,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-weights", + "sp-weights 27.0.0", "xcm-procedural", ] @@ -14110,11 +14502,11 @@ dependencies = [ "parity-scale-codec", "polkadot-parachain-primitives", "scale-info", - "sp-arithmetic", - "sp-io", - "sp-runtime", + "sp-arithmetic 23.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-weights", + "sp-weights 27.0.0", "staging-xcm", "staging-xcm-executor", ] @@ -14131,12 +14523,12 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "sp-arithmetic", - "sp-core", - "sp-io", - "sp-runtime", + "sp-arithmetic 23.0.0", + "sp-core 28.0.0", + "sp-io 30.0.0", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-weights", + "sp-weights 27.0.0", "staging-xcm", ] @@ -14190,7 +14582,7 @@ dependencies = [ "thiserror", "tokio", "tracing", - "tracing-subscriber", + "tracing-subscriber 0.3.18", "url", ] @@ -14213,7 +14605,7 @@ dependencies = [ "thiserror", "tokio", "tracing", - "tracing-subscriber", + "tracing-subscriber 0.3.18", "url", ] @@ -14315,6 +14707,19 @@ dependencies = [ "zeroize", ] +[[package]] +name = "substrate-bip39" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2b564c293e6194e8b222e52436bcb99f60de72043c7f845cf6c4406db4df121" +dependencies = [ + "hmac 0.12.1", + "pbkdf2", + "schnorrkel 0.11.4", + "sha2 0.10.8", + "zeroize", +] + [[package]] name = "substrate-build-script-utils" version = "11.0.0" @@ -14335,8 +14740,8 @@ dependencies = [ "sp-api", "sp-block-builder", "sp-blockchain", - "sp-core", - "sp-runtime", + "sp-core 28.0.0", + "sp-runtime 31.0.1", ] [[package]] @@ -14361,11 +14766,11 @@ dependencies = [ "sc-client-api", "sc-rpc-api", "serde", - "sp-core", - "sp-runtime", - "sp-state-machine", - "sp-trie", - "trie-db", + "sp-core 28.0.0", + "sp-runtime 31.0.1", + "sp-state-machine 0.35.0", + "sp-trie 29.0.0", + "trie-db 0.29.1", ] [[package]] @@ -14484,7 +14889,9 @@ dependencies = [ "scale-value", "serde", "serde_json", + "sp-core 31.0.0", "sp-crypto-hashing 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sp-runtime 34.0.0", "subxt-metadata", "tracing", ] @@ -15133,6 +15540,17 @@ dependencies = [ "syn 2.0.66", ] +[[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" @@ -15144,13 +15562,45 @@ dependencies = [ "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", + "matchers 0.1.0", "nu-ansi-term", "once_cell", "parking_lot 0.12.3", @@ -15160,7 +15610,20 @@ dependencies = [ "thread_local", "tracing", "tracing-core", - "tracing-log", + "tracing-log 0.2.0", +] + +[[package]] +name = "trie-db" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff28e0f815c2fea41ebddf148e008b077d2faddb026c9555b29696114d602642" +dependencies = [ + "hash-db", + "hashbrown 0.13.2", + "log", + "rustc-hex", + "smallvec", ] [[package]] @@ -16029,20 +16492,20 @@ dependencies = [ "serde_derive", "smallvec", "sp-api", - "sp-application-crypto", - "sp-arithmetic", + "sp-application-crypto 30.0.0", + "sp-arithmetic 23.0.0", "sp-authority-discovery", "sp-block-builder", "sp-consensus-babe", "sp-consensus-beefy", - "sp-core", + "sp-core 28.0.0", "sp-genesis-builder", "sp-inherents", - "sp-io", + "sp-io 30.0.0", "sp-mmr-primitives", "sp-npos-elections", "sp-offchain", - "sp-runtime", + "sp-runtime 31.0.1", "sp-session", "sp-staking", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", @@ -16066,9 +16529,9 @@ dependencies = [ "polkadot-primitives", "polkadot-runtime-common", "smallvec", - "sp-core", - "sp-runtime", - "sp-weights", + "sp-core 28.0.0", + "sp-runtime 31.0.1", + "sp-weights 27.0.0", "staging-xcm", "staging-xcm-builder", ] @@ -16484,9 +16947,9 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-api", - "sp-runtime", + "sp-runtime 31.0.1", "sp-std 14.0.0 (git+https://github.com/paritytech/polkadot-sdk?tag=polkadot-v1.13.0)", - "sp-weights", + "sp-weights 27.0.0", "staging-xcm", ] diff --git a/cli/polka-storage/storagext-cli/Cargo.toml b/cli/polka-storage/storagext-cli/Cargo.toml index dcaef5b97..2642d8eb8 100644 --- a/cli/polka-storage/storagext-cli/Cargo.toml +++ b/cli/polka-storage/storagext-cli/Cargo.toml @@ -7,7 +7,8 @@ homepage.workspace = true license-file.workspace = true repository.workspace = true -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +insecure_url = ["storagext/insecure_url"] [dependencies] storagext.workspace = true @@ -21,7 +22,7 @@ hex.workspace = true primitives-proofs = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } -subxt = { workspace = true, features = ["jsonrpsee"] } +subxt = { workspace = true, features = ["jsonrpsee", "substrate-compat"] } subxt-signer = { workspace = true, features = ["subxt"] } thiserror = { workspace = true } tokio = { workspace = true, features = ["rt-multi-thread"] } @@ -29,6 +30,5 @@ tracing = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter"] } url = { workspace = true } - [lints] workspace = true diff --git a/cli/polka-storage/storagext/deals.json b/cli/polka-storage/storagext-cli/deals.json similarity index 94% rename from cli/polka-storage/storagext/deals.json rename to cli/polka-storage/storagext-cli/deals.json index 068b0bcc9..e83c930e3 100644 --- a/cli/polka-storage/storagext/deals.json +++ b/cli/polka-storage/storagext-cli/deals.json @@ -16,9 +16,9 @@ "piece_size": 4, "client": "5GvHnpY1433RytXW66r77iL4CyewAAErDU6fAouoaPKvcvLU", "provider": "5GvHnpY1433RytXW66r77iL4CyewAAErDU6fAouoaPKvcvLU", - "label": "heyyy", + "label": "heyyy 2", "start_block": 10, - "end_block": 55, + "end_block": 25, "storage_price_per_block": 1, "provider_collateral": 1, "state": "Published" diff --git a/cli/polka-storage/storagext-cli/src/cmd/market.rs b/cli/polka-storage/storagext-cli/src/cmd/market.rs index 2dc304caf..8c6be8627 100644 --- a/cli/polka-storage/storagext-cli/src/cmd/market.rs +++ b/cli/polka-storage/storagext-cli/src/cmd/market.rs @@ -2,16 +2,18 @@ use std::{path::PathBuf, str::FromStr}; use clap::Subcommand; use primitives_proofs::DealId; -use storagext::{market::MarketClient, DealProposal, PolkaStorageConfig}; +use storagext::{market::MarketClient, PolkaStorageConfig}; use url::Url; +use crate::DealProposal; + #[derive(Debug, Clone, serde::Deserialize)] -struct DealProposals(Vec); +pub struct DealProposals(Vec); impl DealProposals { fn parse(src: &str) -> Result { Ok(if src.starts_with('@') { - let path = PathBuf::from_str(&src[1..])?; + let path = PathBuf::from_str(&src[1..])?.canonicalize()?; let mut file = std::fs::File::open(path)?; serde_json::from_reader(&mut file) } else { @@ -48,7 +50,7 @@ impl MarketCommand { where Keypair: subxt::tx::Signer, { - let client = MarketClient::::new(node_rpc).await?; + let client = MarketClient::new(node_rpc).await?; match self { MarketCommand::AddBalance { amount } => { let block_hash = client.add_balance(&account_keypair, amount).await?; @@ -60,7 +62,10 @@ impl MarketCommand { } MarketCommand::PublishStorageDeals { deals } => { let block_hash = client - .publish_storage_deals(&account_keypair, deals.0) + .publish_storage_deals( + &account_keypair, + deals.0.into_iter().map(Into::into).collect(), + ) .await?; tracing::info!("[{}] Successfully published storage deals", block_hash); } diff --git a/cli/polka-storage/storagext-cli/src/main.rs b/cli/polka-storage/storagext-cli/src/main.rs index 1168be1c1..bc21c6cbf 100644 --- a/cli/polka-storage/storagext-cli/src/main.rs +++ b/cli/polka-storage/storagext-cli/src/main.rs @@ -2,10 +2,13 @@ mod cmd; +use std::fmt::Debug; + +use cid::Cid; use clap::{ArgGroup, Parser, Subcommand}; -use cli::cmd::market::MarketCommand; +use cmd::market::MarketCommand; use storagext::PolkaStorageConfig; -use subxt_signer::{ecdsa, sr25519}; +use subxt::ext::sp_core::crypto::Ss58Codec; use tracing::level_filters::LevelFilter; use tracing_subscriber::{ filter, fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer, @@ -25,11 +28,11 @@ struct Cli { pub node_rpc: Url, /// An hex encoded Sr25519 key - #[arg(long, value_parser = parse_sr25519_keypair)] - pub sr25519_key: Option, + #[arg(long, value_parser = DebugPair::::value_parser)] + pub sr25519_key: Option>, - #[arg(long, value_parser = parse_ecdsa_keypair)] - pub ecdsa_key: Option, + #[arg(long, value_parser = DebugPair::::value_parser)] + pub ecdsa_key: Option>, } #[derive(Debug, Subcommand)] @@ -86,13 +89,19 @@ async fn main() -> Result<(), anyhow::Error> { (Some(account_keypair), _) => { cli_arguments .subcommand - .run_with_keypair(cli_arguments.node_rpc, account_keypair) + .run_with_keypair( + cli_arguments.node_rpc, + subxt::tx::PairSigner::new(account_keypair.0), + ) .await? } (_, Some(account_keypair)) => { cli_arguments .subcommand - .run_with_keypair(cli_arguments.node_rpc, account_keypair) + .run_with_keypair( + cli_arguments.node_rpc, + subxt::tx::PairSigner::new(account_keypair.0), + ) .await? } _ => unreachable!("should be handled by clap::ArgGroup"), @@ -101,22 +110,31 @@ async fn main() -> Result<(), anyhow::Error> { Ok(()) } -fn parse_sr25519_keypair(mut src: &str) -> Result { - if src.starts_with("0x") { - src = &src[2..] +#[derive(Clone)] +struct DebugPair(Pair) +where + Pair: subxt::ext::sp_core::Pair; + +impl Debug for DebugPair +where + Pair: subxt::ext::sp_core::Pair, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("DebugPair") + .field(&self.0.public().to_ss58check()) + .finish() } - let mut key_bytes = [0u8; 32]; - hex::decode_to_slice(src, &mut key_bytes).unwrap(); - Ok(sr25519::Keypair::from_secret_key(key_bytes).unwrap()) } -fn parse_ecdsa_keypair(mut src: &str) -> Result { - if src.starts_with("0x") { - src = &src[2..] +impl DebugPair +where + Pair: subxt::ext::sp_core::Pair, +{ + fn value_parser(src: &str) -> Result { + Ok(Self( + Pair::from_string(&src, None).map_err(|err| format!("{}", err))?, + )) } - let mut key_bytes = [0u8; 32]; - hex::decode_to_slice(src, &mut key_bytes).unwrap(); - Ok(ecdsa::Keypair::from_secret_key(key_bytes).unwrap()) } /// Currency as specified by the SCALE-encoded runtime. @@ -125,24 +143,12 @@ type Currency = u128; /// BlockNumber as specified by the SCALE-encoded runtime. type BlockNumber = u32; -/// CID wrapper to get deserialization. +/// CID doesn't deserialize from a string, hence we need our work wrapper. +/// +/// #[derive(Debug, Clone)] pub struct CidWrapper(Cid); -impl Deref for CidWrapper { - type Target = Cid; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl Into for CidWrapper { - fn into(self) -> Cid { - self.0 - } -} - // The CID has some issues that require a workaround for strings. // For more details, see: impl<'de> serde::de::Deserialize<'de> for CidWrapper { @@ -182,12 +188,21 @@ pub enum DealState { Active(ActiveDealState), } +impl Into> for DealState { + fn into(self) -> storagext::DealState { + match self { + DealState::Published => storagext::DealState::Published, + DealState::Active(v) => storagext::DealState::Active(v.into()), + } + } +} + #[derive(Debug, Clone, serde::Deserialize)] pub struct DealProposal { pub piece_cid: CidWrapper, pub piece_size: u64, - pub client: AccountId32, - pub provider: AccountId32, + pub client: ::AccountId, + pub provider: ::AccountId, pub label: String, pub start_block: BlockNumber, pub end_block: BlockNumber, @@ -195,3 +210,20 @@ pub struct DealProposal { pub provider_collateral: Currency, pub state: DealState, } + +impl Into for DealProposal { + fn into(self) -> storagext::DealProposal { + storagext::DealProposal { + piece_cid: self.piece_cid.0, + piece_size: self.piece_size, + client: self.client, + provider: self.provider, + label: self.label, + start_block: self.start_block, + end_block: self.end_block, + storage_price_per_block: self.storage_price_per_block, + provider_collateral: self.provider_collateral, + state: self.state.into(), + } + } +} diff --git a/cli/polka-storage/storagext/README.md b/cli/polka-storage/storagext/README.md new file mode 100644 index 000000000..77ae6f769 --- /dev/null +++ b/cli/polka-storage/storagext/README.md @@ -0,0 +1,8 @@ +# storagext + +Extrinsics library for the Polka Storage Parachain. + + +## Development note: + +`subxt` and `frame_support` don't play nice with eachother! diff --git a/cli/polka-storage/storagext/src/lib.rs b/cli/polka-storage/storagext/src/lib.rs index 178b12e88..b726c4ef9 100644 --- a/cli/polka-storage/storagext/src/lib.rs +++ b/cli/polka-storage/storagext/src/lib.rs @@ -29,7 +29,7 @@ impl subxt::Config for PolkaStorageConfig { type Hash = subxt::utils::H256; type AccountId = subxt::config::polkadot::AccountId32; type Address = subxt::config::polkadot::MultiAddress; - type Signature = frame_support::sp_runtime::MultiSignature; + type Signature = subxt::ext::sp_runtime::MultiSignature; type Hasher = subxt::config::substrate::BlakeTwo256; type Header = subxt::config::substrate::SubstrateHeader; diff --git a/cli/polka-storage/storagext/src/runtime/mod.rs b/cli/polka-storage/storagext/src/runtime/mod.rs index 59beeb358..95636e23b 100644 --- a/cli/polka-storage/storagext/src/runtime/mod.rs +++ b/cli/polka-storage/storagext/src/runtime/mod.rs @@ -9,7 +9,7 @@ pub(crate) mod bounded_vec; runtime_metadata_path = "../../artifacts/metadata.scale", substitute_type( path = "sp_runtime::MultiSignature", - with = "::subxt::utils::Static<::frame_support::sp_runtime::MultiSignature>" + with = "::subxt::utils::Static<::subxt::ext::sp_runtime::MultiSignature>" ), derive_for_all_types = "Clone" )] From 1a2e250369bbb10dee486ad6bb79afb2a0ea7982 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Mon, 22 Jul 2024 10:38:18 +0000 Subject: [PATCH 09/38] fix(storagext): remove test file --- cli/polka-storage/storagext-cli/deals.json | 26 ---------------------- 1 file changed, 26 deletions(-) delete mode 100644 cli/polka-storage/storagext-cli/deals.json diff --git a/cli/polka-storage/storagext-cli/deals.json b/cli/polka-storage/storagext-cli/deals.json deleted file mode 100644 index e83c930e3..000000000 --- a/cli/polka-storage/storagext-cli/deals.json +++ /dev/null @@ -1,26 +0,0 @@ -[ - { - "piece_cid": "bafkreibme22gw2h7y2h7tg2fhqotaqjucnbc24deqo72b6mkl2egezxhvy", - "piece_size": 1, - "client": "5GvHnpY1433RytXW66r77iL4CyewAAErDU6fAouoaPKvcvLU", - "provider": "5GvHnpY1433RytXW66r77iL4CyewAAErDU6fAouoaPKvcvLU", - "label": "heyyy", - "start_block": 30, - "end_block": 55, - "storage_price_per_block": 1, - "provider_collateral": 1, - "state": "Published" - }, - { - "piece_cid": "bafkreibme22gw2h7y2h7tg2fhqotaqjucnbc24deqo72b6mkl2egezxhvy", - "piece_size": 4, - "client": "5GvHnpY1433RytXW66r77iL4CyewAAErDU6fAouoaPKvcvLU", - "provider": "5GvHnpY1433RytXW66r77iL4CyewAAErDU6fAouoaPKvcvLU", - "label": "heyyy 2", - "start_block": 10, - "end_block": 25, - "storage_price_per_block": 1, - "provider_collateral": 1, - "state": "Published" - } -] From ad57d84e81259815936e7e0d3dca957962a6c53b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Mon, 22 Jul 2024 10:38:40 +0000 Subject: [PATCH 10/38] fix(storagext-cli): add docs to arguments --- .../storagext-cli/src/cmd/market.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/cli/polka-storage/storagext-cli/src/cmd/market.rs b/cli/polka-storage/storagext-cli/src/cmd/market.rs index 8c6be8627..e1361ebd5 100644 --- a/cli/polka-storage/storagext-cli/src/cmd/market.rs +++ b/cli/polka-storage/storagext-cli/src/cmd/market.rs @@ -7,10 +7,12 @@ use url::Url; use crate::DealProposal; +/// List of [`DealProposal`]s to publish. #[derive(Debug, Clone, serde::Deserialize)] pub struct DealProposals(Vec); impl DealProposals { + /// Attempt to parse a command-line argument into [`DealProposals`]. fn parse(src: &str) -> Result { Ok(if src.starts_with('@') { let path = PathBuf::from_str(&src[1..])?.canonicalize()?; @@ -26,19 +28,29 @@ impl DealProposals { #[command(name = "market", about = "CLI Client to the Market Pallet", version)] pub enum MarketCommand { /// Add balance to an account. - AddBalance { amount: u128 }, + AddBalance { + /// Amount to add to the account. + amount: u128, + }, /// Publish storage deals. PublishStorageDeals { + /// Storage deals to publish. Either JSON or a file path, prepended with an @. #[arg(value_parser = DealProposals::parse)] deals: DealProposals, }, /// Settle deal payments. - SettleDealPayments { deal_ids: Vec }, + SettleDealPayments { + /// The IDs for the deals to settle. + deal_ids: Vec, + }, /// Withdraw balance from an account. - WithdrawBalance { amount: u128 }, + WithdrawBalance { + /// Amount to withdraw from the account. + amount: u128, + }, } impl MarketCommand { From 79e74b639e75ad40cf686d8cadcb25919a9044e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Mon, 22 Jul 2024 10:38:56 +0000 Subject: [PATCH 11/38] fix(storagext): reuse types across crates --- cli/polka-storage/storagext-cli/src/main.rs | 8 +------- cli/polka-storage/storagext/src/lib.rs | 6 +++--- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/cli/polka-storage/storagext-cli/src/main.rs b/cli/polka-storage/storagext-cli/src/main.rs index bc21c6cbf..c848a6bbb 100644 --- a/cli/polka-storage/storagext-cli/src/main.rs +++ b/cli/polka-storage/storagext-cli/src/main.rs @@ -7,7 +7,7 @@ use std::fmt::Debug; use cid::Cid; use clap::{ArgGroup, Parser, Subcommand}; use cmd::market::MarketCommand; -use storagext::PolkaStorageConfig; +use storagext::{BlockNumber, Currency, PolkaStorageConfig}; use subxt::ext::sp_core::crypto::Ss58Codec; use tracing::level_filters::LevelFilter; use tracing_subscriber::{ @@ -137,12 +137,6 @@ where } } -/// Currency as specified by the SCALE-encoded runtime. -type Currency = u128; - -/// BlockNumber as specified by the SCALE-encoded runtime. -type BlockNumber = u32; - /// CID doesn't deserialize from a string, hence we need our work wrapper. /// /// diff --git a/cli/polka-storage/storagext/src/lib.rs b/cli/polka-storage/storagext/src/lib.rs index b726c4ef9..cc6284f95 100644 --- a/cli/polka-storage/storagext/src/lib.rs +++ b/cli/polka-storage/storagext/src/lib.rs @@ -13,12 +13,12 @@ pub use crate::runtime::runtime_types::pallet_market::{ }; /// Currency as specified by the SCALE-encoded runtime. -type Currency = u128; +pub type Currency = u128; /// BlockNumber as specified by the SCALE-encoded runtime. -type BlockNumber = u32; +pub type BlockNumber = u32; -type AccountIndex = u32; +pub type AccountIndex = u32; pub enum PolkaStorageConfig {} From a45be8ca5bcbd3ec3f842a87bd117c13d93393d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Mon, 22 Jul 2024 13:47:46 +0000 Subject: [PATCH 12/38] fix(storagext): reduce MAX_N_DEALS --- cli/polka-storage/storagext/src/market.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/polka-storage/storagext/src/market.rs b/cli/polka-storage/storagext/src/market.rs index b0379c6fe..aa1cdcdf1 100644 --- a/cli/polka-storage/storagext/src/market.rs +++ b/cli/polka-storage/storagext/src/market.rs @@ -9,7 +9,7 @@ use crate::{ /// The maximum number of deal IDs supported. // NOTE(@jmg-duarte,17/07/2024): ideally, should be read from the primitives or something -const MAX_N_DEALS: usize = 128; +const MAX_N_DEALS: usize = 32; #[derive(Debug, thiserror::Error)] pub enum MarketClientError { From 4632d0b50389fddc893e7337fb4522b7f32e35c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Mon, 22 Jul 2024 13:55:18 +0000 Subject: [PATCH 13/38] fix(storagext): more keys --- cli/polka-storage/storagext-cli/src/main.rs | 32 +++++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/cli/polka-storage/storagext-cli/src/main.rs b/cli/polka-storage/storagext-cli/src/main.rs index c848a6bbb..27eaabb25 100644 --- a/cli/polka-storage/storagext-cli/src/main.rs +++ b/cli/polka-storage/storagext-cli/src/main.rs @@ -18,21 +18,28 @@ use url::Url; pub(crate) const FULL_NODE_DEFAULT_RPC_ADDR: &str = "ws://127.0.0.1:9944"; #[derive(Debug, Parser)] -#[command(group(ArgGroup::new("key").required(true).args(&["sr25519_key", "ecdsa_key"])))] +#[command(group(ArgGroup::new("keypair").required(true).args( + &["sr25519_key", "ecdsa_key", "ed25519_key"] +)))] struct Cli { #[command(subcommand)] pub subcommand: SubCommand, - /// URL of the providers RPC server. + /// RPC server's URL. #[arg(long, default_value = FULL_NODE_DEFAULT_RPC_ADDR)] pub node_rpc: Url, - /// An hex encoded Sr25519 key + /// An Sr25519 keypair. #[arg(long, value_parser = DebugPair::::value_parser)] pub sr25519_key: Option>, + /// An ECDSA keypair. #[arg(long, value_parser = DebugPair::::value_parser)] pub ecdsa_key: Option>, + + /// An Ed25519 keypair. + #[arg(long, value_parser = DebugPair::::value_parser)] + pub ed25519_key: Option>, } #[derive(Debug, Subcommand)] @@ -85,8 +92,21 @@ async fn main() -> Result<(), anyhow::Error> { let cli_arguments = Cli::parse(); - match (cli_arguments.sr25519_key, cli_arguments.ecdsa_key) { - (Some(account_keypair), _) => { + match ( + cli_arguments.sr25519_key, + cli_arguments.ecdsa_key, + cli_arguments.ed25519_key, + ) { + (Some(account_keypair), _, _) => { + cli_arguments + .subcommand + .run_with_keypair( + cli_arguments.node_rpc, + subxt::tx::PairSigner::new(account_keypair.0), + ) + .await? + } + (_, Some(account_keypair), _) => { cli_arguments .subcommand .run_with_keypair( @@ -95,7 +115,7 @@ async fn main() -> Result<(), anyhow::Error> { ) .await? } - (_, Some(account_keypair)) => { + (_, _, Some(account_keypair)) => { cli_arguments .subcommand .run_with_keypair( From f422090a4c9cc2c56ba2002f013cfac79bd289a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Mon, 22 Jul 2024 13:56:08 +0000 Subject: [PATCH 14/38] fix(storagext): reuse more types requires serde, making it optional isn't hard, but isn't pretty --- Cargo.lock | 2 + cli/polka-storage/storagext-cli/src/main.rs | 36 +--------- cli/polka-storage/storagext/Cargo.toml | 6 +- cli/polka-storage/storagext/src/lib.rs | 52 +++++++-------- cli/polka-storage/storagext/src/market.rs | 2 +- .../storagext/src/runtime/mod.rs | 65 ++++++++++++++++++- 6 files changed, 95 insertions(+), 68 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a35b438b9..d378687fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14577,6 +14577,8 @@ dependencies = [ "hex", "parity-scale-codec", "primitives-proofs", + "serde", + "serde_json", "subxt", "subxt-signer", "thiserror", diff --git a/cli/polka-storage/storagext-cli/src/main.rs b/cli/polka-storage/storagext-cli/src/main.rs index 27eaabb25..f20ea2e6c 100644 --- a/cli/polka-storage/storagext-cli/src/main.rs +++ b/cli/polka-storage/storagext-cli/src/main.rs @@ -177,40 +177,6 @@ impl<'de> serde::de::Deserialize<'de> for CidWrapper { } } -#[derive(Debug, Clone, serde::Deserialize)] -pub struct ActiveDealState { - pub sector_number: u64, - pub sector_start_block: BlockNumber, - pub last_updated_block: Option, - pub slash_block: Option, -} - -impl Into> for ActiveDealState { - fn into(self) -> storagext::ActiveDealState { - storagext::ActiveDealState { - sector_number: self.sector_number, - sector_start_block: self.sector_start_block, - last_updated_block: self.last_updated_block, - slash_block: self.slash_block, - } - } -} - -#[derive(Debug, Clone, serde::Deserialize)] -pub enum DealState { - Published, - Active(ActiveDealState), -} - -impl Into> for DealState { - fn into(self) -> storagext::DealState { - match self { - DealState::Published => storagext::DealState::Published, - DealState::Active(v) => storagext::DealState::Active(v.into()), - } - } -} - #[derive(Debug, Clone, serde::Deserialize)] pub struct DealProposal { pub piece_cid: CidWrapper, @@ -222,7 +188,7 @@ pub struct DealProposal { pub end_block: BlockNumber, pub storage_price_per_block: Currency, pub provider_collateral: Currency, - pub state: DealState, + pub state: storagext::runtime::runtime_types::pallet_market::pallet::DealState, } impl Into for DealProposal { diff --git a/cli/polka-storage/storagext/Cargo.toml b/cli/polka-storage/storagext/Cargo.toml index 685b5800b..0f5d433d4 100644 --- a/cli/polka-storage/storagext/Cargo.toml +++ b/cli/polka-storage/storagext/Cargo.toml @@ -19,13 +19,17 @@ codec.workspace = true frame-support = { workspace = true, features = ["std"] } hex.workspace = true primitives-proofs = { workspace = true } -subxt = { workspace = true, features = ["jsonrpsee"] } +subxt = { workspace = true, features = ["jsonrpsee", "substrate-compat"] } subxt-signer = { workspace = true, features = ["subxt"] } thiserror = { workspace = true } tokio = { workspace = true, features = ["rt-multi-thread"] } tracing = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter"] } url = { workspace = true } +serde = { workspace = true, features = ["derive"] } + +[dev-dependencies] +serde_json = { workspace = true } [lints] workspace = true diff --git a/cli/polka-storage/storagext/src/lib.rs b/cli/polka-storage/storagext/src/lib.rs index cc6284f95..f9638311a 100644 --- a/cli/polka-storage/storagext/src/lib.rs +++ b/cli/polka-storage/storagext/src/lib.rs @@ -1,7 +1,12 @@ use cid::Cid; use codec::Encode; -use frame_support::CloneNoBound; -use subxt::{self, tx::Signer, utils::Static}; +use frame_support::{sp_runtime::AccountId32, CloneNoBound}; +use subxt::{ + self, + ext::sp_runtime::{MultiAddress, MultiSignature}, + tx::Signer, + utils::Static, +}; pub mod market; pub mod runtime; @@ -49,7 +54,7 @@ pub struct DealProposal { pub end_block: BlockNumber, pub storage_price_per_block: Currency, pub provider_collateral: Currency, - pub state: DealState, + pub state: market_pallet_types::DealState, } impl From @@ -76,7 +81,15 @@ impl From } impl DealProposal { - fn sign(self, keypair: &Keypair) -> ClientDealProposal + fn sign( + self, + keypair: &Keypair, + ) -> market_pallet_types::ClientDealProposal< + ::AccountId, + Currency, + BlockNumber, + Static, + > where Keypair: Signer, Self: Into< @@ -87,33 +100,12 @@ impl DealProposal { >, >, { - let market_deal_proposal: market_pallet_types::DealProposal<_, _, _> = self.clone().into(); - let encoded_deal_proposal = market_deal_proposal.encode(); - - ClientDealProposal { - proposal: self, - client: keypair.sign(&encoded_deal_proposal), - } - } -} + let proposal: market_pallet_types::DealProposal<_, _, _> = self.into(); + let client_signature = Static(keypair.sign(&proposal.encode())); -pub struct ClientDealProposal { - pub proposal: DealProposal, - pub client: ::Signature, -} - -impl From - for market_pallet_types::ClientDealProposal< - ::AccountId, - Currency, - BlockNumber, - Static<::Signature>, - > -{ - fn from(value: ClientDealProposal) -> Self { - Self { - proposal: market_pallet_types::DealProposal::from(value.proposal), - client_signature: Static(value.client), + market_pallet_types::ClientDealProposal { + proposal, + client_signature, } } } diff --git a/cli/polka-storage/storagext/src/market.rs b/cli/polka-storage/storagext/src/market.rs index aa1cdcdf1..3c5958e1f 100644 --- a/cli/polka-storage/storagext/src/market.rs +++ b/cli/polka-storage/storagext/src/market.rs @@ -111,7 +111,7 @@ impl MarketClient { let signed_deal_proposals = deals .into_iter() - .map(|deal| deal.sign(account_keypair).into()) + .map(|deal| deal.sign(account_keypair)) .collect(); // `deals` has been truncated to fit the proper bound, however, diff --git a/cli/polka-storage/storagext/src/runtime/mod.rs b/cli/polka-storage/storagext/src/runtime/mod.rs index 95636e23b..2354c460c 100644 --- a/cli/polka-storage/storagext/src/runtime/mod.rs +++ b/cli/polka-storage/storagext/src/runtime/mod.rs @@ -11,9 +11,72 @@ pub(crate) mod bounded_vec; path = "sp_runtime::MultiSignature", with = "::subxt::utils::Static<::subxt::ext::sp_runtime::MultiSignature>" ), - derive_for_all_types = "Clone" + derive_for_all_types = "Clone, PartialEq, Eq", + derive_for_type( + path = "pallet_market::pallet::ActiveDealState", + derive = "::serde::Deserialize" + ), + derive_for_type( + path = "pallet_market::pallet::DealState", + derive = "::serde::Deserialize" + ) )] mod polka_storage_runtime {} // Using self keeps the import separate from the others pub use self::polka_storage_runtime::*; + +#[cfg(test)] +mod test { + use crate::{ActiveDealState, DealState}; + + #[test] + fn ensure_serde_for_active_deal_state() { + let active_deal_state = serde_json::from_str::>( + r#"{ + "sector_number": 1, + "sector_start_block": 10, + "last_updated_block": 20, + "slash_block": null + }"#, + ) + .unwrap(); + + assert_eq!(active_deal_state.sector_number, 1); + assert_eq!(active_deal_state.sector_start_block, 10); + assert_eq!(active_deal_state.last_updated_block, Some(20)); + assert_eq!(active_deal_state.slash_block, None); + } + + #[test] + fn ensure_serde_for_deal_state_published() { + let deal_state = serde_json::from_str::>(r#""Published""#).unwrap(); + + assert_eq!(deal_state, DealState::Published); + } + + #[test] + fn ensure_serde_for_deal_state_active() { + let deal_state = serde_json::from_str::>( + r#"{ + "Active": { + "sector_number": 1, + "sector_start_block": 10, + "last_updated_block": 20, + "slash_block": null + } + }"#, + ) + .unwrap(); + + assert_eq!( + deal_state, + DealState::Active(ActiveDealState { + sector_number: 1, + sector_start_block: 10, + last_updated_block: Some(20), + slash_block: None + }) + ); + } +} From 36cb09845fb57e5dfc19bc4d2350317488535d84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Mon, 22 Jul 2024 14:21:08 +0000 Subject: [PATCH 15/38] fix(storagext): better docs for keys --- cli/polka-storage/storagext-cli/src/main.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cli/polka-storage/storagext-cli/src/main.rs b/cli/polka-storage/storagext-cli/src/main.rs index f20ea2e6c..25515cac3 100644 --- a/cli/polka-storage/storagext-cli/src/main.rs +++ b/cli/polka-storage/storagext-cli/src/main.rs @@ -29,15 +29,15 @@ struct Cli { #[arg(long, default_value = FULL_NODE_DEFAULT_RPC_ADDR)] pub node_rpc: Url, - /// An Sr25519 keypair. + /// Sr25519 keypair, encoded as hex or BIP-39. See `sp_core::crypto::Pair::from_string_with_seed` for more information. #[arg(long, value_parser = DebugPair::::value_parser)] pub sr25519_key: Option>, - /// An ECDSA keypair. + /// ECDSA keypair, encoded as hex or BIP-39. See `sp_core::crypto::Pair::from_string_with_seed` for more information. #[arg(long, value_parser = DebugPair::::value_parser)] pub ecdsa_key: Option>, - /// An Ed25519 keypair. + /// Ed25519 keypair, encoded as hex or BIP-39. See `sp_core::crypto::Pair::from_string_with_seed` for more information. #[arg(long, value_parser = DebugPair::::value_parser)] pub ed25519_key: Option>, } From a8d4a9ad91d7855069dbd375bdf3bf67baaed593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Mon, 22 Jul 2024 14:22:55 +0000 Subject: [PATCH 16/38] fix(zombienet): fix zombienet ws port --- PARACHAIN.md | 4 ++++ zombienet/local-kube-testnet.toml | 6 +++++- zombienet/local-testnet.toml | 6 +++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/PARACHAIN.md b/PARACHAIN.md index 1b1c38e09..003b69d07 100644 --- a/PARACHAIN.md +++ b/PARACHAIN.md @@ -72,5 +72,9 @@ you won't have access to the parachain extrinsics when calling them. Charlie however, is running a parachain node, and as such, he will be your contact point to the parachain. +> [!INFO] +> Charlie will always open port 42069 as per the [Zombienet configuration](zombienet/local-kube-testnet.toml). + +> [!INFO] > Check you Kubernetes cluster status by using `kubectl get pods --all-namespaces`. > It should show all pods from all namespaces along with their status. diff --git a/zombienet/local-kube-testnet.toml b/zombienet/local-kube-testnet.toml index 3c02e8576..5a0fb139e 100644 --- a/zombienet/local-kube-testnet.toml +++ b/zombienet/local-kube-testnet.toml @@ -3,7 +3,10 @@ image_pull_policy = "IfNotPresent" [relaychain] chain = "rococo-local" -default_args = ["--detailed-log-output", "-lparachain=debug,xcm=trace,runtime=trace"] +default_args = [ + "--detailed-log-output", + "-lparachain=debug,xcm=trace,runtime=trace", +] default_image = "docker.io/parity/polkadot:latest" [[relaychain.nodes]] @@ -29,3 +32,4 @@ command = "polka-storage-node" image = "polkadotstorage.azurecr.io/parachain-node:0.1.0" name = "charlie" validator = true +ws_port = 42069 diff --git a/zombienet/local-testnet.toml b/zombienet/local-testnet.toml index 35151f15f..60e0a62c4 100644 --- a/zombienet/local-testnet.toml +++ b/zombienet/local-testnet.toml @@ -1,6 +1,9 @@ [relaychain] chain = "rococo-local" -default_args = ["--detailed-log-output", "-lparachain=debug,xcm=trace,runtime=trace"] +default_args = [ + "--detailed-log-output", + "-lparachain=debug,xcm=trace,runtime=trace", +] default_command = "polkadot" [[relaychain.nodes]] @@ -25,3 +28,4 @@ args = ["--detailed-log-output", "-lparachain=debug,xcm=trace,runtime=trace"] command = "target/release/polka-storage-node" name = "charlie" validator = true +ws_port = 42069 From 1134132dbbf02ba5d4066f0598b46b964f05b02d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Mon, 22 Jul 2024 14:23:07 +0000 Subject: [PATCH 17/38] fix(storagext): better docs for market --- cli/polka-storage/storagext-cli/src/cmd/market.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cli/polka-storage/storagext-cli/src/cmd/market.rs b/cli/polka-storage/storagext-cli/src/cmd/market.rs index e1361ebd5..55cd9fa04 100644 --- a/cli/polka-storage/storagext-cli/src/cmd/market.rs +++ b/cli/polka-storage/storagext-cli/src/cmd/market.rs @@ -13,6 +13,8 @@ pub struct DealProposals(Vec); impl DealProposals { /// Attempt to parse a command-line argument into [`DealProposals`]. + /// + /// The command-line argument may be a valid JSON object, or a file path starting with @. fn parse(src: &str) -> Result { Ok(if src.starts_with('@') { let path = PathBuf::from_str(&src[1..])?.canonicalize()?; @@ -54,6 +56,9 @@ pub enum MarketCommand { } impl MarketCommand { + /// Run a `market` command. + /// + /// Requires the target RPC address and a keypair able to sign transactions. pub async fn run( self, node_rpc: Url, From ce725c07963d4084107f1cc30c4273fa0eaf0d09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Mon, 22 Jul 2024 14:27:08 +0000 Subject: [PATCH 18/38] fix(storagext): remove hack --- node/src/chain_spec.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/node/src/chain_spec.rs b/node/src/chain_spec.rs index 2cb7d328a..67786beff 100644 --- a/node/src/chain_spec.rs +++ b/node/src/chain_spec.rs @@ -158,8 +158,6 @@ pub fn local_testnet_config() -> ChainSpec { get_account_id_from_seed::("Dave//stash"), get_account_id_from_seed::("Eve//stash"), get_account_id_from_seed::("Ferdie//stash"), - AccountId32::from_ss58check("5GvHnpY1433RytXW66r77iL4CyewAAErDU6fAouoaPKvcvLU") - .unwrap(), ], get_account_id_from_seed::("Alice"), 1000.into(), From 58d00ec45b25288a16c91d54981172d08e46faa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Mon, 22 Jul 2024 14:37:04 +0000 Subject: [PATCH 19/38] fix(storagext): remove custom error and replace tracing fields --- cli/polka-storage/storagext/src/market.rs | 39 +++++++++++++---------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/cli/polka-storage/storagext/src/market.rs b/cli/polka-storage/storagext/src/market.rs index 3c5958e1f..c2ced1789 100644 --- a/cli/polka-storage/storagext/src/market.rs +++ b/cli/polka-storage/storagext/src/market.rs @@ -11,12 +11,6 @@ use crate::{ // NOTE(@jmg-duarte,17/07/2024): ideally, should be read from the primitives or something const MAX_N_DEALS: usize = 32; -#[derive(Debug, thiserror::Error)] -pub enum MarketClientError { - #[error(transparent)] - SubxtError(#[from] subxt::Error), -} - /// Client to interact with the market pallet extrinsics. pub struct MarketClient { client: OnlineClient, @@ -27,7 +21,7 @@ impl MarketClient { /// /// By default, this function does not support insecure URLs, /// to enable support for them, use the `insecure_url` feature. - pub async fn new(rpc_address: impl AsRef) -> Result { + pub async fn new(rpc_address: impl AsRef) -> Result { let client = if cfg!(feature = "insecure_url") { OnlineClient::<_>::from_insecure_url(rpc_address).await? } else { @@ -38,12 +32,15 @@ impl MarketClient { } /// Withdraw the given `amount` of balance. - #[tracing::instrument(skip(self, account_keypair))] + #[tracing::instrument(skip_all, fields( + address = keypair.address(), + amount = amount + ))] pub async fn withdraw_balance( &self, account_keypair: &Keypair, amount: u128, - ) -> Result<::Hash, MarketClientError> + ) -> Result<::Hash, subxt::Error> where Keypair: subxt::tx::Signer, { @@ -52,12 +49,15 @@ impl MarketClient { } /// Add the given `amount` of balance. - #[tracing::instrument(skip(self, account_keypair))] + #[tracing::instrument(skip_all, fields( + address = keypair.address(), + amount = amount + ))] pub async fn add_balance( &self, account_keypair: &Keypair, amount: u128, - ) -> Result<::Hash, MarketClientError> + ) -> Result<::Hash, subxt::Error> where Keypair: subxt::tx::Signer, { @@ -68,12 +68,15 @@ impl MarketClient { /// Settle deal payments for the provided [`DealId`]s. /// /// If `deal_ids` length is bigger than [`MAX_DEAL_IDS`], it will get truncated. - #[tracing::instrument(skip(self, account_keypair))] + #[tracing::instrument(skip_all, fields( + address = keypair.address(), + deal_ids = deal_ids + ))] pub async fn settle_deal_payments( &self, account_keypair: &Keypair, mut deal_ids: Vec, - ) -> Result<::Hash, MarketClientError> + ) -> Result<::Hash, subxt::Error> where Keypair: subxt::tx::Signer, { @@ -94,13 +97,17 @@ impl MarketClient { Ok(self.traced_submission(&payload, account_keypair).await?) } - // TODO remove skip_all - #[tracing::instrument(skip_all)] + /// Publish the given storage deals. + /// + /// If `deals` length is bigger than [`MAX_DEAL_IDS`], it will get truncated. + #[tracing::instrument(skip_all, fields( + address = keypair.address() + ))] pub async fn publish_storage_deals( &self, account_keypair: &Keypair, mut deals: Vec, - ) -> Result<::Hash, MarketClientError> + ) -> Result<::Hash, subxt::Error> where Keypair: subxt::tx::Signer, { From 431b09c605d445681705856ba614d01cbd3f1e77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Mon, 22 Jul 2024 14:37:18 +0000 Subject: [PATCH 20/38] fix(storagext): more docs --- cli/polka-storage/storagext/src/lib.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cli/polka-storage/storagext/src/lib.rs b/cli/polka-storage/storagext/src/lib.rs index f9638311a..4f311fe27 100644 --- a/cli/polka-storage/storagext/src/lib.rs +++ b/cli/polka-storage/storagext/src/lib.rs @@ -23,8 +23,7 @@ pub type Currency = u128; /// BlockNumber as specified by the SCALE-encoded runtime. pub type BlockNumber = u32; -pub type AccountIndex = u32; - +/// Parachain configuration for subxt. pub enum PolkaStorageConfig {} // Types are fully qualified ON PURPOSE! @@ -33,7 +32,7 @@ pub enum PolkaStorageConfig {} impl subxt::Config for PolkaStorageConfig { type Hash = subxt::utils::H256; type AccountId = subxt::config::polkadot::AccountId32; - type Address = subxt::config::polkadot::MultiAddress; + type Address = subxt::config::polkadot::MultiAddress; type Signature = subxt::ext::sp_runtime::MultiSignature; type Hasher = subxt::config::substrate::BlakeTwo256; type Header = From fa9f8f9b606bf64f072429c574c6d9c6e0e5d9f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Mon, 22 Jul 2024 16:01:41 +0000 Subject: [PATCH 21/38] style: taplo format --- Cargo.toml | 8 +++----- cli/polka-storage/storagext-cli/Cargo.toml | 4 ++-- cli/polka-storage/storagext/Cargo.toml | 2 +- runtime/Cargo.toml | 4 +--- zombienet/local-kube-testnet.toml | 5 +---- zombienet/local-testnet.toml | 5 +---- 6 files changed, 9 insertions(+), 19 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e2f4c2d88..fb8f2c6ae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,6 +35,7 @@ panic = 'abort' # Use abort on panic to reduce binary size substrate-build-script-utils = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.13.0" } substrate-wasm-builder = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.13.0" } +anyhow = "1.0.86" async-channel = "2.3.1" async-stream = "0.3.5" async-trait = "0.1.80" @@ -54,6 +55,7 @@ criterion = "0.5.1" digest = "0.10.7" env_logger = "0.11.2" futures = "0.3.28" +hex = "0.4.3" hex-literal = { version = "0.4.1" } indexmap = "2.2.6" integer-encoding = "4.0.0" @@ -93,8 +95,6 @@ tracing = "0.1.40" tracing-subscriber = "0.3.18" url = "2.5.0" uuid = "1.8.0" -hex = "0.4.3" -anyhow = "1.0.86" # Local @@ -146,9 +146,7 @@ substrate-prometheus-endpoint = { git = "https://github.com/paritytech/polkadot- # Polkadot pallet-xcm = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.13.0", default-features = false } -polkadot-cli = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.13.0", features = [ - "rococo-native", -] } +polkadot-cli = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.13.0", features = ["rococo-native"] } polkadot-parachain-primitives = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.13.0", default-features = false } polkadot-primitives = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.13.0" } polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot-sdk", tag = "polkadot-v1.13.0", default-features = false } diff --git a/cli/polka-storage/storagext-cli/Cargo.toml b/cli/polka-storage/storagext-cli/Cargo.toml index 2642d8eb8..1a83c41a1 100644 --- a/cli/polka-storage/storagext-cli/Cargo.toml +++ b/cli/polka-storage/storagext-cli/Cargo.toml @@ -1,11 +1,11 @@ [package] -name = "storagext-cli" -version = "0.1.0" authors.workspace = true edition.workspace = true homepage.workspace = true license-file.workspace = true +name = "storagext-cli" repository.workspace = true +version = "0.1.0" [features] insecure_url = ["storagext/insecure_url"] diff --git a/cli/polka-storage/storagext/Cargo.toml b/cli/polka-storage/storagext/Cargo.toml index 0f5d433d4..b4e65a1a4 100644 --- a/cli/polka-storage/storagext/Cargo.toml +++ b/cli/polka-storage/storagext/Cargo.toml @@ -19,6 +19,7 @@ codec.workspace = true frame-support = { workspace = true, features = ["std"] } hex.workspace = true primitives-proofs = { workspace = true } +serde = { workspace = true, features = ["derive"] } subxt = { workspace = true, features = ["jsonrpsee", "substrate-compat"] } subxt-signer = { workspace = true, features = ["subxt"] } thiserror = { workspace = true } @@ -26,7 +27,6 @@ tokio = { workspace = true, features = ["rt-multi-thread"] } tracing = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter"] } url = { workspace = true } -serde = { workspace = true, features = ["derive"] } [dev-dependencies] serde_json = { workspace = true } diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 3b21e46eb..12ded1cf1 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -25,9 +25,7 @@ pallet-storage-provider = { workspace = true, default-features = false } codec = { workspace = true, default-features = false, features = ["derive"] } hex-literal = { workspace = true, optional = true } log = { workspace = true } -scale-info = { workspace = true, default-features = false, features = [ - "derive", -] } +scale-info = { workspace = true, default-features = false, features = ["derive"] } smallvec = { workspace = true } # Substrate / FRAME diff --git a/zombienet/local-kube-testnet.toml b/zombienet/local-kube-testnet.toml index 5a0fb139e..c838059de 100644 --- a/zombienet/local-kube-testnet.toml +++ b/zombienet/local-kube-testnet.toml @@ -3,10 +3,7 @@ image_pull_policy = "IfNotPresent" [relaychain] chain = "rococo-local" -default_args = [ - "--detailed-log-output", - "-lparachain=debug,xcm=trace,runtime=trace", -] +default_args = ["--detailed-log-output", "-lparachain=debug,xcm=trace,runtime=trace"] default_image = "docker.io/parity/polkadot:latest" [[relaychain.nodes]] diff --git a/zombienet/local-testnet.toml b/zombienet/local-testnet.toml index 60e0a62c4..2c2ea2531 100644 --- a/zombienet/local-testnet.toml +++ b/zombienet/local-testnet.toml @@ -1,9 +1,6 @@ [relaychain] chain = "rococo-local" -default_args = [ - "--detailed-log-output", - "-lparachain=debug,xcm=trace,runtime=trace", -] +default_args = ["--detailed-log-output", "-lparachain=debug,xcm=trace,runtime=trace"] default_command = "polkadot" [[relaychain.nodes]] From 784f6453b7fc74aadd32edca03bcbea1f5abe4ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Tue, 23 Jul 2024 08:40:57 +0000 Subject: [PATCH 22/38] fix(storagext): clippy fixes --- .../storagext-cli/src/cmd/market.rs | 4 ++-- cli/polka-storage/storagext/src/lib.rs | 9 ++------- cli/polka-storage/storagext/src/market.rs | 18 +++++++++--------- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/cli/polka-storage/storagext-cli/src/cmd/market.rs b/cli/polka-storage/storagext-cli/src/cmd/market.rs index 55cd9fa04..e386b31be 100644 --- a/cli/polka-storage/storagext-cli/src/cmd/market.rs +++ b/cli/polka-storage/storagext-cli/src/cmd/market.rs @@ -16,8 +16,8 @@ impl DealProposals { /// /// The command-line argument may be a valid JSON object, or a file path starting with @. fn parse(src: &str) -> Result { - Ok(if src.starts_with('@') { - let path = PathBuf::from_str(&src[1..])?.canonicalize()?; + Ok(if let Some(stripped) = src.strip_prefix('@') { + let path = PathBuf::from_str(stripped)?.canonicalize()?; let mut file = std::fs::File::open(path)?; serde_json::from_reader(&mut file) } else { diff --git a/cli/polka-storage/storagext/src/lib.rs b/cli/polka-storage/storagext/src/lib.rs index 4f311fe27..043f6f337 100644 --- a/cli/polka-storage/storagext/src/lib.rs +++ b/cli/polka-storage/storagext/src/lib.rs @@ -1,12 +1,7 @@ use cid::Cid; use codec::Encode; -use frame_support::{sp_runtime::AccountId32, CloneNoBound}; -use subxt::{ - self, - ext::sp_runtime::{MultiAddress, MultiSignature}, - tx::Signer, - utils::Static, -}; +use frame_support::CloneNoBound; +use subxt::{self, ext::sp_runtime::MultiSignature, tx::Signer, utils::Static}; pub mod market; pub mod runtime; diff --git a/cli/polka-storage/storagext/src/market.rs b/cli/polka-storage/storagext/src/market.rs index c2ced1789..73af7d1f6 100644 --- a/cli/polka-storage/storagext/src/market.rs +++ b/cli/polka-storage/storagext/src/market.rs @@ -33,7 +33,7 @@ impl MarketClient { /// Withdraw the given `amount` of balance. #[tracing::instrument(skip_all, fields( - address = keypair.address(), + address = ?account_keypair.address(), amount = amount ))] pub async fn withdraw_balance( @@ -45,12 +45,12 @@ impl MarketClient { Keypair: subxt::tx::Signer, { let payload = runtime::tx().market().withdraw_balance(amount); - Ok(self.traced_submission(&payload, account_keypair).await?) + self.traced_submission(&payload, account_keypair).await } /// Add the given `amount` of balance. #[tracing::instrument(skip_all, fields( - address = keypair.address(), + address = ?account_keypair.address(), amount = amount ))] pub async fn add_balance( @@ -62,15 +62,15 @@ impl MarketClient { Keypair: subxt::tx::Signer, { let payload = runtime::tx().market().add_balance(amount); - Ok(self.traced_submission(&payload, account_keypair).await?) + self.traced_submission(&payload, account_keypair).await } /// Settle deal payments for the provided [`DealId`]s. /// /// If `deal_ids` length is bigger than [`MAX_DEAL_IDS`], it will get truncated. #[tracing::instrument(skip_all, fields( - address = keypair.address(), - deal_ids = deal_ids + address = ?account_keypair.address(), + deal_ids = ?deal_ids ))] pub async fn settle_deal_payments( &self, @@ -94,14 +94,14 @@ impl MarketClient { .market() .settle_deal_payments(bounded_unbounded_deal_ids); - Ok(self.traced_submission(&payload, account_keypair).await?) + self.traced_submission(&payload, account_keypair).await } /// Publish the given storage deals. /// /// If `deals` length is bigger than [`MAX_DEAL_IDS`], it will get truncated. #[tracing::instrument(skip_all, fields( - address = keypair.address() + address = ?account_keypair.address() ))] pub async fn publish_storage_deals( &self, @@ -133,7 +133,7 @@ impl MarketClient { .market() .publish_storage_deals(bounded_unbounded_deals); - Ok(self.traced_submission(&payload, account_keypair).await?) + self.traced_submission(&payload, account_keypair).await } /// Submit an extrinsic and wait for finalization, returning the block hash it was included in. From 703d63c4f0f221841c72b812804f57b3dfe95c60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Tue, 23 Jul 2024 09:14:44 +0000 Subject: [PATCH 23/38] fix: clippy --- node/src/chain_spec.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/node/src/chain_spec.rs b/node/src/chain_spec.rs index 67786beff..73f23feea 100644 --- a/node/src/chain_spec.rs +++ b/node/src/chain_spec.rs @@ -4,11 +4,8 @@ use runtime::{AccountId, AuraId, Signature, EXISTENTIAL_DEPOSIT}; use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup}; use sc_service::ChainType; use serde::{Deserialize, Serialize}; -use sp_core::{crypto::Ss58Codec, sr25519, Pair, Public}; -use sp_runtime::{ - traits::{IdentifyAccount, Verify}, - AccountId32, -}; +use sp_core::{sr25519, Pair, Public}; +use sp_runtime::traits::{IdentifyAccount, Verify}; /// Specialized `ChainSpec` for the normal parachain runtime. pub type ChainSpec = sc_service::GenericChainSpec; From 7da9a9d2074b1c4359b2d7a4e846e821580243ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Tue, 23 Jul 2024 10:56:14 +0000 Subject: [PATCH 24/38] fix(storagext): address comments --- .../storagext-cli/src/cmd/market.rs | 13 ++++- cli/polka-storage/storagext-cli/src/main.rs | 15 +++-- cli/polka-storage/storagext/src/lib.rs | 18 ++++-- cli/polka-storage/storagext/src/market.rs | 58 ++++++++++++------- 4 files changed, 70 insertions(+), 34 deletions(-) diff --git a/cli/polka-storage/storagext-cli/src/cmd/market.rs b/cli/polka-storage/storagext-cli/src/cmd/market.rs index e386b31be..159387204 100644 --- a/cli/polka-storage/storagext-cli/src/cmd/market.rs +++ b/cli/polka-storage/storagext-cli/src/cmd/market.rs @@ -3,6 +3,7 @@ use std::{path::PathBuf, str::FromStr}; use clap::Subcommand; use primitives_proofs::DealId; use storagext::{market::MarketClient, PolkaStorageConfig}; +use subxt::ext::sp_core::crypto::Ss58Codec; use url::Url; use crate::DealProposal; @@ -32,7 +33,7 @@ pub enum MarketCommand { /// Add balance to an account. AddBalance { /// Amount to add to the account. - amount: u128, + amount: storagext::Currency, }, /// Publish storage deals. @@ -51,7 +52,7 @@ pub enum MarketCommand { /// Withdraw balance from an account. WithdrawBalance { /// Amount to withdraw from the account. - amount: u128, + amount: storagext::Currency, }, } @@ -59,6 +60,14 @@ impl MarketCommand { /// Run a `market` command. /// /// Requires the target RPC address and a keypair able to sign transactions. + #[tracing::instrument( + level = "info", + skip_all, + fields( + node_rpc, + address = account_keypair.account_id().to_ss58check() + ) + )] pub async fn run( self, node_rpc: Url, diff --git a/cli/polka-storage/storagext-cli/src/main.rs b/cli/polka-storage/storagext-cli/src/main.rs index 25515cac3..958260816 100644 --- a/cli/polka-storage/storagext-cli/src/main.rs +++ b/cli/polka-storage/storagext-cli/src/main.rs @@ -15,7 +15,7 @@ use tracing_subscriber::{ }; use url::Url; -pub(crate) const FULL_NODE_DEFAULT_RPC_ADDR: &str = "ws://127.0.0.1:9944"; +pub(crate) const FULL_NODE_DEFAULT_RPC_ADDR: &str = "ws://127.0.0.1:42069"; #[derive(Debug, Parser)] #[command(group(ArgGroup::new("keypair").required(true).args( @@ -29,15 +29,21 @@ struct Cli { #[arg(long, default_value = FULL_NODE_DEFAULT_RPC_ADDR)] pub node_rpc: Url, - /// Sr25519 keypair, encoded as hex or BIP-39. See `sp_core::crypto::Pair::from_string_with_seed` for more information. + /// Sr25519 keypair, encoded as hex, BIP-39 or a dev phrase like `//Alice`. + /// + /// See `sp_core::crypto::Pair::from_string_with_seed` for more information. #[arg(long, value_parser = DebugPair::::value_parser)] pub sr25519_key: Option>, - /// ECDSA keypair, encoded as hex or BIP-39. See `sp_core::crypto::Pair::from_string_with_seed` for more information. + /// ECDSA keypair, encoded as hex, BIP-39 or a dev phrase like `//Alice`. + /// + /// See `sp_core::crypto::Pair::from_string_with_seed` for more information. #[arg(long, value_parser = DebugPair::::value_parser)] pub ecdsa_key: Option>, - /// Ed25519 keypair, encoded as hex or BIP-39. See `sp_core::crypto::Pair::from_string_with_seed` for more information. + /// Ed25519 keypair, encoded as hex, BIP-39 or a dev phrase like `//Alice`. + /// + /// See `sp_core::crypto::Pair::from_string_with_seed` for more information. #[arg(long, value_parser = DebugPair::::value_parser)] pub ed25519_key: Option>, } @@ -70,7 +76,6 @@ impl SubCommand { #[tokio::main] async fn main() -> Result<(), anyhow::Error> { - // TODO: replace the box/dyn // Logger initialization. tracing_subscriber::registry() .with( diff --git a/cli/polka-storage/storagext/src/lib.rs b/cli/polka-storage/storagext/src/lib.rs index 043f6f337..348f19bdb 100644 --- a/cli/polka-storage/storagext/src/lib.rs +++ b/cli/polka-storage/storagext/src/lib.rs @@ -26,7 +26,7 @@ pub enum PolkaStorageConfig {} // going up and down, in and out the files, this helps! impl subxt::Config for PolkaStorageConfig { type Hash = subxt::utils::H256; - type AccountId = subxt::config::polkadot::AccountId32; + type AccountId = subxt::ext::sp_core::crypto::AccountId32; type Address = subxt::config::polkadot::MultiAddress; type Signature = subxt::ext::sp_runtime::MultiSignature; type Hasher = subxt::config::substrate::BlakeTwo256; @@ -51,9 +51,15 @@ pub struct DealProposal { pub state: market_pallet_types::DealState, } +// The following conversions have specific account ID types because of the subxt generation, +// the type required there is `subxt::ext::subxt_core::utils::AccountId32`, however, this type +// is not very useful on its own, it doesn't allow us to print an account ID as anything else +// other than an array of bytes, hence, we use a more generic type for the config +// `subxt::ext::sp_core::crypto::AccountId32` and convert back to the one generated by subxt. + impl From for market_pallet_types::DealProposal< - ::AccountId, + subxt::ext::subxt_core::utils::AccountId32, Currency, BlockNumber, > @@ -62,8 +68,8 @@ impl From Self { piece_cid: value.piece_cid.into_bounded_byte_vec(), piece_size: value.piece_size, - client: value.client, - provider: value.provider, + client: value.client.into(), + provider: value.provider.into(), label: value.label.into_bounded_byte_vec(), start_block: value.start_block, end_block: value.end_block, @@ -79,7 +85,7 @@ impl DealProposal { self, keypair: &Keypair, ) -> market_pallet_types::ClientDealProposal< - ::AccountId, + subxt::ext::subxt_core::utils::AccountId32, Currency, BlockNumber, Static, @@ -88,7 +94,7 @@ impl DealProposal { Keypair: Signer, Self: Into< market_pallet_types::DealProposal< - ::AccountId, + subxt::ext::subxt_core::utils::AccountId32, Currency, BlockNumber, >, diff --git a/cli/polka-storage/storagext/src/market.rs b/cli/polka-storage/storagext/src/market.rs index 73af7d1f6..a1f346280 100644 --- a/cli/polka-storage/storagext/src/market.rs +++ b/cli/polka-storage/storagext/src/market.rs @@ -1,10 +1,10 @@ use hex::ToHex; use primitives_proofs::DealId; -use subxt::OnlineClient; +use subxt::{ext::sp_core::crypto::Ss58Codec, OnlineClient}; use crate::{ runtime::{self}, - DealProposal, PolkaStorageConfig, + Currency, DealProposal, PolkaStorageConfig, }; /// The maximum number of deal IDs supported. @@ -32,14 +32,18 @@ impl MarketClient { } /// Withdraw the given `amount` of balance. - #[tracing::instrument(skip_all, fields( - address = ?account_keypair.address(), - amount = amount - ))] + #[tracing::instrument( + level = "trace", + skip_all, + fields( + address = account_keypair.account_id().to_ss58check(), + amount = amount + ) + )] pub async fn withdraw_balance( &self, account_keypair: &Keypair, - amount: u128, + amount: Currency, ) -> Result<::Hash, subxt::Error> where Keypair: subxt::tx::Signer, @@ -49,14 +53,18 @@ impl MarketClient { } /// Add the given `amount` of balance. - #[tracing::instrument(skip_all, fields( - address = ?account_keypair.address(), - amount = amount - ))] + #[tracing::instrument( + level = "trace", + skip_all, + fields( + address = account_keypair.account_id().to_ss58check(), + amount = amount + ) + )] pub async fn add_balance( &self, account_keypair: &Keypair, - amount: u128, + amount: Currency, ) -> Result<::Hash, subxt::Error> where Keypair: subxt::tx::Signer, @@ -68,10 +76,14 @@ impl MarketClient { /// Settle deal payments for the provided [`DealId`]s. /// /// If `deal_ids` length is bigger than [`MAX_DEAL_IDS`], it will get truncated. - #[tracing::instrument(skip_all, fields( - address = ?account_keypair.address(), - deal_ids = ?deal_ids - ))] + #[tracing::instrument( + level = "trace", + skip_all, + fields( + address = account_keypair.account_id().to_ss58check(), + deal_ids = ?deal_ids + ) + )] pub async fn settle_deal_payments( &self, account_keypair: &Keypair, @@ -100,9 +112,13 @@ impl MarketClient { /// Publish the given storage deals. /// /// If `deals` length is bigger than [`MAX_DEAL_IDS`], it will get truncated. - #[tracing::instrument(skip_all, fields( - address = ?account_keypair.address() - ))] + #[tracing::instrument( + level = "trace", + skip_all, + fields( + address = account_keypair.account_id().to_ss58check() + ) + )] pub async fn publish_storage_deals( &self, account_keypair: &Keypair, @@ -149,7 +165,7 @@ impl MarketClient { Call: subxt::tx::Payload, Keypair: subxt::tx::Signer, { - tracing::info!("submitting extrinsic"); + tracing::trace!("submitting extrinsic"); let submission_progress = self .client .tx() @@ -163,7 +179,7 @@ impl MarketClient { let finalized_xt = submission_progress.wait_for_finalized().await?; let block_hash = finalized_xt.block_hash(); - tracing::info!( + tracing::trace!( block_hash = block_hash.encode_hex::(), "successfully submitted extrinsic" ); From 78aec2352f03ac99138cc9732e88e174e89fd564 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Tue, 23 Jul 2024 11:25:50 +0000 Subject: [PATCH 25/38] fix(storagext): better error message for cid deserialization --- cli/polka-storage/storagext-cli/src/main.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/cli/polka-storage/storagext-cli/src/main.rs b/cli/polka-storage/storagext-cli/src/main.rs index 958260816..c1c48f9f0 100644 --- a/cli/polka-storage/storagext-cli/src/main.rs +++ b/cli/polka-storage/storagext-cli/src/main.rs @@ -176,9 +176,12 @@ impl<'de> serde::de::Deserialize<'de> for CidWrapper { D: serde::Deserializer<'de>, { let s = String::deserialize(deserializer)?; - Ok(Self( - Cid::try_from(s.as_str()).map_err(|e| serde::de::Error::custom(format!("{e:?}")))?, - )) + let cid = Cid::try_from(s.as_str()).map_err(|e| { + serde::de::Error::custom(format!( + "failed to parse CID, check that the input is a valid CID: {e:?}" + )) + })? + Ok(Self(cid)) } } From bb746b6e10afa86dc4e4ece09a4c73ad8d590d4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Tue, 23 Jul 2024 13:16:24 +0000 Subject: [PATCH 26/38] fix(storagext): deserialization tests --- cli/polka-storage/storagext-cli/src/deser.rs | 210 +++++++++++++++++++ cli/polka-storage/storagext-cli/src/main.rs | 102 ++------- 2 files changed, 222 insertions(+), 90 deletions(-) create mode 100644 cli/polka-storage/storagext-cli/src/deser.rs diff --git a/cli/polka-storage/storagext-cli/src/deser.rs b/cli/polka-storage/storagext-cli/src/deser.rs new file mode 100644 index 000000000..7528d6bc3 --- /dev/null +++ b/cli/polka-storage/storagext-cli/src/deser.rs @@ -0,0 +1,210 @@ +//! Types in this module are defined to enable deserializing them from the CLI arguments or similar. + +use std::fmt::Debug; + +use cid::Cid; +use storagext::{BlockNumber, Currency, PolkaStorageConfig}; +use subxt::ext::sp_core::crypto::Ss58Codec; + +#[derive(Clone, PartialEq, Eq)] +pub(crate) struct DebugPair(pub(crate) Pair) +where + Pair: subxt::ext::sp_core::Pair; + +impl Debug for DebugPair +where + Pair: subxt::ext::sp_core::Pair, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("DebugPair") + .field(&self.0.public().to_ss58check()) + .finish() + } +} + +impl DebugPair +where + Pair: subxt::ext::sp_core::Pair, +{ + pub fn value_parser(src: &str) -> Result { + Ok(Self(Pair::from_string(&src, None).map_err(|err| { + format!("failed to parse pair from string: {}", err) + })?)) + } +} + +/// CID doesn't deserialize from a string, hence we need our work wrapper. +/// +/// +#[derive(Debug, Clone, PartialEq, Eq)] +pub(crate) struct CidWrapper(Cid); + +// The CID has some issues that require a workaround for strings. +// For more details, see: +impl<'de> serde::de::Deserialize<'de> for CidWrapper { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + let cid = Cid::try_from(s.as_str()).map_err(|e| { + serde::de::Error::custom(format!( + "failed to parse CID, check that the input is a valid CID: {e:?}" + )) + })?; + Ok(Self(cid)) + } +} + +#[derive(Debug, Clone, serde::Deserialize, PartialEq, Eq)] +pub(crate) struct DealProposal { + pub piece_cid: CidWrapper, + pub piece_size: u64, + pub client: ::AccountId, + pub provider: ::AccountId, + pub label: String, + pub start_block: BlockNumber, + pub end_block: BlockNumber, + pub storage_price_per_block: Currency, + pub provider_collateral: Currency, + pub state: storagext::runtime::runtime_types::pallet_market::pallet::DealState, +} + +impl Into for DealProposal { + fn into(self) -> storagext::DealProposal { + storagext::DealProposal { + piece_cid: self.piece_cid.0, + piece_size: self.piece_size, + client: self.client, + provider: self.provider, + label: self.label, + start_block: self.start_block, + end_block: self.end_block, + storage_price_per_block: self.storage_price_per_block, + provider_collateral: self.provider_collateral, + state: self.state.into(), + } + } +} + +#[cfg(test)] +mod test { + //! These tests basically ensure that the underlying parsers aren't broken without warning. + + use std::str::FromStr; + + use cid::Cid; + use storagext::PolkaStorageConfig; + use subxt::ext::sp_core::{ + ecdsa::Pair as ECDSAPair, ed25519::Pair as Ed25519Pair, sr25519::Pair as Sr25519Pair, + }; + + use super::{CidWrapper, DealProposal, DebugPair}; + + #[track_caller] + fn assert_debug_pair

(s: &str) + where + P: subxt::ext::sp_core::Pair, + { + let result_pair = DebugPair::

::value_parser(s).unwrap(); + let expect_pair = P::from_string(s, None).unwrap(); + + assert_eq!(result_pair.0.to_raw_vec(), expect_pair.to_raw_vec()); + } + + #[test] + fn deserialize_debug_pair_sr25519() { + assert_debug_pair::("//Alice"); + // https://docs.substrate.io/reference/glossary/#dev-phrase + // link visited on 23/7/2024 (you never know when Substrate's docs will become stale) + assert_debug_pair::( + "bottom drive obey lake curtain smoke basket hold race lonely fit walk", + ); + // secret seed for testing purposes + assert_debug_pair::( + "0xd045270857659c84705fbb367fd9644e5ab9b0c668f37c0bf28c6e72a120dd1f", + ); + } + + #[test] + fn deserialize_debug_pair_ecdsa() { + assert_debug_pair::("//Alice"); + // https://docs.substrate.io/reference/glossary/#dev-phrase + // link visited on 23/7/2024 (you never know when Substrate's docs will become stale) + assert_debug_pair::( + "bottom drive obey lake curtain smoke basket hold race lonely fit walk", + ); + // secret seed for testing purposes + assert_debug_pair::( + "0xd045270857659c84705fbb367fd9644e5ab9b0c668f37c0bf28c6e72a120dd1f", + ); + } + + #[test] + fn deserialize_debug_pair_ed25519() { + assert_debug_pair::("//Alice"); + // https://docs.substrate.io/reference/glossary/#dev-phrase + // link visited on 23/7/2024 (you never know when Substrate's docs will become stale) + assert_debug_pair::( + "bottom drive obey lake curtain smoke basket hold race lonely fit walk", + ); + // secret seed for testing purposes + assert_debug_pair::( + "0xd045270857659c84705fbb367fd9644e5ab9b0c668f37c0bf28c6e72a120dd1f", + ); + } + + #[test] + fn deserialize_cid_json_string() { + let result_cid = serde_json::from_str::( + "\"bafybeih5zgcgqor3dv6kfdtv3lshv3yfkfewtx73lhedgihlmvpcmywmua\"", + ) + .unwrap(); + let expect_cid = + Cid::from_str("bafybeih5zgcgqor3dv6kfdtv3lshv3yfkfewtx73lhedgihlmvpcmywmua").unwrap(); + assert_eq!(result_cid.0, expect_cid); + } + + #[test] + fn deserialize_deal_proposal_json_object() { + let json = r#" + { + "piece_cid": "bafkreibme22gw2h7y2h7tg2fhqotaqjucnbc24deqo72b6mkl2egezxhvy", + "piece_size": 1, + "client": "5GvHnpY1433RytXW66r77iL4CyewAAErDU6fAouoaPKvcvLU", + "provider": "5GvHnpY1433RytXW66r77iL4CyewAAErDU6fAouoaPKvcvLU", + "label": "heyyy", + "start_block": 30, + "end_block": 55, + "storage_price_per_block": 1, + "provider_collateral": 1, + "state": "Published" + } + "#; + let result_deal_proposal = serde_json::from_str::(json).unwrap(); + + let piece_cid = CidWrapper( + Cid::from_str("bafkreibme22gw2h7y2h7tg2fhqotaqjucnbc24deqo72b6mkl2egezxhvy").unwrap(), + ); + let expect_deal_proposal = DealProposal { + piece_cid, + piece_size: 1, + client: ::AccountId::from_str( + "5GvHnpY1433RytXW66r77iL4CyewAAErDU6fAouoaPKvcvLU", + ) + .unwrap(), + provider: ::AccountId::from_str( + "5GvHnpY1433RytXW66r77iL4CyewAAErDU6fAouoaPKvcvLU", + ) + .unwrap(), + label: "heyyy".to_string(), + start_block: 30, + end_block: 55, + storage_price_per_block: 1, + provider_collateral: 1, + state: storagext::DealState::Published, + }; + + assert_eq!(result_deal_proposal, expect_deal_proposal); + } +} diff --git a/cli/polka-storage/storagext-cli/src/main.rs b/cli/polka-storage/storagext-cli/src/main.rs index c1c48f9f0..568072f73 100644 --- a/cli/polka-storage/storagext-cli/src/main.rs +++ b/cli/polka-storage/storagext-cli/src/main.rs @@ -1,14 +1,17 @@ #![deny(clippy::unwrap_used)] mod cmd; +mod deser; use std::fmt::Debug; -use cid::Cid; use clap::{ArgGroup, Parser, Subcommand}; use cmd::market::MarketCommand; -use storagext::{BlockNumber, Currency, PolkaStorageConfig}; -use subxt::ext::sp_core::crypto::Ss58Codec; +use deser::{DealProposal, DebugPair}; +use storagext::PolkaStorageConfig; +use subxt::ext::sp_core::{ + ecdsa::Pair as ECDSAPair, ed25519::Pair as Ed25519Pair, sr25519::Pair as Sr25519Pair, +}; use tracing::level_filters::LevelFilter; use tracing_subscriber::{ filter, fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer, @@ -32,20 +35,20 @@ struct Cli { /// Sr25519 keypair, encoded as hex, BIP-39 or a dev phrase like `//Alice`. /// /// See `sp_core::crypto::Pair::from_string_with_seed` for more information. - #[arg(long, value_parser = DebugPair::::value_parser)] - pub sr25519_key: Option>, + #[arg(long, value_parser = DebugPair::::value_parser)] + pub sr25519_key: Option>, /// ECDSA keypair, encoded as hex, BIP-39 or a dev phrase like `//Alice`. /// /// See `sp_core::crypto::Pair::from_string_with_seed` for more information. - #[arg(long, value_parser = DebugPair::::value_parser)] - pub ecdsa_key: Option>, + #[arg(long, value_parser = DebugPair::::value_parser)] + pub ecdsa_key: Option>, /// Ed25519 keypair, encoded as hex, BIP-39 or a dev phrase like `//Alice`. /// /// See `sp_core::crypto::Pair::from_string_with_seed` for more information. - #[arg(long, value_parser = DebugPair::::value_parser)] - pub ed25519_key: Option>, + #[arg(long, value_parser = DebugPair::::value_parser)] + pub ed25519_key: Option>, } #[derive(Debug, Subcommand)] @@ -134,84 +137,3 @@ async fn main() -> Result<(), anyhow::Error> { Ok(()) } - -#[derive(Clone)] -struct DebugPair(Pair) -where - Pair: subxt::ext::sp_core::Pair; - -impl Debug for DebugPair -where - Pair: subxt::ext::sp_core::Pair, -{ - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_tuple("DebugPair") - .field(&self.0.public().to_ss58check()) - .finish() - } -} - -impl DebugPair -where - Pair: subxt::ext::sp_core::Pair, -{ - fn value_parser(src: &str) -> Result { - Ok(Self( - Pair::from_string(&src, None).map_err(|err| format!("{}", err))?, - )) - } -} - -/// CID doesn't deserialize from a string, hence we need our work wrapper. -/// -/// -#[derive(Debug, Clone)] -pub struct CidWrapper(Cid); - -// The CID has some issues that require a workaround for strings. -// For more details, see: -impl<'de> serde::de::Deserialize<'de> for CidWrapper { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let s = String::deserialize(deserializer)?; - let cid = Cid::try_from(s.as_str()).map_err(|e| { - serde::de::Error::custom(format!( - "failed to parse CID, check that the input is a valid CID: {e:?}" - )) - })? - Ok(Self(cid)) - } -} - -#[derive(Debug, Clone, serde::Deserialize)] -pub struct DealProposal { - pub piece_cid: CidWrapper, - pub piece_size: u64, - pub client: ::AccountId, - pub provider: ::AccountId, - pub label: String, - pub start_block: BlockNumber, - pub end_block: BlockNumber, - pub storage_price_per_block: Currency, - pub provider_collateral: Currency, - pub state: storagext::runtime::runtime_types::pallet_market::pallet::DealState, -} - -impl Into for DealProposal { - fn into(self) -> storagext::DealProposal { - storagext::DealProposal { - piece_cid: self.piece_cid.0, - piece_size: self.piece_size, - client: self.client, - provider: self.provider, - label: self.label, - start_block: self.start_block, - end_block: self.end_block, - storage_price_per_block: self.storage_price_per_block, - provider_collateral: self.provider_collateral, - state: self.state.into(), - } - } -} From 4382b6b727122dd71b6b2394bd9e538807ce26aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Tue, 23 Jul 2024 13:19:21 +0000 Subject: [PATCH 27/38] fix(storagext): rebuild when SCALE changes --- cli/polka-storage/storagext/build.rs | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 cli/polka-storage/storagext/build.rs diff --git a/cli/polka-storage/storagext/build.rs b/cli/polka-storage/storagext/build.rs new file mode 100644 index 000000000..f86754509 --- /dev/null +++ b/cli/polka-storage/storagext/build.rs @@ -0,0 +1,4 @@ +fn main() { + // This ensures that the library recompiles when the SCALE file suffers changes + println!("cargo::rerun-if-changed=../../artifacts/metadata.scale") +} From 08f87ab515664ec223b8769d8bc1158f8da4dc97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Tue, 23 Jul 2024 15:39:39 +0000 Subject: [PATCH 28/38] docs(storagext): add README --- cli/polka-storage/storagext-cli/README.md | 129 ++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 cli/polka-storage/storagext-cli/README.md diff --git a/cli/polka-storage/storagext-cli/README.md b/cli/polka-storage/storagext-cli/README.md new file mode 100644 index 000000000..3aa5d8b97 --- /dev/null +++ b/cli/polka-storage/storagext-cli/README.md @@ -0,0 +1,129 @@ +# storagext-cli + +CLI wrapper around `storagext`, it aims to provide an ergonomic way to execute the extrinsics made available by the Polka Storage Parachain. + +The CLI commands are namespaced according to the pallet you will be interacting with, +as such, if you want to interact with the `market` pallet, you can find it's functions under `storagext-cli market`. + +## Global Flags + +### Keypair — `--X-key` + +Extrinsics are *required* to be signed, as such you need to pass your key. + +You can pass it as an hex encoded string, seed key (BIP-39) or use the dev phrases available +(e.g. `//Alice` — remember that these are configured as Sr25519 keypairs by default). + +Depending on the type of key you use, you should use a different flag as well: + +* `--sr25519-key` for Sr25519 keypairs +* `--ecdsa-key` for ECDSA keypairs +* `--ed25519-key` for Ed25519 keypairs + +Example: + +``` +storagext-cli --sr25519 "//Alice" ... +``` + +### RPC Address — `--node-rpc` + +If you so wish, you can also change the node RPC address, this is achieved through the `--node-rpc` flag. The address can be secure or not (i.e. use TLS). + +Secure if, for example, you are running the node behind a reverse proxy (like Nginx) which enables TLS for your connections: + +``` +storagext-cli --node-rpc wss://172.16.10.10:9944 ... +``` + +Or insecure if, for example, you are running the node locally, using just the standard setup. + +``` +storagext-cli --node-rpc ws://0.0.0.0:7331 ... +``` + + +## `market` + +The `market` subcommand enables you to interact with the `market` pallet, +this is one of the entrypoints for the parachain as you need to add some balance before you can make use of the parachain features. + +### `add-balance` + +Add a given amount of MDOT to your free balance, this will enable you to store your files in providers or provide space to others. + +``` +storagext-cli --sr25519-key market add-balance +``` + +### `withdraw-balance` + +The dual to `add-balance`, `withdraw-balance` allows you to reclaim back DOT from your free balance. +You cannot reclaim DOT from the locked balance, as it is necessary to pay out for faults, etc. + +``` +storagext-cli --sr25519-key market withdraw-balance +``` + +### `publish-storage-deals` + +As a storage provider, you are able to publish storage deals you have done off-chain. + +``` +storagext-cli --sr25519-key market publish-storage-deals +``` + +The command takes `deals` as a JSON array, containing one or more storage deals. + +

+Example Storage Deals JSON +

+ +```json +[ + { + "piece_cid": "bafkreibme22gw2h7y2h7tg2fhqotaqjucnbc24deqo72b6mkl2egezxhvy", + "piece_size": 47000000000, + "client": "5GvHnpY1433RytXW66r77iL4CyewAAErDU6fAouoaPKvcvLU", + "provider": "5DJiX75PZjvntUMeq7XP8qqJ3Tdg6F2Nybk9So1Z5mWArnG2", + "label": "737-800 schematics", + "start_block": 1580889600, + "end_block": 1721747575, + "storage_price_per_block": 17144352, + "provider_collateral": 3735928559, + "state": "Published" + }, + { + "piece_cid": "bafybeih5zgcgqor3dv6kfdtv3lshv3yfkfewtx73lhedgihlmvpcmywmua", + "piece_size": 269490583, + "client": "5GvHnpY1433RytXW66r77iL4CyewAAErDU6fAouoaPKvcvLU", + "provider": "5DJiX75PZjvntUMeq7XP8qqJ3Tdg6F2Nybk9So1Z5mWArnG2", + "label": "Falcon C-00000291", + "start_block": 1721410062, + "end_block": 1721747843, + "storage_price_per_block": 46349, + "provider_collateral": 3735928559, + "state": "Published" + } +] +``` + +

+
+ +However, writing a full JSON file in a single command is cumbersome, to solve that, +you prefix a file path with `@` and use the JSON file location instead: + +``` +storagext-cli --sr25519-key market publish-storage-deals @important-deals.json +``` + +### `settle-deal-payments` + +As a storage provider, you are entitled to your payment (when you are well behaved), +you can reclaim your payment by calling `settle-deal-payments`. The command takes a +list of IDs for the deals to be processed. + +``` +storagext-cli --sr25519-key market settle-deal-payments +``` From 1812b6d6226102db35e681b3fbe8d534c701411a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Tue, 23 Jul 2024 15:57:35 +0000 Subject: [PATCH 29/38] fix(storagext): wait for successful finalization --- cli/polka-storage/storagext/src/market.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cli/polka-storage/storagext/src/market.rs b/cli/polka-storage/storagext/src/market.rs index a1f346280..c87235b59 100644 --- a/cli/polka-storage/storagext/src/market.rs +++ b/cli/polka-storage/storagext/src/market.rs @@ -178,6 +178,9 @@ impl MarketClient { ); let finalized_xt = submission_progress.wait_for_finalized().await?; + // Wait for a successful inclusion because finalization != success + finalized_xt.wait_for_success().await?; + let block_hash = finalized_xt.block_hash(); tracing::trace!( block_hash = block_hash.encode_hex::(), From 4096bbed751569fcd0fecfecb050dd97be3e3a7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Tue, 23 Jul 2024 16:16:04 +0000 Subject: [PATCH 30/38] fix(storagext): metadata mismatch --- cli/artifacts/metadata.scale | Bin 135134 -> 136258 bytes cli/polka-storage/storagext/src/lib.rs | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/artifacts/metadata.scale b/cli/artifacts/metadata.scale index f3602b324266362e2b053a833deea7c6ccf172d6..599139ec1d6b1f08211ba705d530021eb87daac6 100644 GIT binary patch delta 3748 zcma)94RBP|6~5=~yReZU8%U4*swbLwBp8DVhsC&VCYaNtJNU<0C~jM=MugjSVJjNd9d7Hm^7bt4}(fMW*Ehv*4l7ddq4~tXN^0bq$88 zM~z2$Xgdox@o;m()1N@2^CBZ|OJ8{`4R7)=Pb74^?e*2Izfdqz|Jk+U-8IXhG#a&b zdW!)k+U7{2FB^)a2AQy**I=GC(<`CFEjReFe`+$kz5X?a0^$^Tc zI#rRUL;m_s6)L|IcMQv1xmE^bQ!-Z1ZA9r*)miBURjmdM{DDoD$q6BWDl5iSq7edw zbg6_Wx=Nl9^*Y3$TMRVAO!3acFlPo)s|Zoau`$E<= z)zt0ta@|!;Pyui%4gR75`8lV@fu5GaM}1^K{Kb*VI(syE8<- z3A1sVSD8=>*F}d3OW||zstI{W{GACLsL(9PouQ#mV_QxXLavL4Em(Nh=QnLV(68)0 zP;c|)p!)rOLPfs?k(n9ZJTM4ks(j1T76nKaO$Ey|(k?arlR$05gKAA|tO#Ww|~ zdDL^@hjD0tI|Q^qF%EaPK*7`kPho(Rt7LJSX?F_rQo+MtpV-qLZrB_8iAw7*m`I!zBBgE(gnb(04uaDpCG-;#TK*~Bl;9(wabdp<j}#Y8sNbh?O`wItVxf@ITl&Nl(u1EmB@v%ki_(6j@1O~sLm3eam+|arZf+#+-W#X ztQCt|Bwfma(F)U>)|d%2jYrlQ5p*c+8JX@s4`ngUJFLy%$o!uu- z>im9sik_we^b9>m&(jNZkdl6Jx7(jS3d`R0XQcY%i(;QXG;$-^#b)brEaLR#nU}d1cPFr2i7Z> z=(8{1Hg)dSBz9#nj>eK9ap%kMM|eW0y|7$8tirL>Kwhq>?Zu+fFPvVy^;eK6vZ9bH z272KRC>I~}!kvmvQ_Yid#j@jQ+kUb6IIMz`?$gI%vf|Tf+YYaMeF;p8EyT|`)KkhG5kIRVZhD)0Cr+);6C+txC=0NZw|xr zaMrE;5Z(c};1>Kt8ak|A7I%JxJ;Y_v_7QvwK6d**g8WHvMGSrdjd0B^y#j9oWC;IN z_%06mRjBu6(5d3>tJsodiN;UiQ^*q!UxW3&0=iiAUV~b=*S&EKUh-j_j$B821$AUF z^2FrNV4tssZgaaogJKH0ceUo}1@*ToB<7#LvI@mo11YK9E(9I;SQRwGw!rB6~t zv!YbuhW%Vo3Va7>dZT{k!-fP7x$jO^`asc+y4@MdGXN*V?NgLr=B=s5vr=OkPKD`p z6^T(}3CVs<{A-FbuU(!d%y5PiYytLA2+b_RtW%aumlJHW<>vs>^<5L`nA0#X+Sp%X z9>M#JUlK9zvOg4>2pifSB+G%72OERz=EWM>!k4hJ(rr~CnX+VtFuitH<_mnhF9J-( zBYnSzgdY`p8(BHQR*hxLFySv-teL75iH=O=L<70Qi~V@x5%239U4qoF8ZJFc$1b>X zLJ%}|LpGPAfPdNGVci_4G}g^D4C?>H5_4`I^w(0FzEu_?BQ{76Ucy4|s~)1{ Ezj3^MR{#J2 delta 2430 zcmZuz4@_0p89%@K&cSCvy{Pb(L^gMa2%>$ zU4aTfrJE;lET2!V|PBZKsl~^OO zwUtOyh85abiFBhauY_$GV~UfrW_q&{UR^V_#y!Yfd)H7l$=S3iX%@{2n=v&-&Yk!!W)06XmN_0r#a^UD?CHz(zk6{C_?(LT z_>QbcqaS(rlE(blf(JC`N2&y41JD4f3&6H!Nu3qOzNGE|Hg12wdGe7!*zNZjLCtem z)x&wltrBaTW(l!*_%|hLPUCsvp2%l^eu#E4Z>!F z(0D1A1e1?JCi;;7L=nmrKID60h< zB0axMQ`$siESN}#Ucr-SH$-RBqpe7?$gn=>KpKr2RszW*>V`nvfuNJI8zS-tWvzaK@M9I@(fRSc@?*apwU70} z&L@PmCh{+yLhZfC!6e=4m3wK5)IMa;sy^7Lun!|>ric2m16{PYAGK@wZxI-w&o0XC9T-3c`tKi`BX?fu5ul)_% zfiar+1Rc1c*UaK~z=Zzzr-ry`K0|qP@@AN!m*=n>v-+($q{m>6KK%!(@wr~|1#SX@ zQtso2vI*TsrA3J4^uc{x!3t{l3SY>y_`XJgWxdFx;jdAK9lH7eS1dA5L;sZc0TDJ5 zkV>|BT(A_2QvLOLN~uuQ^EcN}K34+L ze7E{CjdH~;P5b%Z&^96Suc~E-EYvQPLujFogpz4#6VYVrSux5KN4w5rl_8nJZe5R4 zS|N93!Aj+NVzzm!hl;ddzO%t#mX)x9(pM>IyQ`cH_Dx~8SF_jq++lltNUO3x?GM^r zPLHeJ<23Gq&3g*nKI2~_zdmRJrcxG1HdXmBX-}c^+5a7s+U4N!c;yZ?u2$w7`$Rh9 z4VE^G#s@`4!TuUe{$lujC$ylyME+rD!6DJP*F;MKnyX9;h9v1Vq3$#>$FmE_uu!v2 z Date: Wed, 24 Jul 2024 12:40:15 +0100 Subject: [PATCH 31/38] fix: typo Co-authored-by: Konrad Stepniak --- cli/polka-storage/storagext-cli/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/polka-storage/storagext-cli/README.md b/cli/polka-storage/storagext-cli/README.md index 3aa5d8b97..40ea4526a 100644 --- a/cli/polka-storage/storagext-cli/README.md +++ b/cli/polka-storage/storagext-cli/README.md @@ -23,7 +23,7 @@ Depending on the type of key you use, you should use a different flag as well: Example: ``` -storagext-cli --sr25519 "//Alice" ... +storagext-cli --sr25519-key "//Alice" ... ``` ### RPC Address — `--node-rpc` From 4292a4e269f378e802e7090d1c0c7e4b6ee0d789 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Wed, 24 Jul 2024 12:40:31 +0100 Subject: [PATCH 32/38] fix: wrong ip Co-authored-by: Konrad Stepniak --- cli/polka-storage/storagext-cli/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/polka-storage/storagext-cli/README.md b/cli/polka-storage/storagext-cli/README.md index 40ea4526a..714cbdca3 100644 --- a/cli/polka-storage/storagext-cli/README.md +++ b/cli/polka-storage/storagext-cli/README.md @@ -39,7 +39,7 @@ storagext-cli --node-rpc wss://172.16.10.10:9944 ... Or insecure if, for example, you are running the node locally, using just the standard setup. ``` -storagext-cli --node-rpc ws://0.0.0.0:7331 ... +storagext-cli --node-rpc ws://127.0.0.1:7331 ... ``` From 110c83402fca0cc6f6365aa90082db43b9acb467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Wed, 24 Jul 2024 12:40:51 +0100 Subject: [PATCH 33/38] fix: typo Co-authored-by: Konrad Stepniak --- cli/polka-storage/storagext-cli/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/polka-storage/storagext-cli/README.md b/cli/polka-storage/storagext-cli/README.md index 714cbdca3..118956e01 100644 --- a/cli/polka-storage/storagext-cli/README.md +++ b/cli/polka-storage/storagext-cli/README.md @@ -121,7 +121,7 @@ storagext-cli --sr25519-key market publish-storage-deals @important-deals. ### `settle-deal-payments` As a storage provider, you are entitled to your payment (when you are well behaved), -you can reclaim your payment by calling `settle-deal-payments`. The command takes a +you can claim your payment by calling`settle-deal-payments`. The command takes a list of IDs for the deals to be processed. ``` From fde6ac6f6b5199846c42501effe7677a5f191517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Wed, 24 Jul 2024 12:50:56 +0000 Subject: [PATCH 34/38] fix(zombienet): port --- zombienet/local-kube-testnet.toml | 2 +- zombienet/local-testnet.toml | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/zombienet/local-kube-testnet.toml b/zombienet/local-kube-testnet.toml index c838059de..413a7e482 100644 --- a/zombienet/local-kube-testnet.toml +++ b/zombienet/local-kube-testnet.toml @@ -29,4 +29,4 @@ command = "polka-storage-node" image = "polkadotstorage.azurecr.io/parachain-node:0.1.0" name = "charlie" validator = true -ws_port = 42069 +rpc_port = 42069 diff --git a/zombienet/local-testnet.toml b/zombienet/local-testnet.toml index 2c2ea2531..24ef01395 100644 --- a/zombienet/local-testnet.toml +++ b/zombienet/local-testnet.toml @@ -1,6 +1,9 @@ [relaychain] chain = "rococo-local" -default_args = ["--detailed-log-output", "-lparachain=debug,xcm=trace,runtime=trace"] +default_args = [ + "--detailed-log-output", + "-lparachain=debug,xcm=trace,runtime=trace", +] default_command = "polkadot" [[relaychain.nodes]] @@ -25,4 +28,4 @@ args = ["--detailed-log-output", "-lparachain=debug,xcm=trace,runtime=trace"] command = "target/release/polka-storage-node" name = "charlie" validator = true -ws_port = 42069 +rpc_port = 42069 From 2c5f7fa27b1646dc3ad89460e532c7e6e6e72357 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Wed, 24 Jul 2024 12:51:08 +0000 Subject: [PATCH 35/38] fix: address comments --- cli/polka-storage/storagext-cli/README.md | 9 ++++++++- cli/polka-storage/storagext/src/lib.rs | 6 ++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/cli/polka-storage/storagext-cli/README.md b/cli/polka-storage/storagext-cli/README.md index 118956e01..c1b501d92 100644 --- a/cli/polka-storage/storagext-cli/README.md +++ b/cli/polka-storage/storagext-cli/README.md @@ -50,7 +50,8 @@ this is one of the entrypoints for the parachain as you need to add some balance ### `add-balance` -Add a given amount of MDOT to your free balance, this will enable you to store your files in providers or provide space to others. +Add a given amount of [Plancks](https://wiki.polkadot.network/docs/learn-DOT#the-planck-unit) to your free balance, +this will enable you to store your files in providers or provide space to others. ``` storagext-cli --sr25519-key market add-balance @@ -124,6 +125,12 @@ As a storage provider, you are entitled to your payment (when you are well behav you can claim your payment by calling`settle-deal-payments`. The command takes a list of IDs for the deals to be processed. +> [!NOTE] +> The deal ID list is separated by spaces, for example: +> ``` +> settle_deal_payments 1203 1243 1254 +> ``` + ``` storagext-cli --sr25519-key market settle-deal-payments ``` diff --git a/cli/polka-storage/storagext/src/lib.rs b/cli/polka-storage/storagext/src/lib.rs index f787062de..9e6f70bc0 100644 --- a/cli/polka-storage/storagext/src/lib.rs +++ b/cli/polka-storage/storagext/src/lib.rs @@ -30,8 +30,10 @@ impl subxt::Config for PolkaStorageConfig { type Address = subxt::config::polkadot::MultiAddress; type Signature = subxt::ext::sp_runtime::MultiSignature; type Hasher = subxt::config::substrate::BlakeTwo256; - type Header = - subxt::config::substrate::SubstrateHeader; + type Header = subxt::config::substrate::SubstrateHeader< + BlockNumber, + subxt::config::substrate::BlakeTwo256, + >; type ExtrinsicParams = subxt::config::DefaultExtrinsicParams; type AssetId = u32; } From 07051c1d303e9714dac7c5cf7fe78e26b4d4bf0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Duarte?= Date: Wed, 24 Jul 2024 13:13:31 +0000 Subject: [PATCH 36/38] style: taplo --- zombienet/local-kube-testnet.toml | 2 +- zombienet/local-testnet.toml | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/zombienet/local-kube-testnet.toml b/zombienet/local-kube-testnet.toml index 413a7e482..0a860218f 100644 --- a/zombienet/local-kube-testnet.toml +++ b/zombienet/local-kube-testnet.toml @@ -28,5 +28,5 @@ args = ["--detailed-log-output", "-lparachain=debug,xcm=trace,runtime=trace"] command = "polka-storage-node" image = "polkadotstorage.azurecr.io/parachain-node:0.1.0" name = "charlie" -validator = true rpc_port = 42069 +validator = true diff --git a/zombienet/local-testnet.toml b/zombienet/local-testnet.toml index 24ef01395..5d994e7d4 100644 --- a/zombienet/local-testnet.toml +++ b/zombienet/local-testnet.toml @@ -1,9 +1,6 @@ [relaychain] chain = "rococo-local" -default_args = [ - "--detailed-log-output", - "-lparachain=debug,xcm=trace,runtime=trace", -] +default_args = ["--detailed-log-output", "-lparachain=debug,xcm=trace,runtime=trace"] default_command = "polkadot" [[relaychain.nodes]] @@ -27,5 +24,5 @@ id = 1000 args = ["--detailed-log-output", "-lparachain=debug,xcm=trace,runtime=trace"] command = "target/release/polka-storage-node" name = "charlie" -validator = true rpc_port = 42069 +validator = true From 936e708fb9595390192c30dd39a3a858823de26e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Thu, 25 Jul 2024 09:22:00 +0100 Subject: [PATCH 37/38] fix(zombienet): local config --- zombienet/local-testnet.toml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/zombienet/local-testnet.toml b/zombienet/local-testnet.toml index 5d994e7d4..caee7bde2 100644 --- a/zombienet/local-testnet.toml +++ b/zombienet/local-testnet.toml @@ -1,6 +1,9 @@ [relaychain] chain = "rococo-local" -default_args = ["--detailed-log-output", "-lparachain=debug,xcm=trace,runtime=trace"] +default_args = [ + "--detailed-log-output", + "-lparachain=debug,xcm=trace,runtime=trace", +] default_command = "polkadot" [[relaychain.nodes]] @@ -24,5 +27,5 @@ id = 1000 args = ["--detailed-log-output", "-lparachain=debug,xcm=trace,runtime=trace"] command = "target/release/polka-storage-node" name = "charlie" -rpc_port = 42069 +ws_port = 42069 validator = true From ce25aebf9cebe42a63d838792dfdb84fbecd7efb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Duarte?= Date: Thu, 25 Jul 2024 09:43:00 +0100 Subject: [PATCH 38/38] style: taplo --- zombienet/local-testnet.toml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/zombienet/local-testnet.toml b/zombienet/local-testnet.toml index caee7bde2..2c2ea2531 100644 --- a/zombienet/local-testnet.toml +++ b/zombienet/local-testnet.toml @@ -1,9 +1,6 @@ [relaychain] chain = "rococo-local" -default_args = [ - "--detailed-log-output", - "-lparachain=debug,xcm=trace,runtime=trace", -] +default_args = ["--detailed-log-output", "-lparachain=debug,xcm=trace,runtime=trace"] default_command = "polkadot" [[relaychain.nodes]] @@ -27,5 +24,5 @@ id = 1000 args = ["--detailed-log-output", "-lparachain=debug,xcm=trace,runtime=trace"] command = "target/release/polka-storage-node" name = "charlie" -ws_port = 42069 validator = true +ws_port = 42069