diff --git a/.github/workflows/README.md b/.github/workflows/README.md index e5de7d8524..69fba9770f 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -36,7 +36,7 @@ Release | [`rolling-upgrade-testing.yml`](rolling-upgrade-testing.yml) | Mixed-version perf tests for `thresholdWithEnclave` | Manual | | [`pr-preview-deploy.yml`](pr-preview-deploy.yml) | Ephemeral PR environments | Workflow call | | [`pr-preview-destroy.yml`](pr-preview-destroy.yml) | Cleanup PR environments | PR close, label removal, scheduled | -| [`rust-lint.yml`](rust-lint.yml) | `cargo fmt --check` + `cargo clippy -D warnings` + `cargo dylint` | PRs | +| [`rust-lint.yml`](rust-lint.yml) | `cargo fmt --check` + `cargo clippy -D warnings` + `make lint-dylint` | PRs | | [`common-testing.yml`](common-testing.yml) | Reusable test runner | Workflow call | | [`wasm-testing.yml`](wasm-testing.yml) | WASM test pipeline | Workflow call | | [`ci_lint.yml`](ci_lint.yml) | actionlint + zizmor on workflow files | PRs | @@ -166,7 +166,7 @@ Generates WASM test fixtures from Rust tests, builds `tkms` and `node-tkms` pack ### `rust-lint.yml` -`cargo fmt --all -- --check`, `cargo clippy --workspace --all-targets --all-features -- -D warnings`, and `cargo dylint --all`. Runs on every PR. +`cargo fmt --all -- --check`, `cargo clippy --workspace --all-targets --all-features -- -D warnings`, and `make lint-dylint`. Runs on every PR. The Makefile centralizes the `DYLINT_RUSTFLAGS` passed to the Dylint rustc driver, turning Dylint warnings to errors while disabling the broad tfhe-rs `serialize_without_versionize` lint. ### `docker-build.yml` diff --git a/.github/workflows/kind-testing.yml b/.github/workflows/kind-testing.yml index 689d3811f3..316f3d8bbf 100644 --- a/.github/workflows/kind-testing.yml +++ b/.github/workflows/kind-testing.yml @@ -223,11 +223,6 @@ jobs: # Verify the installed version cargo nextest --version - - name: Setup cargo dylint - if: matrix.cargo-check == true - run: | - cargo install cargo-dylint dylint-link --force - - name: clippy and rustfmt versions if: matrix.cargo-check == true run: | @@ -243,10 +238,6 @@ jobs: PACKAGE_NAME: 'kms-core-client' run: cargo clippy --all-targets --all-features --package "${PACKAGE_NAME}" -- -D warnings - - name: Linting dylint - if: matrix.cargo-check == true - run: cargo dylint --all - # ========================================================================== # Test Execution # Runs the Kubernetes integration tests using the configured environment diff --git a/.github/workflows/rust-lint.yml b/.github/workflows/rust-lint.yml index 06ebd47368..136aed2117 100644 --- a/.github/workflows/rust-lint.yml +++ b/.github/workflows/rust-lint.yml @@ -54,12 +54,12 @@ jobs: echo "EXECUTING: cargo clippy --workspace --all-targets --all-features -- -D warnings" cargo clippy --workspace --all-targets --all-features -- -D warnings - - name: Install cargo-dylint + - name: Install Dylint run: | - echo "EXECUTING: cargo install cargo-dylint dylint-link --locked" - cargo install cargo-dylint dylint-link --locked + echo "EXECUTING: make install-dylint" + make install-dylint - name: Dylint run: | - echo "EXECUTING: cargo dylint --all" - cargo dylint --all + echo "EXECUTING: make lint-dylint" + make lint-dylint diff --git a/Cargo.toml b/Cargo.toml index 8f75258517..fc604d99aa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -197,6 +197,7 @@ syn = { version = "2.0", features = ["full"] } # Syn macro parsing - MEDIUM RIS sysinfo = "0.36.1" # System information gathering - MEDIUM RISK: Reputable individual maintainer (GuillaumeGomez), 71M+ downloads tempfile = "=3.20.0" # Temporary file handling - MEDIUM RISK: Individual maintainers (Stebalien, KodrAus), 345M+ downloads, test-only dependency test-context = "=0.4.1" # Test context utilities - MEDIUM RISK: Individual maintainers (markhildreth, JasperV), test-only dependency +# NOTE: when changing the tfhe dependency, consider also updating the pinned version of dylint lints from tfhe (see dylint.toml) tfhe = "=1.6.1" # Fully Homomorphic Encryption library - LOW RISK: Zama tfhe-csprng = "=0.9.0" # Cryptographically secure PRNG for TFHE - LOW RISK: Zama tfhe-versionable = "=0.7.0" # TFHE versioning support - LOW RISK: Zama diff --git a/Makefile b/Makefile index 38e62e2b75..f5fb7bbe5d 100644 --- a/Makefile +++ b/Makefile @@ -96,12 +96,33 @@ check-git-lfs: pull-lfs-files: check-git-lfs git lfs pull -linting-all: + +# `DYLINT_RUSTFLAGS` is consumed by `cargo-dylint` and forwarded to the `rustc` +# driver that runs each Dylint library. Here it turns warnings to errors so Dylint +# findings fail CI, while disabling the tfhe-rs `serialize_without_versionize` +# lint, which is intentionally too broad for this workspace. `-Aunknown-lints` +# is paired with it because `cargo dylint --all` loads multiple lint +# libraries/toolchains; libraries that do not define +# `serialize_without_versionize` would otherwise emit an "unknown lint" warning +# for the command-line allow. +DYLINT_RUSTFLAGS ?= -D warnings -Aunknown-lints -Aserialize_without_versionize + +lint: cargo clippy --all-targets --all-features -- -D warnings -linting-package: +lint-package: @if [ -z "$(PACKAGE)" ]; then \ - echo "Error: PACKAGE is not set. Usage: make clippy-package PACKAGE="; \ + echo "Error: PACKAGE is not set. Usage: make lint-package PACKAGE="; \ exit 1; \ fi cargo clippy --all-targets --all-features --package $(PACKAGE) -- -D warnings + +# The nightly toolchain and components needed to build each Dylint library are +# auto-installed by rustup on the first `cargo dylint --all` run, driven by the +# `rust-toolchain` file each library ships (e.g. `tfhe-lints` in the tfhe-rs +# repo at the tag pinned in `dylint.toml`). +install-dylint: + cargo install cargo-dylint dylint-link --locked + +lint-dylint: + DYLINT_RUSTFLAGS="$(DYLINT_RUSTFLAGS)" cargo dylint --all diff --git a/ai-docs/ARCHITECTURE.md b/ai-docs/ARCHITECTURE.md index c724d4ea80..cc59bdf010 100644 --- a/ai-docs/ARCHITECTURE.md +++ b/ai-docs/ARCHITECTURE.md @@ -219,8 +219,8 @@ enum whose variants are its historical layouts (`V0`, `V1`, …). `Unversionize` dispatches to the right variant by tag on read. On-disk and on-wire encoding goes through the pinned-`bincode` wrapper [bc2wrap](bc2wrap/) so the binary layout is deterministic. Examples of -versioned types: `BackupCiphertextVersioned`, -`InternalCustodianContextVersioned`, `AppKeyBlobVersioned`. +versioned types: `BackupCiphertextVersions`, +`InternalCustodianContextVersions`, `AppKeyBlobVersions`. **Freeze-and-replay harness.** [backward-compatibility/](backward-compatibility/) is a separate Cargo workspace (excluded from the root — see [Cargo.toml](Cargo.toml) diff --git a/ai-docs/COMMANDS.md b/ai-docs/COMMANDS.md index c9b554ed98..56b44bd3c9 100644 --- a/ai-docs/COMMANDS.md +++ b/ai-docs/COMMANDS.md @@ -23,15 +23,23 @@ cargo clippy --all-targets --all-features -- -D warnings All-features clippy as a Makefile target: ``` -make linting-all +make lint ``` Lint a single crate: ``` -make linting-package PACKAGE= +make lint-package PACKAGE= ``` +Installing and running dylint: + +``` +make install-dylint +make lint-dylint +``` + + ## Testing Typical test run — uses the `testing` feature, includes unit and integration tests (some integration tests need Redis running locally): diff --git a/backward-compatibility/Makefile b/backward-compatibility/Makefile index e94dad30c8..326a95b7bf 100644 --- a/backward-compatibility/Makefile +++ b/backward-compatibility/Makefile @@ -11,7 +11,7 @@ check-git-lfs: pull-lfs-files: check-git-lfs git lfs pull -linting: +lint: RUSTFLAGS="-Aclippy::doc-lazy-continuation" cargo clippy --all-features -- -D warnings generate-data: check-duplicate @@ -19,4 +19,4 @@ generate-data: check-duplicate check-duplicate: cargo check - ./scripts/check_duplicate_tfhe_versions.sh \ No newline at end of file + ./scripts/check_duplicate_tfhe_versions.sh diff --git a/core/grpc/src/rpc_types.rs b/core/grpc/src/rpc_types.rs index d4b7ef03c0..ed779d812a 100644 --- a/core/grpc/src/rpc_types.rs +++ b/core/grpc/src/rpc_types.rs @@ -57,7 +57,7 @@ impl fmt::Display for KMSType { /// The format of what will be stored, and returned in gRPC, as a result of CRS generation in the KMS #[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, VersionsDispatch)] -pub enum SignedPubDataHandleInternalVersioned { +pub enum SignedPubDataHandleInternalVersions { V0(SignedPubDataHandleInternal), } @@ -67,7 +67,7 @@ pub enum SignedPubDataHandleInternalVersioned { /// It's needed because we are not able to derive versioned /// for the protobuf type. #[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Versionize)] -#[versionize(SignedPubDataHandleInternalVersioned)] +#[versionize(SignedPubDataHandleInternalVersions)] pub struct SignedPubDataHandleInternal { // Digest (the 256-bit hex-encoded value, computed using compute_info/handle) // This lower-case hex values without the 0x prefix. @@ -105,7 +105,7 @@ impl SignedPubDataHandleInternal { /// for more details. #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Version)] #[repr(transparent)] -pub struct CrsGenSignedPubDataHandleInternalWrapper(pub SignedPubDataHandleInternal); +pub struct CrsGenMetadataV0(pub SignedPubDataHandleInternal); // This function needs to use the non-wasm feature because tonic is not available in wasm builds. #[cfg(feature = "non-wasm")] @@ -190,7 +190,7 @@ pub fn alloy_to_protobuf_domain(domain: &Eip712Domain) -> anyhow::Result for CustodianRecoveryOutput { } #[derive(Clone, Serialize, Deserialize, VersionsDispatch)] -pub enum CustodianSetupMessagePayloadVersioned { +pub enum CustodianSetupMessagePayloadVersions { V0(CustodianSetupMessagePayload), } /// This is payload in the setup message that the custodian sends to the operators. #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize, Versionize)] -#[versionize(CustodianSetupMessagePayloadVersioned)] +#[versionize(CustodianSetupMessagePayloadVersions)] pub struct CustodianSetupMessagePayload { pub header: String, pub random_value: [u8; 32], @@ -109,7 +109,7 @@ impl Named for CustodianSetupMessagePayload { } #[derive(Clone, Serialize, Deserialize, VersionsDispatch)] -pub enum InternalCustodianSetupMessageVersioned { +pub enum InternalCustodianSetupMessageVersions { V0(InternalCustodianSetupMessage), } @@ -120,7 +120,7 @@ pub enum InternalCustodianSetupMessageVersioned { /// The operators need to persist this message in their storage /// so that they can run the backup procedure when needed. #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize, Versionize)] -#[versionize(InternalCustodianSetupMessageVersioned)] +#[versionize(InternalCustodianSetupMessageVersions)] pub struct InternalCustodianSetupMessage { pub header: String, pub custodian_role: Role, @@ -177,13 +177,13 @@ impl TryFrom for CustodianSetupMessage { } #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, VersionsDispatch)] -pub enum InternalCustodianContextVersioned { +pub enum InternalCustodianContextVersions { V0(InternalCustodianContext), } /// This is the internal representation of the custodian context. #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize, Versionize)] -#[versionize(InternalCustodianContextVersioned)] +#[versionize(InternalCustodianContextVersions)] pub struct InternalCustodianContext { /// The custodian threshold for recovery pub threshold: u32, @@ -284,19 +284,38 @@ impl Custodian { }) } + /// Obtain the operator ephemeral public key for reencryption, + /// unsigncrypt the signcryption encrypted under the custodian's public key + /// and then signcrypt it it under the operator's public key // We allow the following lints because we are fine with mutating the rng even if // we end up returning an error when signing the encrypted share. #[allow(unknown_lints)] #[allow(non_local_effect_before_error_return)] - /// Obtain the operator ephemeral public key for reencryption, - /// unsigncrypt the signcryption encrypted under the custodian's public key - /// and then signcrypt it it under the operator's public key pub fn verify_reencrypt( &self, rng: &mut R, backup: &InnerOperatorBackupOutput, operator_verification_key: &PublicSigKey, operator_ephem_enc_key: &UnifiedPublicEncKey, + ) -> Result { + self.verify_reencrypt_inner( + rng, + backup, + operator_verification_key, + operator_ephem_enc_key, + ) + } + + // Keep the body private so the Dylint public API pass does not exhaust its + // path-search work limit on this deliberately allowed pattern. + #[allow(unknown_lints)] + #[allow(non_local_effect_before_error_return)] + fn verify_reencrypt_inner( + &self, + rng: &mut R, + backup: &InnerOperatorBackupOutput, + operator_verification_key: &PublicSigKey, + operator_ephem_enc_key: &UnifiedPublicEncKey, ) -> Result { tracing::debug!( "Verifying and re-encrypting backup for operator: {}", diff --git a/core/service/src/backup/mod.rs b/core/service/src/backup/mod.rs index 4d720889b7..11e760e549 100644 --- a/core/service/src/backup/mod.rs +++ b/core/service/src/backup/mod.rs @@ -19,12 +19,12 @@ pub const KMS_CUSTODIAN: &str = "kms-custodian"; pub const SEED_PHRASE_DESC: &str = "The SECRET seed phrase for the custodian keys is: "; #[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, VersionsDispatch)] -pub enum BackupCiphertextVersioned { +pub enum BackupCiphertextVersions { V0(BackupCiphertext), } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Versionize)] -#[versionize(BackupCiphertextVersioned)] +#[versionize(BackupCiphertextVersions)] pub struct BackupCiphertext { pub ciphertext: UnifiedCipher, pub priv_data_type: PrivDataType, diff --git a/core/service/src/backup/operator.rs b/core/service/src/backup/operator.rs index 670bacecea..4218d3c59e 100644 --- a/core/service/src/backup/operator.rs +++ b/core/service/src/backup/operator.rs @@ -47,7 +47,7 @@ pub(crate) const DSEP_BACKUP_RECOVERY: DomainSep = *b"BKUPRECO"; const TIMESTAMP_VALIDATION_WINDOW_SECS: u64 = 24 * 3600; // 1 day #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, VersionsDispatch)] -pub enum InternalRecoveryRequestVersioned { +pub enum InternalRecoveryRequestVersions { V0(InternalRecoveryRequest), } @@ -61,7 +61,7 @@ impl Named for InternalRecoveryRequest { /// This is because we have to assume that the operator has no access to the private storage /// when creating this object. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Versionize)] -#[versionize(InternalRecoveryRequestVersioned)] +#[versionize(InternalRecoveryRequestVersions)] pub struct InternalRecoveryRequest { ephem_op_enc_key: UnifiedPublicEncKey, cts: BTreeMap, @@ -165,7 +165,7 @@ impl std::fmt::Debug for Operator { } #[derive(Clone, Serialize, Deserialize, VersionsDispatch)] -pub enum InnerOperatorBackupOutputVersioned { +pub enum InnerOperatorBackupOutputVersions { V0(InnerOperatorBackupOutput), } @@ -173,7 +173,7 @@ pub enum InnerOperatorBackupOutputVersioned { /// This data needs to be persisted on some public storage so that /// new operators can download and recover. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Versionize)] -#[versionize(InnerOperatorBackupOutputVersioned)] +#[versionize(InnerOperatorBackupOutputVersions)] pub struct InnerOperatorBackupOutput { pub signcryption: UnifiedSigncryption, } @@ -232,7 +232,7 @@ fn verify_n_t(n: usize, t: usize) -> Result<(), BackupError> { } #[derive(Clone, Serialize, Deserialize, VersionsDispatch)] -pub enum RecoveryValidationMaterialVersioned { +pub enum RecoveryValidationMaterialVersions { V0(RecoveryValidationMaterial), } @@ -242,7 +242,7 @@ pub enum RecoveryValidationMaterialVersioned { /// Furthermore, the data is signed by the operator to allow it to verify the /// data upon load. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Versionize)] -#[versionize(RecoveryValidationMaterialVersioned)] +#[versionize(RecoveryValidationMaterialVersions)] pub struct RecoveryValidationMaterial { pub(crate) payload: RecoveryValidationMaterialPayload, signature: Vec, @@ -355,11 +355,11 @@ impl RecoveryValidationMaterial { } #[derive(Clone, Serialize, Deserialize, VersionsDispatch)] -pub enum RecoveryValidationMaterialPayloadVersioned { +pub enum RecoveryValidationMaterialPayloadVersions { V0(RecoveryValidationMaterialPayload), } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Versionize)] -#[versionize(RecoveryValidationMaterialPayloadVersioned)] +#[versionize(RecoveryValidationMaterialPayloadVersions)] pub struct RecoveryValidationMaterialPayload { /// The signcrypted shares of the operators' private backup decryption key towards each custodian. /// I.e. the key to the map is the role of the custodian. @@ -376,12 +376,12 @@ impl Named for RecoveryValidationMaterialPayload { } #[derive(Clone, Serialize, Deserialize, VersionsDispatch)] -pub enum BackupMaterialVersioned { +pub enum BackupMaterialVersions { V0(BackupMaterial), } #[derive(Clone, Debug, Serialize, Deserialize, Versionize)] -#[versionize(BackupMaterialVersioned)] +#[versionize(BackupMaterialVersions)] pub struct BackupMaterial { /// The custodian context this backup is associated with. pub backup_id: RequestId, diff --git a/core/service/src/cryptography/encryption.rs b/core/service/src/cryptography/encryption.rs index 23f2774a28..3ba20928d9 100644 --- a/core/service/src/cryptography/encryption.rs +++ b/core/service/src/cryptography/encryption.rs @@ -18,12 +18,12 @@ use tfhe_versionable::VersionsDispatch; use zeroize::{Zeroize, ZeroizeOnDrop}; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, VersionsDispatch)] -pub enum UnifiedPublicEncKeyVersioned { +pub enum UnifiedPublicEncKeyVersions { V0(UnifiedPublicEncKey), } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Versionize)] -#[versionize(UnifiedPublicEncKeyVersioned)] +#[versionize(UnifiedPublicEncKeyVersions)] #[expect(clippy::large_enum_variant)] pub enum UnifiedPublicEncKey { MlKem512(PublicEncKey), @@ -224,7 +224,7 @@ impl Encrypt for UnifiedPublicEncKey { #[derive( Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Zeroize, ZeroizeOnDrop, VersionsDispatch, )] -pub enum UnifiedPrivateEncKeyVersioned { +pub enum UnifiedPrivateEncKeyVersions { V0(UnifiedPrivateEncKey), } @@ -234,7 +234,7 @@ pub enum UnifiedPrivateEncKeyVersioned { /// - Scope: Lifetime of a backup (i.e. lifetime of a custodian context), but local to client application #[derive(Clone, Debug, Serialize, Deserialize, Zeroize, Versionize)] #[expect(clippy::large_enum_variant)] -#[versionize(UnifiedPrivateEncKeyVersioned)] +#[versionize(UnifiedPrivateEncKeyVersions)] pub enum UnifiedPrivateEncKey { MlKem512(PrivateEncKey), MlKem1024(PrivateEncKey), @@ -442,12 +442,12 @@ pub trait HasPkeScheme { } #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize, VersionsDispatch)] -pub enum PkeSchemeTypeVersioned { +pub enum PkeSchemeTypeVersions { V0(PkeSchemeType), } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Display, Versionize)] -#[versionize(PkeSchemeTypeVersioned)] +#[versionize(PkeSchemeTypeVersions)] pub enum PkeSchemeType { MlKem512, #[deprecated( @@ -522,12 +522,12 @@ impl<'a, R: CryptoRng + RngCore + Send + Sync> PkeScheme for Encryption<'a, R> { } #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, VersionsDispatch)] -pub enum UnifiedCipherVersioned { +pub enum UnifiedCipherVersions { V0(UnifiedCipher), } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Versionize)] -#[versionize(UnifiedCipherVersioned)] +#[versionize(UnifiedCipherVersions)] pub struct UnifiedCipher { pub cipher: HybridKemCt, pub pke_type: PkeSchemeType, diff --git a/core/service/src/cryptography/hybrid_ml_kem.rs b/core/service/src/cryptography/hybrid_ml_kem.rs index 60bd5a733a..c387649a52 100644 --- a/core/service/src/cryptography/hybrid_ml_kem.rs +++ b/core/service/src/cryptography/hybrid_ml_kem.rs @@ -32,7 +32,7 @@ struct InnerHybridKemCt { } #[derive(Clone, Eq, PartialEq, Serialize, Deserialize, VersionsDispatch)] -pub enum HybridKemCtVersioned { +pub enum HybridKemCtVersions { V0(HybridKemCt), } @@ -41,7 +41,7 @@ pub enum HybridKemCtVersioned { // larger than 32. So we have this [HybridKemCt] type where // [kem_ct] is a Vec. #[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Versionize)] -#[versionize(HybridKemCtVersioned)] +#[versionize(HybridKemCtVersions)] // WARNING: This type is currently using a legacy approach to serialization using bincode. When updating please also update the serialization to safe serialization // In connection with this the trait `LegacySerialization` must also be implemented and used! pub struct HybridKemCt { diff --git a/core/service/src/cryptography/signatures.rs b/core/service/src/cryptography/signatures.rs index 072873020e..cdd7a9a29b 100644 --- a/core/service/src/cryptography/signatures.rs +++ b/core/service/src/cryptography/signatures.rs @@ -27,12 +27,12 @@ pub trait HasSigningScheme { } #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize, VersionsDispatch)] -pub enum SigningSchemeTypeVersioned { +pub enum SigningSchemeTypeVersions { V0(SigningSchemeType), } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Display, Versionize)] -#[versionize(SigningSchemeTypeVersioned)] +#[versionize(SigningSchemeTypeVersions)] pub enum SigningSchemeType { Ecdsa256k1, // Eventually we will support post quantum signatures as well @@ -62,14 +62,14 @@ impl TryFrom for SigningSchemeType { } #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize, VersionsDispatch)] -pub enum PublicSigKeyVersioned { +pub enum PublicSigKeyVersions { V0(PublicSigKey), } // Struct wrapping signature verification key used by both the user's wallet and server #[wasm_bindgen] #[derive(Clone, PartialEq, Eq, Debug, Hash, Serialize, Deserialize, Versionize)] -#[versionize(PublicSigKeyVersioned)] +#[versionize(PublicSigKeyVersions)] pub struct PublicSigKey { pk: WrappedVerifyingKey, } @@ -206,7 +206,7 @@ impl Visitor<'_> for PublicSigKeyVisitor { } // Drop manually implemented due to conflict with Versionize macro #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize, Zeroize, VersionsDispatch)] -pub enum PrivateSigKeyVersioned { +pub enum PrivateSigKeyVersions { V0(PrivateSigKey), } // TODO(#2781) should eventually be replaced or consolidated with the UnifiedPrivateSigningKey @@ -214,7 +214,7 @@ pub enum PrivateSigKeyVersioned { // messages to one another #[wasm_bindgen] #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize, Zeroize, Versionize)] -#[versionize(PrivateSigKeyVersioned)] +#[versionize(PrivateSigKeyVersions)] pub struct PrivateSigKey { sk: WrappedSigningKey, } diff --git a/core/service/src/cryptography/signcryption.rs b/core/service/src/cryptography/signcryption.rs index b762c64be8..d266efafb9 100644 --- a/core/service/src/cryptography/signcryption.rs +++ b/core/service/src/cryptography/signcryption.rs @@ -95,12 +95,12 @@ pub trait UnsigncryptFHEPlaintext: Unsigncrypt { #[derive( Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Zeroize, ZeroizeOnDrop, VersionsDispatch, )] -pub enum UnifiedSigncryptionKeyOwnedVersioned { +pub enum UnifiedSigncryptionKeyOwnedVersions { V0(UnifiedSigncryptionKeyOwned), } #[derive(Clone, Eq, PartialEq, Serialize, Deserialize, Debug, Zeroize, Versionize)] -#[versionize(UnifiedSigncryptionKeyOwnedVersioned)] +#[versionize(UnifiedSigncryptionKeyOwnedVersions)] pub struct UnifiedSigncryptionKeyOwned { pub signing_key: PrivateSigKey, pub receiver_enc_key: UnifiedPublicEncKey, @@ -216,12 +216,12 @@ impl HasSigningScheme for UnifiedUnsigncryptionKey<'_> { #[derive( Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Zeroize, ZeroizeOnDrop, VersionsDispatch, )] -pub enum UnifiedUnsigncryptionKeyOwnedVersioned { +pub enum UnifiedUnsigncryptionKeyOwnedVersions { V0(UnifiedUnsigncryptionKeyOwned), } #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Versionize)] -#[versionize(UnifiedUnsigncryptionKeyOwnedVersioned)] +#[versionize(UnifiedUnsigncryptionKeyOwnedVersions)] pub struct UnifiedUnsigncryptionKeyOwned { pub decryption_key: UnifiedPrivateEncKey, pub encryption_key: UnifiedPublicEncKey, // Needed for validation of the signcrypted payload @@ -275,12 +275,12 @@ impl HasSigningScheme for UnifiedUnsigncryptionKeyOwned { } #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize, VersionsDispatch)] -pub enum UnifiedSigncryptionVersioned { +pub enum UnifiedSigncryptionVersions { V0(UnifiedSigncryption), } #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug, Versionize)] -#[versionize(UnifiedSigncryptionVersioned)] +#[versionize(UnifiedSigncryptionVersions)] pub struct UnifiedSigncryption { pub payload: Vec, pub pke_type: PkeSchemeType, @@ -297,7 +297,7 @@ impl UnifiedSigncryption { } #[derive(Clone, Serialize, Deserialize, Hash, PartialEq, Eq, Debug, VersionsDispatch)] -pub enum SigncryptionPayloadVersioned { +pub enum SigncryptionPayloadVersions { V0(SigncryptionPayload), } @@ -350,7 +350,7 @@ pub enum SigncryptionPayloadVersioned { /// - Both tests MUST pass before any changes to this type #[derive(Clone, Serialize, Deserialize, Hash, PartialEq, Eq, Debug, Versionize)] -#[versionize(SigncryptionPayloadVersioned)] +#[versionize(SigncryptionPayloadVersions)] pub struct SigncryptionPayload { pub plaintext: TypedPlaintext, pub link: Vec, diff --git a/core/service/src/engine/base.rs b/core/service/src/engine/base.rs index 90b26983d7..96bbb5e68f 100644 --- a/core/service/src/engine/base.rs +++ b/core/service/src/engine/base.rs @@ -22,7 +22,7 @@ use kms_grpc::RequestId; use kms_grpc::kms::v1::{ CiphertextFormat, FheParameter, TypedPlaintext, UserDecryptionResponsePayload, }; -use kms_grpc::rpc_types::CrsGenSignedPubDataHandleInternalWrapper; +use kms_grpc::rpc_types::CrsGenMetadataV0; use kms_grpc::rpc_types::KMSType; use kms_grpc::rpc_types::PubDataType; use kms_grpc::rpc_types::SignedPubDataHandleInternal; @@ -78,7 +78,7 @@ pub static INSECURE_PREPROCESSING_ID: LazyLock = LazyLock::new(|| crate::engine::base::derive_request_id("INSECURE_PREPROCESSING_ID").unwrap()); #[derive(Clone, Serialize, Deserialize, VersionsDispatch)] -pub enum KmsFheKeyHandlesVersioned { +pub enum KmsFheKeyHandlesVersions { V0(KmsFheKeyHandlesV0), V1(KmsFheKeyHandles), } @@ -99,7 +99,7 @@ impl Upgrade for KmsFheKeyHandlesV0 { /// This structure securely holds sensitive key material used by the KMS, /// including the client key, optional decompression key, and public key metadata. #[derive(Clone, Serialize, Deserialize, Versionize)] -#[versionize(KmsFheKeyHandlesVersioned)] +#[versionize(KmsFheKeyHandlesVersions)] pub struct KmsFheKeyHandles { /// Client's private key for FHE operations pub client_key: FhePrivateKey, @@ -939,14 +939,14 @@ pub(crate) fn retrieve_parameters(fhe_parameter: Option) -> Result, } -impl Upgrade for KeyGenMetadataInnerQ126 { +impl Upgrade for KeyGenMetadataInnerV0 { type Error = std::convert::Infallible; fn upgrade(self) -> Result { @@ -992,8 +992,9 @@ impl Upgrade for KeyGenMetadataInnerV1 { } } +/// Previously called KeyGenMetadataInnerQ126 - quater 1, 2026 #[derive(Clone, Serialize, Deserialize, Version)] -pub struct KeyGenMetadataInnerQ126 { +pub struct KeyGenMetadataInnerV0 { pub key_id: RequestId, pub preprocessing_id: RequestId, pub key_digest_map: HashMap>, @@ -1001,13 +1002,13 @@ pub struct KeyGenMetadataInnerQ126 { } #[derive(Clone, Serialize, Deserialize, VersionsDispatch)] -pub enum KeyGenMetadataVersioned { +pub enum KeyGenMetadataVersions { V0(KeyGenMetadata), } // Values that need to be stored temporarily as part of an async key generation call. #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Versionize)] -#[versionize(KeyGenMetadataVersioned)] +#[versionize(KeyGenMetadataVersions)] pub enum KeyGenMetadata { Current(KeyGenMetadataInner), LegacyV0(HashMap), @@ -1064,13 +1065,13 @@ impl KeyGenMetadata { } #[derive(Clone, Serialize, Deserialize, VersionsDispatch)] -pub enum CrsGenMetadataInnerVersioned { - V0(CrsGenMetadataInnerQ126), +pub enum CrsGenMetadataInnerVersions { + V0(CrsGenMetadataInnerV0), V1(CrsGenMetadataInner), } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Versionize)] -#[versionize(CrsGenMetadataInnerVersioned)] +#[versionize(CrsGenMetadataInnerVersions)] pub struct CrsGenMetadataInner { pub(crate) crs_id: RequestId, pub(crate) crs_digest: Vec, @@ -1079,7 +1080,7 @@ pub struct CrsGenMetadataInner { pub(crate) external_signature: Vec, } -impl Upgrade for CrsGenMetadataInnerQ126 { +impl Upgrade for CrsGenMetadataInnerV0 { type Error = std::convert::Infallible; fn upgrade(self) -> Result { @@ -1094,7 +1095,7 @@ impl Upgrade for CrsGenMetadataInnerQ126 { } #[derive(Clone, Serialize, Deserialize, Version)] -pub struct CrsGenMetadataInnerQ126 { +pub struct CrsGenMetadataInnerV0 { pub crs_id: RequestId, pub crs_digest: Vec, pub max_num_bits: u32, @@ -1102,19 +1103,19 @@ pub struct CrsGenMetadataInnerQ126 { } #[derive(Clone, Serialize, Deserialize, VersionsDispatch)] -pub enum CrsGenMetadataVersioned { - V0(CrsGenSignedPubDataHandleInternalWrapper), +pub enum CrsGenMetadataVersions { + V0(CrsGenMetadataV0), V1(CrsGenMetadata), } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Versionize)] -#[versionize(CrsGenMetadataVersioned)] +#[versionize(CrsGenMetadataVersions)] pub enum CrsGenMetadata { Current(CrsGenMetadataInner), LegacyV0(SignedPubDataHandleInternal), } -impl Upgrade for CrsGenSignedPubDataHandleInternalWrapper { +impl Upgrade for CrsGenMetadataV0 { type Error = std::convert::Infallible; fn upgrade(self) -> Result { Ok(CrsGenMetadata::LegacyV0(self.0)) @@ -1176,7 +1177,7 @@ pub type UserDecryptCallValues = (UserDecryptionResponsePayload, Vec, Vec, pub context_id: ContextId, diff --git a/core/service/src/engine/threshold/service/kms_impl.rs b/core/service/src/engine/threshold/service/kms_impl.rs index 6811ec231b..739e806c59 100644 --- a/core/service/src/engine/threshold/service/kms_impl.rs +++ b/core/service/src/engine/threshold/service/kms_impl.rs @@ -109,7 +109,7 @@ use super::{crs_generator::RealInsecureCrsGenerator, key_generator::RealInsecure /// Versioned envelope for PublicKeyMaterial. /// V0 is the fat variant (with decompressed keys), V1 is the slim variant. #[derive(Clone, Serialize, Deserialize, VersionsDispatch)] -pub enum PublicKeyMaterialVersioned { +pub enum PublicKeyMaterialVersions { V0(PublicKeyMaterialV0), V1(PublicKeyMaterial), } @@ -133,7 +133,7 @@ pub enum PublicKeyMaterialV0 { /// Enum to hold either compressed or uncompressed public key material. /// This allows a single [`ThresholdFheKeys`] type to support both modes. #[derive(Clone, Serialize, Deserialize, Versionize)] -#[versionize(PublicKeyMaterialVersioned)] +#[versionize(PublicKeyMaterialVersions)] pub enum PublicKeyMaterial { Uncompressed { integer_server_key: Arc, @@ -198,7 +198,7 @@ struct UncompressedKeys { } #[derive(Clone, Serialize, Deserialize, VersionsDispatch)] -pub enum ThresholdFheKeysVersioned { +pub enum ThresholdFheKeysVersions { V0(ThresholdFheKeysV0), V1(ThresholdFheKeysV1), V2(ThresholdFheKeysV2), @@ -209,7 +209,7 @@ pub enum ThresholdFheKeysVersioned { /// These are the internal key materials (public and private) /// needed for decryption, user decryption and verifying a proven input. #[derive(Clone, Serialize, Deserialize, Versionize)] -#[versionize(ThresholdFheKeysVersioned)] +#[versionize(ThresholdFheKeysVersions)] pub struct ThresholdFheKeys { pub private_keys: Arc>, pub public_material: PublicKeyMaterial, @@ -223,7 +223,7 @@ pub struct ThresholdFheKeys { /// V2: Unified key storage supporting both compressed and uncompressed keys. /// Note: the field type is `PublicKeyMaterial` (the latest version), not a frozen V2-era copy. /// This is a consequence of `Versionize`: nested fields are serialized via their current dispatch -/// type, so current code reads old nested `PublicKeyMaterialVersioned::V0` values by upgrading +/// type, so current code reads old nested `PublicKeyMaterialVersions::V0` values by upgrading /// them during unversionizing, but cannot itself re-emit that old nested shape. #[derive(Clone, Serialize, Deserialize, Version)] pub struct ThresholdFheKeysV2 { @@ -916,12 +916,12 @@ mod tests { use super::*; #[derive(Clone, Serialize, Deserialize, VersionsDispatch)] - pub enum PublicKeyMaterialVersioned { + pub enum PublicKeyMaterialVersions { V0(PublicKeyMaterial), } #[derive(Clone, Serialize, Deserialize, Versionize)] - #[versionize(PublicKeyMaterialVersioned)] + #[versionize(PublicKeyMaterialVersions)] pub enum PublicKeyMaterial { Uncompressed { integer_server_key: Arc, @@ -959,14 +959,14 @@ mod tests { } #[derive(Clone, Serialize, Deserialize, VersionsDispatch)] - pub enum ThresholdFheKeysVersioned { + pub enum ThresholdFheKeysVersions { V0(PlaceholderV0), V1(PlaceholderV1), V2(ThresholdFheKeys), } #[derive(Clone, Serialize, Deserialize, Versionize)] - #[versionize(ThresholdFheKeysVersioned)] + #[versionize(ThresholdFheKeysVersions)] pub struct ThresholdFheKeys { pub private_keys: Arc< PrivateKeySet< diff --git a/core/service/src/engine/threshold/service/session.rs b/core/service/src/engine/threshold/service/session.rs index 5c62b90c62..105efbe7c4 100644 --- a/core/service/src/engine/threshold/service/session.rs +++ b/core/service/src/engine/threshold/service/session.rs @@ -56,13 +56,13 @@ struct Context { } #[derive(Debug, Clone, Serialize, Deserialize, VersionsDispatch)] -pub enum PRSSSetupCombinedVersioned { +pub enum PRSSSetupCombinedVersions { V0(PRSSSetupCombined), } /// Public because it's used by storage. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Versionize)] -#[versionize(PRSSSetupCombinedVersioned)] +#[versionize(PRSSSetupCombinedVersions)] pub struct PRSSSetupCombined { pub prss_setup_z64: PRSSSetup, pub prss_setup_z128: PRSSSetup, diff --git a/core/service/src/vault/keychain/mod.rs b/core/service/src/vault/keychain/mod.rs index 3f1ec8da39..130b4efcf5 100644 --- a/core/service/src/vault/keychain/mod.rs +++ b/core/service/src/vault/keychain/mod.rs @@ -22,13 +22,13 @@ pub mod awskms; pub mod secretsharing; #[derive(Serialize, Deserialize, VersionsDispatch)] -pub enum AppKeyBlobVersioned { +pub enum AppKeyBlobVersions { V0(AppKeyBlob), } /// Container type for encrypted application keys (such as FHE private keys) #[derive(Serialize, Deserialize, Versionize, PartialEq, Debug, Clone)] -#[versionize(AppKeyBlobVersioned)] +#[versionize(AppKeyBlobVersions)] pub struct AppKeyBlob { pub root_key_id: String, pub data_key_blob: Vec, diff --git a/core/service/src/vault/storage/mod.rs b/core/service/src/vault/storage/mod.rs index a38f947bf1..021d5f17a7 100644 --- a/core/service/src/vault/storage/mod.rs +++ b/core/service/src/vault/storage/mod.rs @@ -646,7 +646,7 @@ pub mod tests { use tfhe_versionable::VersionsDispatch; #[derive(Serialize, Deserialize, Eq, PartialEq, Debug, VersionsDispatch)] - pub enum TestTypeVersioned { + pub enum TestTypeVersions { V0(TestType), } @@ -655,7 +655,7 @@ pub mod tests { } #[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Versionize)] - #[versionize(TestTypeVersioned)] + #[versionize(TestTypeVersions)] pub struct TestType { pub i: u32, } diff --git a/core/service/tests/versioned_enum_coverage.rs b/core/service/tests/versioned_enum_coverage.rs index 4530d96ef0..4d637e36aa 100644 --- a/core/service/tests/versioned_enum_coverage.rs +++ b/core/service/tests/versioned_enum_coverage.rs @@ -2,7 +2,7 @@ //! best-effort solution, not a guarantee there are no coverage gaps if the //! tests here pass! //! -//! Adding a new versionable type requires (a) a `*Versioned` dispatch enum +//! Adding a new versionable type requires (a) a `*Versions` dispatch enum //! with contiguous `V0..Vn` variants, and (b) at least one `.ron` fixture //! entry under `backward-compatibility/data/`. @@ -19,7 +19,7 @@ use syn::{Attribute, Item, Path as SynPath}; /// One `#[derive(VersionsDispatch)]` enum discovered during the workspace scan. /// /// Carries just enough information to drive the two coverage checks: -/// `enum_name` (e.g. `FooVersioned`) is stripped of its `Versioned` suffix to +/// `enum_name` (e.g. `FooVersions`) is stripped of its dispatch suffix to /// match against `.ron` fixture entries; `variants` is inspected for the /// `V0..Vn` contiguity rule; `file` is reported back in error messages so the /// offending source location is obvious. @@ -30,6 +30,13 @@ struct Dispatch { file: PathBuf, } +fn dispatch_underlying_type_name(enum_name: &str) -> String { + enum_name + .strip_suffix("Versions") + .unwrap_or(enum_name) + .to_string() +} + /// Types we deliberately don't require a direct `.ron` fixture for, because /// they are transitively exercised as fields of a root type that *does* have /// a fixture. @@ -286,7 +293,7 @@ fn versioned_enums_are_covered_by_ron_metadata() { // smooth the casing of the underlying Rust type (`PRSSSetupCombined`). // `TestMetadata*` derive `strum::Display`, which renders an enum value as // just its variant name — exactly what we need to match against - // `*Versioned` dispatch enums. + // `*Versions` dispatch enums. let data_dir = root.join("backward-compatibility/data"); let mut covered: BTreeSet = BTreeSet::new(); covered.extend(load_covered_names::( @@ -302,7 +309,7 @@ fn versioned_enums_are_covered_by_ron_metadata() { let mut missing: Vec<(String, PathBuf)> = Vec::new(); let mut seen: BTreeSet = BTreeSet::new(); for d in &dispatches { - let underlying = d.enum_name.trim_end_matches("Versioned").to_string(); + let underlying = dispatch_underlying_type_name(&d.enum_name); if !seen.insert(underlying.clone()) { continue; } @@ -430,9 +437,15 @@ fn derives_versions_dispatch_corner_cases() { assert!(!derives_versions_dispatch(&[attr])); // Non-derive attributes are ignored entirely. - let attr: Attribute = syn::parse_quote!(#[versionize(FooVersioned)]); + let attr: Attribute = syn::parse_quote!(#[versionize(FooVersions)]); assert!(!derives_versions_dispatch(&[attr])); // No attributes at all. assert!(!derives_versions_dispatch(&[])); } + +#[test] +fn dispatch_underlying_type_name_handles_dispatch_suffix() { + assert_eq!(dispatch_underlying_type_name("FooVersions"), "Foo"); + assert_eq!(dispatch_underlying_type_name("Foo"), "Foo"); +} diff --git a/core/threshold-algebra/src/galois_rings/common.rs b/core/threshold-algebra/src/galois_rings/common.rs index 4f893428d5..8e52f8cf69 100644 --- a/core/threshold-algebra/src/galois_rings/common.rs +++ b/core/threshold-algebra/src/galois_rings/common.rs @@ -44,7 +44,7 @@ use zeroize::Zeroize; /// /// This is also the 'value' of a single ShamirShare. #[derive(Clone, Copy, PartialEq, Hash, Eq, Debug, Zeroize, Versionize)] -#[versionize(ResiduePolyVersioned)] +#[versionize(ResiduePolyVersions)] pub struct ResiduePoly { pub coefs: [Z; EXTENSION_DEGREE], } @@ -88,7 +88,7 @@ impl<'a, Z: Deserialize<'a>, const EXTENSION_DEGREE: usize> Deserialize<'a> } #[derive(Serialize, Deserialize, Clone, VersionsDispatch)] -pub enum ResiduePolyVersioned { +pub enum ResiduePolyVersions { V0(ResiduePoly), } diff --git a/core/threshold-algebra/src/role.rs b/core/threshold-algebra/src/role.rs index a377997815..ab6bdb35cf 100644 --- a/core/threshold-algebra/src/role.rs +++ b/core/threshold-algebra/src/role.rs @@ -90,7 +90,7 @@ impl TwoSetsRole { Zeroize, tfhe_versionable::Versionize, )] -#[versionize(RoleVersioned)] +#[versionize(RoleVersions)] /// This defines the role of a party in the distributed system. /// Role are stored as 1-based indices, meaning that the first party has role 1, the second party has role 2, and so on. /// However, when used to do direct indexing into a vector, it is converted to a 0-based index. @@ -99,7 +99,7 @@ impl TwoSetsRole { pub struct Role(u64); #[derive(Clone, Serialize, Deserialize, tfhe_versionable::VersionsDispatch)] -pub enum RoleVersioned { +pub enum RoleVersions { V0(Role), } diff --git a/core/threshold-algebra/src/sharing/share.rs b/core/threshold-algebra/src/sharing/share.rs index 42b61c33f9..4d28f02267 100644 --- a/core/threshold-algebra/src/sharing/share.rs +++ b/core/threshold-algebra/src/sharing/share.rs @@ -9,13 +9,13 @@ use threshold_types::role::Role; use super::super::structure_traits::Ring; #[derive(Clone, Serialize, Deserialize, VersionsDispatch)] -pub enum ShareVersioned { +pub enum ShareVersions { V0(Share), } /// Generic structure for shares with non-interactive methods possible to carry out on shares. #[derive(Clone, Debug, Hash, PartialEq, Eq, Copy, Serialize, Deserialize, Zeroize, Versionize)] -#[versionize(ShareVersioned)] +#[versionize(ShareVersions)] pub struct Share { value: Z, owner: Role, diff --git a/core/threshold-execution/src/small_execution/prf.rs b/core/threshold-execution/src/small_execution/prf.rs index ad5ecb03cd..e838feacd3 100644 --- a/core/threshold-execution/src/small_execution/prf.rs +++ b/core/threshold-execution/src/small_execution/prf.rs @@ -12,13 +12,13 @@ use threshold_types::commitment::KEY_BYTE_LEN; use threshold_types::session_id::SessionId; #[derive(Clone, Serialize, Deserialize, VersionsDispatch)] -pub enum PrfKeyVersioned { +pub enum PrfKeyVersions { V0(PrfKey), } /// key for the PRF #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Hash, Eq, Versionize)] -#[versionize(PrfKeyVersioned)] +#[versionize(PrfKeyVersions)] pub struct PrfKey(pub [u8; 16]); /// helper function that compute bit-wise xor of two byte arrays in place (overwriting the first argument `arr1`) diff --git a/core/threshold-execution/src/small_execution/prss.rs b/core/threshold-execution/src/small_execution/prss.rs index 2817c7c891..fa52b94c27 100644 --- a/core/threshold-execution/src/small_execution/prss.rs +++ b/core/threshold-execution/src/small_execution/prss.rs @@ -351,14 +351,14 @@ pub(crate) struct PrfAes { } #[derive(Debug, Clone, Serialize, Deserialize, VersionsDispatch)] -pub enum PrssSetVersioned { +pub enum PrssSetVersions { V0(PrssSetV0), V1(PrssSet), } /// structure for holding values for each subset of n-t parties #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Versionize)] -#[versionize(PrssSetVersioned)] +#[versionize(PrssSetVersions)] pub struct PrssSet { parties: PartySet, set_key: PrfKey, @@ -428,14 +428,14 @@ type ValueVotes = HashMap, HashSet>; /// PRSS object that holds info in a certain epoch for a single party Pi #[derive(Debug, Clone, Serialize, Deserialize, VersionsDispatch)] -pub enum PRSSSetupVersioned { +pub enum PRSSSetupVersions { V0(PRSSSetup), } /// This struct is cheap to clone as it's made of Arc /// This is because it's cloned for every new session #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Versionize)] -#[versionize(PRSSSetupVersioned)] +#[versionize(PRSSSetupVersions)] pub struct PRSSSetup { // all possible subsets of n-t parties (A) that contain Pi and their shared PRF keys pub(crate) sets: Arc>>, diff --git a/core/threshold-execution/src/tfhe_internals/compression_decompression_key.rs b/core/threshold-execution/src/tfhe_internals/compression_decompression_key.rs index c4101e79b5..68ef17af50 100644 --- a/core/threshold-execution/src/tfhe_internals/compression_decompression_key.rs +++ b/core/threshold-execution/src/tfhe_internals/compression_decompression_key.rs @@ -17,14 +17,14 @@ use algebra::{ use super::{glwe_key::GlweSecretKeyShare, lwe_key::LweSecretKeyShare}; #[derive(Clone, Serialize, Deserialize, VersionsDispatch)] -pub enum CompressionPrivateKeySharesVersioned { +pub enum CompressionPrivateKeySharesVersions { V0(CompressionPrivateKeyShares), } ///Structure that holds a share of the LWE key /// - data contains shares of the key components #[derive(Clone, Debug, Serialize, Deserialize, Versionize, PartialEq)] -#[versionize(CompressionPrivateKeySharesVersioned)] +#[versionize(CompressionPrivateKeySharesVersions)] pub struct CompressionPrivateKeyShares { pub post_packing_ks_key: GlweSecretKeyShare, pub params: CompressionParameters, diff --git a/core/threshold-execution/src/tfhe_internals/glwe_key.rs b/core/threshold-execution/src/tfhe_internals/glwe_key.rs index b5acd8ae34..0d4cbbc342 100644 --- a/core/threshold-execution/src/tfhe_internals/glwe_key.rs +++ b/core/threshold-execution/src/tfhe_internals/glwe_key.rs @@ -20,7 +20,7 @@ use algebra::{ use super::lwe_key::LweSecretKeyShare; #[derive(Clone, Serialize, Deserialize, VersionsDispatch)] -pub enum GlweSecretKeyShareVersioned { +pub enum GlweSecretKeyShareVersions { V0(GlweSecretKeyShare), } @@ -30,7 +30,7 @@ pub enum GlweSecretKeyShareVersioned { /// shares are in the galois extension domain but the underlying secret is really a bit in the underlying [`BaseRing`] /// - polynomial_size is the total number of coefficients in the above polynomials #[derive(Clone, Debug, Serialize, Deserialize, Versionize, PartialEq)] -#[versionize(GlweSecretKeyShareVersioned)] +#[versionize(GlweSecretKeyShareVersions)] pub struct GlweSecretKeyShare { pub data: Vec>>, pub polynomial_size: PolynomialSize, diff --git a/core/threshold-execution/src/tfhe_internals/lwe_key.rs b/core/threshold-execution/src/tfhe_internals/lwe_key.rs index 1ca9165263..16fefb9c25 100644 --- a/core/threshold-execution/src/tfhe_internals/lwe_key.rs +++ b/core/threshold-execution/src/tfhe_internals/lwe_key.rs @@ -38,14 +38,14 @@ use super::{ }; #[derive(Clone, Serialize, Deserialize, VersionsDispatch)] -pub enum LweSecretKeyShareVersioned { +pub enum LweSecretKeyShareVersions { V0(LweSecretKeyShare), } ///Structure that holds a share of the LWE key /// - data contains shares of the key components #[derive(Clone, Debug, Serialize, Deserialize, Versionize, PartialEq)] -#[versionize(LweSecretKeyShareVersioned)] +#[versionize(LweSecretKeyShareVersions)] pub struct LweSecretKeyShare { pub data: Vec>>, } diff --git a/core/threshold-execution/src/tfhe_internals/private_keysets.rs b/core/threshold-execution/src/tfhe_internals/private_keysets.rs index ec8521667b..9c31db8048 100644 --- a/core/threshold-execution/src/tfhe_internals/private_keysets.rs +++ b/core/threshold-execution/src/tfhe_internals/private_keysets.rs @@ -33,7 +33,7 @@ pub(crate) struct GenericPrivateKeySet } #[derive(Clone, Debug, Serialize, Deserialize, VersionsDispatch)] -pub enum PrivateKeySetVersioned { +pub enum PrivateKeySetVersions { /// V0 is the original private key set V0(PrivateKeySetV0), // V1 is the same as V0 with the addition of glwe_sns_compression_key @@ -43,7 +43,7 @@ pub enum PrivateKeySetVersioned { } #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Versionize)] -#[versionize(PrivateKeySetVersioned)] +#[versionize(PrivateKeySetVersions)] /// The private key set structure holding the secret key shares for each party /// of the DKG. The keys can be either Z64 or Z128 depending on the DKG parameters. /// But all keys in the set are of the same type after a DKG. @@ -368,12 +368,12 @@ impl Upgrade> } #[derive(Clone, Debug, Serialize, Deserialize, VersionsDispatch)] -pub enum CompressionPrivateKeySharesEnumVersioned { +pub enum CompressionPrivateKeySharesEnumVersions { V0(CompressionPrivateKeySharesEnum), } #[derive(Clone, Debug, Serialize, Deserialize, Versionize, PartialEq)] -#[versionize(CompressionPrivateKeySharesEnumVersioned)] +#[versionize(CompressionPrivateKeySharesEnumVersions)] pub enum CompressionPrivateKeySharesEnum { Z64(CompressionPrivateKeyShares), Z128(CompressionPrivateKeyShares), @@ -431,12 +431,12 @@ impl CompressionPrivateKeySharesEnum { +pub enum LweSecretKeyShareEnumVersions { V0(LweSecretKeyShareEnum), } #[derive(Clone, Debug, Serialize, Deserialize, Versionize, PartialEq)] -#[versionize(LweSecretKeyShareEnumVersioned)] +#[versionize(LweSecretKeyShareEnumVersions)] pub enum LweSecretKeyShareEnum { Z64(LweSecretKeyShare), Z128(LweSecretKeyShare), @@ -511,12 +511,12 @@ impl LweSecretKeyShareEnum { } #[derive(Clone, Debug, Serialize, Deserialize, VersionsDispatch)] -pub enum GlweSecretKeyShareEnumVersioned { +pub enum GlweSecretKeyShareEnumVersions { V0(GlweSecretKeyShareEnum), } #[derive(Clone, Debug, Serialize, Deserialize, Versionize, PartialEq)] -#[versionize(GlweSecretKeyShareEnumVersioned)] +#[versionize(GlweSecretKeyShareEnumVersions)] pub enum GlweSecretKeyShareEnum { Z64(GlweSecretKeyShare), Z128(GlweSecretKeyShare), diff --git a/core/threshold-networking/src/tls.rs b/core/threshold-networking/src/tls.rs index b1a5271f7a..6776ade72b 100644 --- a/core/threshold-networking/src/tls.rs +++ b/core/threshold-networking/src/tls.rs @@ -30,7 +30,7 @@ use tokio_rustls::rustls::{ use x509_parser::{certificate::X509Certificate, parse_x509_certificate, pem::Pem}; #[derive(VersionsDispatch, Clone, Debug, Serialize, Deserialize)] -pub enum ReleasePCRValuesVersioned { +pub enum ReleasePCRValuesVersions { V0(ReleasePCRValues), } @@ -42,7 +42,7 @@ pub enum ReleasePCRValuesVersioned { /// WARNING: this may be printed for debugging and hence should NOT contain any secrets, such as private keys. /// If minor secrets needs to be added, then ensure fields are annotated with `#[serde(skip_serializing)]` to avoid accidentally diclosing them. #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Versionize, Hash, Eq)] -#[versionize(ReleasePCRValuesVersioned)] +#[versionize(ReleasePCRValuesVersions)] #[serde(deny_unknown_fields)] pub struct ReleasePCRValues { // EIF hash diff --git a/core/threshold-types/src/role.rs b/core/threshold-types/src/role.rs index a0d923138c..91f2edd56c 100644 --- a/core/threshold-types/src/role.rs +++ b/core/threshold-types/src/role.rs @@ -90,7 +90,7 @@ impl TwoSetsRole { Zeroize, tfhe_versionable::Versionize, )] -#[versionize(RoleVersioned)] +#[versionize(RoleVersions)] /// This defines the role of a party in the distributed system. /// Role are stored as 1-based indices, meaning that the first party has role 1, the second party has role 2, and so on. /// However, when used to do direct indexing into a vector, it is converted to a 0-based index. @@ -99,7 +99,7 @@ impl TwoSetsRole { pub struct Role(u64); #[derive(Clone, Serialize, Deserialize, tfhe_versionable::VersionsDispatch)] -pub enum RoleVersioned { +pub enum RoleVersions { V0(Role), } diff --git a/docs/developer/backward_compatibility.md b/docs/developer/backward_compatibility.md index 75d72073bb..4f0ecd13d3 100644 --- a/docs/developer/backward_compatibility.md +++ b/docs/developer/backward_compatibility.md @@ -328,7 +328,7 @@ impl TestedModule for KMS { A test at [`core/service/tests/versioned_enum_coverage.rs`](../../core/service/tests/versioned_enum_coverage.rs) runs as part of the `core/service` test suite, but its scan is workspace-wide: it uses `cargo metadata` to enumerate every workspace member and statically inspects each one for `#[derive(VersionsDispatch)]` enums, enforcing two invariants: 1. **Contiguous variants** — variants must be named `V0`, `V1`, `V2`, … in order. -2. **Fixture coverage** — every dispatch type (with its `Versioned` suffix stripped) must appear as a variant of one of the `TestMetadata*` enums backing `backward-compatibility/data/{kms,kms-grpc,threshold-fhe}.ron`, *or* be explicitly listed in the `ALLOW_UNCOVERED` constant in the same test file. +2. **Fixture coverage** — every dispatch type (with its `Versions` suffix stripped) must appear as a variant of one of the `TestMetadata*` enums backing `backward-compatibility/data/{kms,kms-grpc,threshold-fhe}.ron`, *or* be explicitly listed in the `ALLOW_UNCOVERED` constant in the same test file. The default expectation when you add a new `#[derive(VersionsDispatch)]` enum is to add a direct `.ron` fixture for it, as described in [Adding a test for a new type](#adding-a-test-for-a-new-type). `ALLOW_UNCOVERED` is for inner types that are only reachable as fields of a parent type that already has a fixture. @@ -418,11 +418,11 @@ The data is stored using git-lfs, so be sure to clone the kms-core repo with lfs When some breaking changes are added to a versionized type, you should update several things. Let's say that the type only had a `V0` version, then you should: -- add a new version `v1` to the `XXXVersioned` enum associated to the type `XXX` (ex: `PrivateSigKeyVersioned` for `PrivateSigKey`) +- add a new version `v1` to the `XXXVersions` enum associated to the type `XXX` (ex: `PrivateSigKeyVersions` for `PrivateSigKey`) - **keep** the `PrivateSigKey` old definition and rename it to `PrivateSigKeyV0` - replace the `Versionize` derive trait with the `Version` one (import if from `tfhe-versionable` if needed) -- remove the `#[versionize(XXXVersioned)]` attribute -- add your new `XXX` type (ex: `PrivateSigKey`) definition and add both the `Versionize` derive trait and the `#[versionize(XXXVersioned)]` attribute to it +- remove the `#[versionize(XXXVersions)]` attribute +- add your new `XXX` type (ex: `PrivateSigKey`) definition and add both the `Versionize` derive trait and the `#[versionize(XXXVersions)]` attribute to it - implement the `Upgrade` trait for the old definition (ex: `PrivateSigKeyV0`) It is important to understand that the old definition **must not** be changed whenever there's a breaking change. Also, only the latest definition should be annotated with both versionize macros. @@ -431,7 +431,7 @@ It should look like the following: ```rust #[derive(..., VersionsDispatch)] -pub enum PrivateSigKeyVersioned { +pub enum PrivateSigKeyVersions { V0(PrivateSigKeyV0), V1(PrivateSigKey), } @@ -444,7 +444,7 @@ pub struct PrivateSigKeyV0 { // New definition #[derive(..., Versionize)] -#[versionize(PrivateSigKeyVersioned)] +#[versionize(PrivateSigKeyVersions)] pub struct PrivateSigKey { // New definition } diff --git a/docs/developer/contributing.md b/docs/developer/contributing.md index 69e0a8f96d..866a72d7b5 100644 --- a/docs/developer/contributing.md +++ b/docs/developer/contributing.md @@ -38,15 +38,19 @@ git checkout -b feat/1337/new_feature_X Each commit to **TKMS** should conform to the standards of the project. In particular, every source code, docker or workflows file should be linted to prevent programmatic and stylistic errors. -- Rust source code linters: `cargo-fmt` and `clippy` +- Rust source code linters: `cargo-fmt`, `clippy`, and `dylint` To format the code and check for issues the following commands are used: ``` cargo fmt cargo clippy --all-targets --all-features -- -D warnings +make install-dylint +make lint-dylint ``` +`make lint-dylint` runs project-specific lints, including tfhe-rs lints loaded from the tfhe-rs tag matching the workspace `tfhe` dependency. Dylint warnings are errors, so reported warnings must be fixed or explicitly allowed. + ### 3.2 Testing Your contributions must include comprehensive documentation and tests without breaking existing tests. @@ -100,7 +104,7 @@ We have certain rules about dependencies and how we manage them, mostly related 1. *Never* update a version of a dependency as part of a regular PR. Such updates must be done in a separate PR. 2. Do not update a dependency unless the update is really needed because of new features, or to fix a bug we have encountered or to fix a known security issue. -3. Do not add new dependencies without previous discussion with the TKMS team. +3. Do not add new dependencies without previous discussion with the KMS team. ## 6. Merging diff --git a/docs/operations/advanced/common-errors.md b/docs/operations/advanced/common-errors.md index a428ffbbd6..d2f99aed1e 100644 --- a/docs/operations/advanced/common-errors.md +++ b/docs/operations/advanced/common-errors.md @@ -312,7 +312,7 @@ If there's an `missing field ` issue in ASC, for example when runnin It must match the proc macro above the enum variant. ```rust -#[versionize(OperationValueVersioned)] +#[versionize(OperationValueVersions)] pub enum OperationValue { #[strum(serialize = "verify_proven_ct")] #[serde(rename = "verify_proven_ct")] diff --git a/dylint.toml b/dylint.toml index 0297b0ecd4..8b6db065aa 100644 --- a/dylint.toml +++ b/dylint.toml @@ -1,8 +1,11 @@ [workspace.metadata.dylint] libraries = [ { git = "https://github.com/trailofbits/dylint", rev = "2c20d164e06c446de2cecadff0c55e16a877c006", pattern = "examples/general/non_local_effect_before_error_return" }, + # The nightly toolchain + components needed to build this library are read + # from `utils/tfhe-lints/rust-toolchain` in the tfhe-rs repo at the tag + # below, and auto-installed by rustup on first `cargo dylint --all` run. + { git = "https://github.com/zama-ai/tfhe-rs", tag = "tfhe-rs-1.6.1", pattern = "utils/tfhe-lints/lints" }, ] [non_local_effect_before_error_return] work_limit = 100000000 -