From b60c38401de39dfb855c4fa14ca68de9f40d3c9d Mon Sep 17 00:00:00 2001 From: Konrad Stepniak Date: Mon, 29 Jul 2024 16:18:37 +0200 Subject: [PATCH] feat(storagext): prove commit --- cli/polka-storage/storagext-cli/Cargo.toml | 2 +- .../storagext-cli/src/cmd/storage_provider.rs | 52 ++++++++++++++++--- cli/polka-storage/storagext-cli/src/deser.rs | 36 +++++++++++++ cli/polka-storage/storagext/src/lib.rs | 17 ++++++ .../storagext/src/runtime/bounded_vec.rs | 6 +++ .../storagext/src/storage_provider.rs | 26 +++++++++- 6 files changed, 130 insertions(+), 9 deletions(-) diff --git a/cli/polka-storage/storagext-cli/Cargo.toml b/cli/polka-storage/storagext-cli/Cargo.toml index 1a83c41a1..db7037c00 100644 --- a/cli/polka-storage/storagext-cli/Cargo.toml +++ b/cli/polka-storage/storagext-cli/Cargo.toml @@ -18,7 +18,7 @@ cid = { workspace = true, features = ["scale-codec"] } clap = { workspace = true, features = ["derive"] } codec.workspace = true frame-support = { workspace = true, features = ["std"] } -hex.workspace = true +hex = { workspace = true, features = ["std"] } primitives-proofs = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } diff --git a/cli/polka-storage/storagext-cli/src/cmd/storage_provider.rs b/cli/polka-storage/storagext-cli/src/cmd/storage_provider.rs index 29b13c636..7d76cdbb8 100644 --- a/cli/polka-storage/storagext-cli/src/cmd/storage_provider.rs +++ b/cli/polka-storage/storagext-cli/src/cmd/storage_provider.rs @@ -1,12 +1,21 @@ use std::{path::PathBuf, str::FromStr}; -use crate::deser::PreCommitSector; +use crate::deser::{PreCommitSector, ProveCommitSector}; use anyhow::bail; use clap::Subcommand; use storagext::{storage_provider::StorageProviderClient, PolkaStorageConfig, RegisteredPoStProof}; use subxt::ext::sp_core::crypto::Ss58Codec; use url::Url; +fn parse_post_proof(src: &str) -> Result { + let post_proof = match src { + "2KiB" => RegisteredPoStProof::StackedDRGWindow2KiBV1P1, + unknown => bail!("Unknown PoSt Proof type: {}", unknown), + }; + + Ok(post_proof) +} + #[derive(Debug, Clone)] pub struct PreCommitSectorWrapper(PreCommitSector); @@ -25,13 +34,22 @@ impl PreCommitSectorWrapper { } } -fn parse_post_proof(src: &str) -> Result { - let post_proof = match src { - "2KiB" => RegisteredPoStProof::StackedDRGWindow2KiBV1P1, - unknown => bail!("Unknown PoSt Proof type: {}", unknown), - }; +#[derive(Debug, Clone)] +pub struct ProveCommitSectorWrapper(ProveCommitSector); - Ok(post_proof) +impl ProveCommitSectorWrapper { + /// Attempt to parse a command-line argument into [`ProveCommitSector`]. + /// + /// The command-line argument may be a valid JSON object, or a file path starting with @. + pub(crate) fn parse(src: &str) -> Result { + Ok(Self(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 { + serde_json::from_str(src) + }?)) + } } #[derive(Debug, Subcommand)] @@ -58,6 +76,12 @@ pub enum StorageProviderCommand { #[arg(value_parser = PreCommitSectorWrapper::parse)] pre_commit_sector: PreCommitSectorWrapper, }, + /// Proves sector that has been previously pre-committed. + /// After proving, a deal in a sector is considered Active. + ProveCommit { + #[arg(value_parser = ProveCommitSectorWrapper::parse)] + prove_commit_sector: ProveCommitSectorWrapper, + }, } impl StorageProviderCommand { @@ -112,6 +136,20 @@ impl StorageProviderCommand { sector_number ); } + StorageProviderCommand::ProveCommit { + prove_commit_sector, + } => { + let sector_number = prove_commit_sector.0.sector_number; + let block_hash = client + .prove_commit_sector(&account_keypair, prove_commit_sector.0.into()) + .await?; + + tracing::info!( + "[{}] Successfully proven sector {}.", + block_hash, + sector_number + ); + } } Ok(()) } diff --git a/cli/polka-storage/storagext-cli/src/deser.rs b/cli/polka-storage/storagext-cli/src/deser.rs index 350b4ee90..4f060876c 100644 --- a/cli/polka-storage/storagext-cli/src/deser.rs +++ b/cli/polka-storage/storagext-cli/src/deser.rs @@ -120,6 +120,42 @@ impl Into for PreCommitSector { } } +/// Deserialize hex-string as `Vec`. +/// JSON doesn't have 'bytes' format, so we specify that bytes need to be just a hex-string and we provide deserializer for it. +#[derive(Debug, Clone, PartialEq, Eq)] +pub(crate) struct HexBytesWrapper(pub(crate) Vec); + +impl<'de> serde::de::Deserialize<'de> for HexBytesWrapper { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + let bytes = hex::decode(s.as_str()).map_err(|e| { + serde::de::Error::custom(format!("failed to parse bytes from hex string: {e:?}")) + })?; + Ok(Self(bytes)) + } +} + +#[derive(Debug, Clone, serde::Deserialize)] +pub(crate) struct ProveCommitSector { + /// Number of a sector that has been previously pre-committed. + pub sector_number: SectorNumber, + /// Proof bytes as a hex string. + /// If empty it fails validation, it has any bytes it succeeds. + pub proof: HexBytesWrapper, +} + +impl Into for ProveCommitSector { + fn into(self) -> storagext::ProveCommitSector { + storagext::ProveCommitSector { + sector_number: self.sector_number, + proof: self.proof.0.clone(), + } + } +} + #[cfg(test)] mod test { //! These tests basically ensure that the underlying parsers aren't broken without warning. diff --git a/cli/polka-storage/storagext/src/lib.rs b/cli/polka-storage/storagext/src/lib.rs index a7085eaa9..f2d71ff02 100644 --- a/cli/polka-storage/storagext/src/lib.rs +++ b/cli/polka-storage/storagext/src/lib.rs @@ -144,3 +144,20 @@ impl From } } } + +#[derive(CloneNoBound)] +pub struct ProveCommitSector { + pub sector_number: SectorNumber, + pub proof: Vec, +} + +impl From + for runtime::runtime_types::pallet_storage_provider::sector::ProveCommitSector +{ + fn from(value: ProveCommitSector) -> Self { + Self { + sector_number: value.sector_number, + proof: value.proof.into_bounded_byte_vec(), + } + } +} diff --git a/cli/polka-storage/storagext/src/runtime/bounded_vec.rs b/cli/polka-storage/storagext/src/runtime/bounded_vec.rs index 3ea4526ed..9b2ddf6a6 100644 --- a/cli/polka-storage/storagext/src/runtime/bounded_vec.rs +++ b/cli/polka-storage/storagext/src/runtime/bounded_vec.rs @@ -26,3 +26,9 @@ impl IntoBoundedByteVec for String { bounded_vec::BoundedVec(self.into_bytes()) } } + +impl IntoBoundedByteVec for Vec { + fn into_bounded_byte_vec(self) -> bounded_vec::BoundedVec { + bounded_vec::BoundedVec(self) + } +} diff --git a/cli/polka-storage/storagext/src/storage_provider.rs b/cli/polka-storage/storagext/src/storage_provider.rs index 5092443bf..029286186 100644 --- a/cli/polka-storage/storagext/src/storage_provider.rs +++ b/cli/polka-storage/storagext/src/storage_provider.rs @@ -2,7 +2,7 @@ use subxt::ext::sp_core::crypto::Ss58Codec; use crate::{ runtime::{self, bounded_vec::IntoBoundedByteVec}, - PolkaStorageConfig, RegisteredPoStProof, SectorPreCommitInfo, + PolkaStorageConfig, ProveCommitSector, RegisteredPoStProof, SectorPreCommitInfo, }; /// The maximum number of deal IDs supported. @@ -70,4 +70,28 @@ impl StorageProviderClient { .traced_submission(&payload, account_keypair) .await } + + #[tracing::instrument( + level = "trace", + skip_all, + fields( + address = account_keypair.account_id().to_ss58check(), + ) + )] + pub async fn prove_commit_sector( + &self, + account_keypair: &Keypair, + prove_commit_sector: ProveCommitSector, + ) -> Result<::Hash, subxt::Error> + where + Keypair: subxt::tx::Signer, + { + let payload = runtime::tx() + .storage_provider() + .prove_commit_sector(prove_commit_sector.into()); + + self.client + .traced_submission(&payload, account_keypair) + .await + } }