From 74d74f4037f8c210f623265c5b94d2f665bd1f66 Mon Sep 17 00:00:00 2001 From: Uncle Stretch Date: Fri, 9 Oct 2026 19:07:35 +0300 Subject: [PATCH] fix for https://ghostforum.org/t/cross-generation-dkg-package-replay-signed-payload-does-not-bind-dkg-index/105 Signed-off-by: Uncle Stretch --- pallets/exodus/Cargo.toml | 2 +- pallets/exodus/src/benchmarking.rs | 22 +++ pallets/exodus/src/lib.rs | 194 ++++++++++++++-------- pallets/exodus/src/types/local_storage.rs | 10 +- pallets/exodus/src/types/packages.rs | 17 +- 5 files changed, 173 insertions(+), 72 deletions(-) diff --git a/pallets/exodus/Cargo.toml b/pallets/exodus/Cargo.toml index 84549c7..e5d13ca 100644 --- a/pallets/exodus/Cargo.toml +++ b/pallets/exodus/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ghost-exodus" -version = "0.0.22" +version = "0.0.23" description = "Threshold signature generation with DKG included" license.workspace = true authors.workspace = true diff --git a/pallets/exodus/src/benchmarking.rs b/pallets/exodus/src/benchmarking.rs index 95ae153..4bf65a8 100644 --- a/pallets/exodus/src/benchmarking.rs +++ b/pallets/exodus/src/benchmarking.rs @@ -47,11 +47,13 @@ mod benchmarks { prepare_pallet::(1); dkg_state.next_phase(); + let dkg_index = dkg_state.get_dkg_index(); QualificationDkgState::::insert(&network_curve, dkg_state); let round0_package = PackageContext::default() .with_network_curve(NetworkCurve::Secp256k1) .with_authority_index(0) + .with_dkg_index(dkg_index) .with_dkg_round0(dummy_hash); let dkg_package = DkgPackage::Round0(round0_package); @@ -83,6 +85,7 @@ mod benchmarks { dkg_state.next_phase(); dkg_state.insert_index(authority_index); + let dkg_index = dkg_state.get_dkg_index(); QualificationDkgState::::insert(&network_curve, dkg_state); let mut rng = ChaCha20Rng::seed_from_u64(694201337); @@ -99,6 +102,7 @@ mod benchmarks { let round1_package = PackageContext::default() .with_network_curve(NetworkCurve::Secp256k1) .with_authority_index(0) + .with_dkg_index(dkg_index) .with_dkg_round1(public_package) .expect("Round1 package should be valid"); @@ -130,6 +134,8 @@ mod benchmarks { dkg_state.next_phase(); dkg_state.next_phase(); + let dkg_index = dkg_state.get_dkg_index(); + (0..max_signers).for_each(|i| { dkg_state.insert_index(i); }); @@ -164,6 +170,7 @@ mod benchmarks { let round2_package = PackageContext::default() .with_network_curve(NetworkCurve::Secp256k1) .with_authority_index(authority_index) + .with_dkg_index(dkg_index) .with_dkg_round2(encryption_bundle) .expect("Round2 package should be valid"); @@ -196,6 +203,8 @@ mod benchmarks { dkg_state.next_phase(); dkg_state.next_phase(); + let dkg_index = dkg_state.get_dkg_index(); + (0..max_signers).for_each(|i| { dkg_state.insert_index(i); }); @@ -216,6 +225,7 @@ mod benchmarks { let round3_package = PackageContext::default() .with_network_curve(NetworkCurve::Secp256k1) .with_authority_index(authority_index) + .with_dkg_index(dkg_index) .with_dkg_round3(accused_indexes) .expect("Round3 package should be valid"); @@ -252,6 +262,8 @@ mod benchmarks { dkg_state.next_phase(); dkg_state.next_phase(); + let dkg_index = dkg_state.get_dkg_index(); + (0..max_signers).for_each(|i| { dkg_state.insert_index(i); }); @@ -286,6 +298,7 @@ mod benchmarks { let round4_package = PackageContext::default() .with_network_curve(NetworkCurve::Secp256k1) .with_authority_index(authority_index) + .with_dkg_index(dkg_index) .with_dkg_round4(justification_bundle) .expect("Round4 package should be valid"); @@ -335,6 +348,7 @@ mod benchmarks { let round5_package = PackageContext::default() .with_network_curve(NetworkCurve::Secp256k1) .with_authority_index(authority_index) + .with_dkg_index(dkg_index) .with_dkg_round5(dummy_verifying_key.clone(), dummy_merkle_root) .expect("Round5 package should be valid"); @@ -437,6 +451,7 @@ mod benchmarks { let round6_package = PackageContext::default() .with_network_curve(NetworkCurve::Secp256k1) .with_authority_index(authority_index) + .with_dkg_index(dkg_index) .with_dkg_round6(dummy_verifying_share.clone(), dummy_merkle_proof) .expect("Round6 package should be valid"); @@ -506,6 +521,8 @@ mod benchmarks { let authorities = QualificationAuthorities::::get(&network_curve); let active_dkg: ActivatedState = (&dkg_state).into(); + let active_dkg_index = active_dkg.get_dkg_index(); + QualificationDkgState::::insert(&network_curve, dkg_state); ActiveDkgAuthorities::::insert(&network_curve, active_dkg); ActiveAuthorities::::insert(&network_curve, authorities); @@ -514,6 +531,7 @@ mod benchmarks { let nonce_package = PackageContext::default() .with_network_curve(NetworkCurve::Secp256k1) .with_authority_index(authority_index) + .with_dkg_index(active_dkg_index) .with_exodus_nonce_commitment( exodus_session, dummy_nonce.to_vec(), @@ -584,6 +602,8 @@ mod benchmarks { let authorities = QualificationAuthorities::::get(&network_curve); let active_dkg: ActivatedState = (&dkg_state).into(); + let active_dkg_index = active_dkg.get_dkg_index(); + QualificationDkgState::::insert(&network_curve, dkg_state); ActiveDkgAuthorities::::insert(&network_curve, active_dkg); ActiveAuthorities::::insert(&network_curve, authorities); @@ -600,6 +620,7 @@ mod benchmarks { let group_package = PackageContext::default() .with_network_curve(NetworkCurve::Secp256k1) .with_authority_index(authority_index) + .with_dkg_index(active_dkg_index) .with_exodus_group_commitment( exodus_session, dummy_group_commitment.clone(), @@ -766,6 +787,7 @@ mod benchmarks { let share_package = PackageContext::default() .with_network_curve(NetworkCurve::Secp256k1) .with_authority_index(authority_index) + .with_dkg_index(active_dkg_index) .with_exodus_signature_share( exodus_session, dummy_signature_share.clone(), diff --git a/pallets/exodus/src/lib.rs b/pallets/exodus/src/lib.rs index 863f897..f47df9d 100644 --- a/pallets/exodus/src/lib.rs +++ b/pallets/exodus/src/lib.rs @@ -502,11 +502,9 @@ pub mod pallet { InvalidMerkleProof, NetworkDoesNotExist, NoActiveAuthorities, - InvalidSignatureShare, VerifyingShareNotFound, BridgeQueueMinimumNotMet, DkgAuthoritiesInProgress, - PackagesAlreadyRegistered, DkgAuthoritiesNotInitialized, Round0PackageInvalidProof, @@ -519,7 +517,7 @@ pub mod pallet { Round2PackagesAlreadyRegistered, Round2PackagesWrongCoefficients, Round3PackageInvalidProof, - Round3PackagesAlreadyRegistere, + Round3PackagesAlreadyRegistered, Round4PackageInvalidProof, Round4PackagesAlreadyRegistered, Round5PackageInvalidProof, @@ -667,15 +665,6 @@ pub mod pallet { OptionQuery, >; - #[pallet::storage] - #[pallet::getter(fn exodus_activity)] - pub(super) type ExodusActivity = StorageMap< - _, - Twox64Concat, AuthIndex, - BlockNumberFor, - ValueQuery, - >; - #[pallet::storage] #[pallet::getter(fn round0_packages)] pub(super) type Round0Packages = StorageDoubleMap< @@ -910,8 +899,6 @@ pub mod pallet { Self::validate_round0_package_size(&dkg_package, &signature) .map_err(|_| Error::::Round0PackageInvalidProof)?; - Self::register_latest_activity(&dkg_package)?; - let DkgPackage::Round0(round0) = dkg_package else { return Err(Error::::Round0PackageInvalidProof.into()); }; @@ -968,8 +955,6 @@ pub mod pallet { Self::validate_round1_package_size(&dkg_package, &signature) .map_err(|_| Error::::Round1PackageInvalidProof)?; - Self::register_latest_activity(&dkg_package)?; - let DkgPackage::Round1(round1) = dkg_package else { return Err(Error::::Round1PackageInvalidProof.into()); }; @@ -1047,8 +1032,6 @@ pub mod pallet { Self::validate_round2_package_size(&dkg_package, &signature) .map_err(|_| Error::::Round2PackagesInvalidProof)?; - Self::register_latest_activity(&dkg_package)?; - let DkgPackage::Round2(round2_bundle) = dkg_package else { return Err(Error::::Round2PackagesInvalidProof.into()); }; @@ -1122,8 +1105,6 @@ pub mod pallet { Self::validate_round3_complaints_size(&dkg_package, &signature) .map_err(|_| Error::::Round3PackageInvalidProof)?; - Self::register_latest_activity(&dkg_package)?; - let DkgPackage::Round3(round3_complaints) = dkg_package else { return Err(Error::::Round3PackageInvalidProof.into()); }; @@ -1141,7 +1122,7 @@ pub mod pallet { |complaints| -> DispatchResult { ensure!( !complaints.contains_key(&authority_index), - Error::::Round3PackagesAlreadyRegistere, + Error::::Round3PackagesAlreadyRegistered, ); complaints.try_insert(authority_index, complaints_bitmap) @@ -1180,8 +1161,6 @@ pub mod pallet { Self::validate_round4_justifications_size(&dkg_package, &signature) .map_err(|_| Error::::Round4PackageInvalidProof)?; - Self::register_latest_activity(&dkg_package)?; - let DkgPackage::Round4(round4_bundle) = dkg_package else { return Err(Error::::Round4PackageInvalidProof.into()); }; @@ -1247,8 +1226,6 @@ pub mod pallet { Self::validate_round5_package_size(&dkg_package, &signature) .map_err(|_| Error::::Round5PackageInvalidProof)?; - Self::register_latest_activity(&dkg_package)?; - let DkgPackage::Round5(round5) = dkg_package else { return Err(Error::::Round5PackageInvalidProof.into()); }; @@ -1323,8 +1300,6 @@ pub mod pallet { Self::validate_round6_package_size(&dkg_package, &signature) .map_err(|_| Error::::Round6PackageInvalidProof)?; - Self::register_latest_activity(&dkg_package)?; - let DkgPackage::Round6(round6) = dkg_package else { return Err(Error::::Round6PackageInvalidProof.into()); }; @@ -1406,8 +1381,6 @@ pub mod pallet { &signature, ).map_err(|_| Error::::ExodusNoncePackageInvalidProof)?; - Self::register_latest_activity(&exodus_package)?; - let ExodusPackage::NonceCommitment(package) = exodus_package else { return Err(Error::::ExodusNoncePackageInvalidProof.into()); }; @@ -1497,8 +1470,6 @@ pub mod pallet { &signature, ).map_err(|_| Error::::ExodusGroupPackageInvalidProof)?; - Self::register_latest_activity(&exodus_package)?; - let ExodusPackage::GroupCommitment(package) = exodus_package else { return Err(Error::::ExodusGroupPackageInvalidProof.into()); }; @@ -1617,8 +1588,6 @@ pub mod pallet { &signature, ).map_err(|_| Error::::ExodusSharePackageInvalidProof)?; - Self::register_latest_activity(&exodus_package)?; - let ExodusPackage::SignatureShare(package) = exodus_package else { return Err(Error::::ExodusSharePackageInvalidProof.into()); }; @@ -1983,94 +1952,98 @@ pub mod pallet { Call::register_round0_package { dkg_package, signature } => { let network_curve = dkg_package.get_network_curve(); let authority_index = dkg_package.get_authority_index(); + let dkg_index = dkg_package.get_dkg_index(); Self::validate_round0_package_size(dkg_package, signature)?; ValidTransaction::with_tag_prefix("GhostExodus") .priority(T::UnsignedPriority::get()) .longevity(T::UnsignedLongevity::get()) - .and_provides((network_curve, authority_index)) + .and_provides((network_curve, authority_index, dkg_index)) .propagate(true) .build() }, Call::register_round1_package { dkg_package, signature } => { let network_curve = dkg_package.get_network_curve(); let authority_index = dkg_package.get_authority_index(); + let dkg_index = dkg_package.get_dkg_index(); Self::validate_round1_package_size(dkg_package, signature)?; ValidTransaction::with_tag_prefix("GhostExodus") .priority(T::UnsignedPriority::get()) .longevity(T::UnsignedLongevity::get()) - .and_provides((network_curve, authority_index)) + .and_provides((network_curve, authority_index, dkg_index)) .propagate(true) .build() }, Call::register_encrypted_round2_packages { dkg_package, signature } => { let network_curve = dkg_package.get_network_curve(); let authority_index = dkg_package.get_authority_index(); + let dkg_index = dkg_package.get_dkg_index(); - Self::validate_round2_package_size( - dkg_package, - signature, - )?; + Self::validate_round2_package_size(dkg_package, signature)?; ValidTransaction::with_tag_prefix("GhostExodus") .priority(T::UnsignedPriority::get()) .longevity(T::UnsignedLongevity::get()) - .and_provides((network_curve, authority_index)) + .and_provides((network_curve, authority_index, dkg_index)) .propagate(true) .build() }, Call::register_round3_complaints { dkg_package, signature } => { let network_curve = dkg_package.get_network_curve(); let authority_index = dkg_package.get_authority_index(); + let dkg_index = dkg_package.get_dkg_index(); Self::validate_round3_complaints_size(dkg_package, signature)?; ValidTransaction::with_tag_prefix("GhostExodus") .priority(T::UnsignedPriority::get()) .longevity(T::UnsignedLongevity::get()) - .and_provides((network_curve, authority_index)) + .and_provides((network_curve, authority_index, dkg_index)) .propagate(true) .build() }, Call::register_round4_justifications { dkg_package, signature } => { let network_curve = dkg_package.get_network_curve(); let authority_index = dkg_package.get_authority_index(); + let dkg_index = dkg_package.get_dkg_index(); Self::validate_round4_justifications_size(dkg_package, signature)?; ValidTransaction::with_tag_prefix("GhostExodus") .priority(T::UnsignedPriority::get()) .longevity(T::UnsignedLongevity::get()) - .and_provides((network_curve, authority_index)) + .and_provides((network_curve, authority_index, dkg_index)) .propagate(true) .build() }, Call::register_round5_verifying_package { dkg_package, signature } => { let network_curve = dkg_package.get_network_curve(); let authority_index = dkg_package.get_authority_index(); + let dkg_index = dkg_package.get_dkg_index(); Self::validate_round5_package_size(dkg_package, signature)?; ValidTransaction::with_tag_prefix("GhostExodus") .priority(T::UnsignedPriority::get()) .longevity(T::UnsignedLongevity::get()) - .and_provides((network_curve, authority_index)) + .and_provides((network_curve, authority_index, dkg_index)) .propagate(true) .build() }, Call::register_round6_public_share_package { dkg_package, signature } => { let network_curve = dkg_package.get_network_curve(); let authority_index = dkg_package.get_authority_index(); + let dkg_index = dkg_package.get_dkg_index(); Self::validate_round6_package_size(dkg_package, signature)?; ValidTransaction::with_tag_prefix("GhostExodus") .priority(T::UnsignedPriority::get()) .longevity(T::UnsignedLongevity::get()) - .and_provides((network_curve, authority_index)) + .and_provides((network_curve, authority_index, dkg_index)) .propagate(true) .build() }, @@ -2078,6 +2051,7 @@ pub mod pallet { let network_curve = exodus_package.get_network_curve(); let authority_index = exodus_package.get_authority_index(); let exodus_session = exodus_package.get_exodus_session(); + let dkg_index = exodus_package.get_dkg_index(); let (_, roast_session) = Self::validate_exodus_nonce_commitment_size_and_get_metadata( @@ -2085,7 +2059,13 @@ pub mod pallet { signature, )?; - let nonce_metadata = (network_curve, authority_index, exodus_session, roast_session); + let nonce_metadata = ( + network_curve, + authority_index, + dkg_index, + exodus_session, + roast_session, + ); ValidTransaction::with_tag_prefix("GhostExodus") .priority(T::UnsignedPriority::get()) @@ -2098,6 +2078,7 @@ pub mod pallet { let network_curve = exodus_package.get_network_curve(); let authority_index = exodus_package.get_authority_index(); let exodus_session = exodus_package.get_exodus_session(); + let dkg_index = exodus_package.get_dkg_index(); let roast_session = Self::validate_exodus_group_commitment_size_and_get_metadata( @@ -2105,7 +2086,13 @@ pub mod pallet { signature, )?; - let group_metadata = (network_curve, authority_index, exodus_session, roast_session); + let group_metadata = ( + network_curve, + authority_index, + dkg_index, + exodus_session, + roast_session, + ); ValidTransaction::with_tag_prefix("GhostExodus") .priority(T::UnsignedPriority::get()) @@ -2119,6 +2106,7 @@ pub mod pallet { let network_curve = exodus_package.get_network_curve(); let authority_index = exodus_package.get_authority_index(); let exodus_session = exodus_package.get_exodus_session(); + let dkg_index = exodus_package.get_dkg_index(); let (roast_session, _) = Self::validate_exodus_signature_share_size_and_get_metadata( @@ -2126,7 +2114,13 @@ pub mod pallet { signature, )?; - let signature_share_metadata = (network_curve, authority_index, exodus_session, roast_session); + let signature_share_metadata = ( + network_curve, + authority_index, + dkg_index, + exodus_session, + roast_session, + ); ValidTransaction::with_tag_prefix("GhostExodus") .priority(T::UnsignedPriority::get()) @@ -2646,31 +2640,13 @@ impl Pallet { }) } - fn register_latest_activity( - package_ref: &impl PackageMetadata, - ) -> DispatchResult { - let authority_index = package_ref.get_authority_index(); - let current_block = T::BlockNumberProvider::current_block_number(); - - ExodusActivity::::try_mutate(&authority_index, - |stored_block| -> DispatchResult { - ensure!( - *stored_block < current_block, - Error::::PackagesAlreadyRegistered, - ); - *stored_block = current_block; - Ok(()) - })?; - - Ok(()) - } - fn validate_round0_package_size( dkg_package: & DkgPackage, signature: &::Signature, ) -> Result<(), InvalidTransaction> { let network_curve = dkg_package.get_network_curve(); let authority_index = dkg_package.get_authority_index(); + let package_dkg_index = dkg_package.get_dkg_index(); if !T::NetworkDataHandler::curve_exists(&network_curve) { return Err(InvalidTransaction::BadProof); @@ -2682,6 +2658,10 @@ impl Pallet { return Err(InvalidTransaction::BadProof); } + if state.get_dkg_index() != package_dkg_index { + return Err(InvalidTransaction::BadProof); + } + if state.contains_index(authority_index) { return Err(InvalidTransaction::BadSigner); } @@ -2709,6 +2689,7 @@ impl Pallet { let network_curve = dkg_package.get_network_curve(); let authority_index = dkg_package.get_authority_index(); + let package_dkg_index = dkg_package.get_dkg_index(); if !T::NetworkDataHandler::curve_exists(&network_curve) { return Err(InvalidTransaction::BadProof); @@ -2720,6 +2701,10 @@ impl Pallet { return Err(InvalidTransaction::BadProof); } + if state.get_dkg_index() != package_dkg_index { + return Err(InvalidTransaction::BadProof); + } + if !state.contains_index(authority_index) { return Err(InvalidTransaction::BadSigner); } @@ -2760,6 +2745,7 @@ impl Pallet { let network_curve = dkg_package.get_network_curve(); let authority_index = dkg_package.get_authority_index(); + let package_dkg_index = dkg_package.get_dkg_index(); if !T::NetworkDataHandler::curve_exists(&network_curve) { return Err(InvalidTransaction::BadProof); @@ -2771,6 +2757,10 @@ impl Pallet { return Err(InvalidTransaction::BadProof); } + if state.get_dkg_index() != package_dkg_index { + return Err(InvalidTransaction::BadProof); + } + if !state.contains_index(authority_index) { return Err(InvalidTransaction::BadSigner); } @@ -2839,6 +2829,7 @@ impl Pallet { let network_curve = dkg_package.get_network_curve(); let authority_index = dkg_package.get_authority_index(); + let package_dkg_index = dkg_package.get_dkg_index(); if !T::NetworkDataHandler::curve_exists(&network_curve) { return Err(InvalidTransaction::BadProof); @@ -2850,6 +2841,10 @@ impl Pallet { return Err(InvalidTransaction::BadProof); } + if state.get_dkg_index() != package_dkg_index { + return Err(InvalidTransaction::BadProof); + } + if !state.contains_index(authority_index) { return Err(InvalidTransaction::BadSigner); } @@ -2903,6 +2898,7 @@ impl Pallet { let network_curve = dkg_package.get_network_curve(); let authority_index = dkg_package.get_authority_index(); + let package_dkg_index = dkg_package.get_dkg_index(); if !T::NetworkDataHandler::curve_exists(&network_curve) { return Err(InvalidTransaction::BadProof); @@ -2914,6 +2910,10 @@ impl Pallet { return Err(InvalidTransaction::BadProof); } + if state.get_dkg_index() != package_dkg_index { + return Err(InvalidTransaction::BadProof); + } + if !state.contains_index(authority_index) { return Err(InvalidTransaction::BadSigner); } @@ -2978,6 +2978,7 @@ impl Pallet { ) -> Result<(), InvalidTransaction> { let network_curve = dkg_package.get_network_curve(); let authority_index = dkg_package.get_authority_index(); + let package_dkg_index = dkg_package.get_dkg_index(); if !T::NetworkDataHandler::curve_exists(&network_curve) { return Err(InvalidTransaction::BadProof); @@ -2989,6 +2990,10 @@ impl Pallet { return Err(InvalidTransaction::BadProof); } + if state.get_dkg_index() != package_dkg_index { + return Err(InvalidTransaction::BadProof); + } + if !state.contains_index(authority_index) { return Err(InvalidTransaction::BadSigner); } @@ -3020,6 +3025,7 @@ impl Pallet { ) -> Result<(), InvalidTransaction> { let network_curve = dkg_package.get_network_curve(); let authority_index = dkg_package.get_authority_index(); + let package_dkg_index = dkg_package.get_dkg_index(); if !T::NetworkDataHandler::curve_exists(&network_curve) { return Err(InvalidTransaction::BadProof); @@ -3031,6 +3037,10 @@ impl Pallet { return Err(InvalidTransaction::BadProof); } + if state.get_dkg_index() != package_dkg_index { + return Err(InvalidTransaction::BadProof); + } + if !state.contains_index(authority_index) { return Err(InvalidTransaction::BadSigner); } @@ -3067,6 +3077,7 @@ impl Pallet { let network_curve = exodus_package.get_network_curve(); let authority_index = exodus_package.get_authority_index(); + let exodus_dkg_index = exodus_package.get_dkg_index(); if package.hiding_commitment.len() != network_curve.element_bytes_len() { return Err(InvalidTransaction::BadProof); @@ -3096,6 +3107,10 @@ impl Pallet { return Err(InvalidTransaction::BadSigner); } + if active_state.get_dkg_index() != exodus_dkg_index { + return Err(InvalidTransaction::BadProof); + } + let authority = ActiveAuthorities::::get(&network_curve) .get(authority_index as usize) .cloned() @@ -3129,6 +3144,7 @@ impl Pallet { let network_curve = exodus_package.get_network_curve(); let authority_index = exodus_package.get_authority_index(); + let exodus_dkg_index = exodus_package.get_dkg_index(); if !T::NetworkDataHandler::curve_exists(&network_curve) { return Err(InvalidTransaction::BadProof); @@ -3148,6 +3164,10 @@ impl Pallet { return Err(InvalidTransaction::BadSigner); } + if active_state.get_dkg_index() != exodus_dkg_index { + return Err(InvalidTransaction::BadProof); + } + let authority = ActiveAuthorities::::get(&network_curve) .get(authority_index as usize) .cloned() @@ -3172,6 +3192,7 @@ impl Pallet { let network_curve = exodus_package.get_network_curve(); let authority_index = exodus_package.get_authority_index(); + let exodus_dkg_index = exodus_package.get_dkg_index(); if package.signature_share.len() != network_curve.scalar_bytes_len() { return Err(InvalidTransaction::BadProof); @@ -3196,6 +3217,10 @@ impl Pallet { return Err(InvalidTransaction::BadSigner); } + if active_state.get_dkg_index() != exodus_dkg_index { + return Err(InvalidTransaction::BadProof); + } + let authority = ActiveAuthorities::::get(&network_curve) .get(authority_index as usize) .cloned() @@ -3380,6 +3405,7 @@ impl Pallet { secret_share, &authority_key, session, + dkg_index )?; Ok(ExodusOk::ExodusNonceCommitted( @@ -3400,6 +3426,7 @@ impl Pallet { &authority_key, session, roast_session, + dkg_index, ); group_commitment_result @@ -3432,6 +3459,7 @@ impl Pallet { &authority_key, session, roast_session, + dkg_index ); signature_share_result @@ -3560,6 +3588,7 @@ impl Pallet { secret_share: &[u8], authority_key: &T::AuthorityId, exodus_session: ExodusSession, + active_dkg_index: DkgIndex, ) -> ExodusResult<()> { let authority_index = exodus_storage.authority_index; let network_curve = exodus_storage.network_curve; @@ -3573,6 +3602,7 @@ impl Pallet { exodus_storage.prepare_signed_call_with_context( authority_key, + active_dkg_index, exodus_records, |context| { let package = context.with_exodus_nonce_commitment( @@ -3604,6 +3634,7 @@ impl Pallet { authority_key: &T::AuthorityId, exodus_session: ExodusSession, roast_session: RoastSession, + active_dkg_index: DkgIndex, ) -> ExodusResult<()> { let authority_index = exodus_storage.authority_index; let network_curve = exodus_storage.network_curve; @@ -3635,6 +3666,7 @@ impl Pallet { exodus_storage.prepare_signed_call_with_context( authority_key, + active_dkg_index, exodus_records, |context| { let package = context.with_exodus_group_commitment( @@ -3668,6 +3700,7 @@ impl Pallet { authority_key: &T::AuthorityId, exodus_session: ExodusSession, roast_session: RoastSession, + active_dkg_index: DkgIndex, ) -> ExodusResult<()> { let authority_index = exodus_storage.authority_index; let network_curve = exodus_storage.network_curve; @@ -3717,6 +3750,7 @@ impl Pallet { exodus_storage.prepare_signed_call_with_context( authority_key, + active_dkg_index, exodus_records, |context| { let package = context.with_exodus_signature_share( @@ -3808,8 +3842,12 @@ impl Pallet { DkgStorageEnum::Round0 { package_hash } )?; + let current_dkg_index = QualificationDkgState::::get(&network_curve) + .get_dkg_index(); + dkg_storage.prepare_signed_call_with_context( &authority_key, + current_dkg_index, &mut round0_metadata, |context: PackageContext| { Ok(DkgPackage::Round0(context.with_dkg_round0(package_hash))) @@ -3904,8 +3942,12 @@ impl Pallet { )); } + let current_dkg_index = QualificationDkgState::::get(&network_curve) + .get_dkg_index(); + dkg_storage.prepare_signed_call_with_context( &authority_key, + current_dkg_index, &mut round1_metadata, |context| { let package = context.with_dkg_round1(public_package_clone)?; @@ -4019,8 +4061,12 @@ impl Pallet { DkgStorageEnum::Round2 { secret_package, public_packages }, )?; + let current_dkg_index = QualificationDkgState::::get(&network_curve) + .get_dkg_index(); + dkg_storage.prepare_signed_call_with_context( &authority_key, + current_dkg_index, &mut round2_metadata, |context| { let encryption_bundle = BundledPackages { bitmask, blob }; @@ -4130,8 +4176,12 @@ impl Pallet { DkgStorageEnum::Round3 { decrypted }, )?; + let current_dkg_index = QualificationDkgState::::get(&network_curve) + .get_dkg_index(); + dkg_storage.prepare_signed_call_with_context( &authority_key, + current_dkg_index, &mut round3_metadata, |context| { let package = context.with_dkg_round3(indices)?; @@ -4235,8 +4285,12 @@ impl Pallet { DkgStorageEnum::Round4, )?; + let current_dkg_index = QualificationDkgState::::get(&network_curve) + .get_dkg_index(); + dkg_storage.prepare_signed_call_with_context( &authority_key, + current_dkg_index, &mut round4_metadata, |context| { let justification_bundle = BundledPackages { bitmask, blob }; @@ -4358,8 +4412,12 @@ impl Pallet { DkgStorageEnum::Round5 { secret_share, merkle_proof } )?; + let current_dkg_index = QualificationDkgState::::get(&network_curve) + .get_dkg_index(); + dkg_storage.prepare_signed_call_with_context( &authority_key, + current_dkg_index, &mut round_metadata, |context| { let package = context.with_dkg_round5(verifying_key, merkle_root)?; @@ -4434,8 +4492,12 @@ impl Pallet { let owned_merkle_proof = core::mem::take(merkle_proof); + let current_dkg_index = QualificationDkgState::::get(&network_curve) + .get_dkg_index(); + dkg_storage.prepare_signed_call_with_context( &authority_key, + current_dkg_index, &mut round_metadata, |context| { let package = context.with_dkg_round6(verifying_share, owned_merkle_proof)?; diff --git a/pallets/exodus/src/types/local_storage.rs b/pallets/exodus/src/types/local_storage.rs index 81a7c59..5f5327a 100644 --- a/pallets/exodus/src/types/local_storage.rs +++ b/pallets/exodus/src/types/local_storage.rs @@ -8,7 +8,7 @@ use sp_runtime::{ }; use super::{DkgPackage, ExodusPackage, ExodusOk, PackageContext}; -use crate::{AuthIndex, ExodusSession, ExodusHash, ExodusError}; +use crate::{AuthIndex, DkgIndex, ExodusSession, ExodusHash, ExodusError}; fn create_storage_key(prefix: &[u8], index: &[u8], network: &[u8]) -> Vec { let mut key = crate::DB_STORAGE_PREFIX.to_vec(); @@ -156,6 +156,7 @@ where pub fn prepare_signed_call_with_context( &self, authority_key: &A, + current_dkg_index: DkgIndex, exodus_records: &mut ExodusRecords, make_data: F1, submit_call: F2, @@ -170,7 +171,8 @@ where { let context = PackageContext::default() .with_authority_index(self.authority_index) - .with_network_curve(self.network_curve); + .with_network_curve(self.network_curve) + .with_dkg_index(current_dkg_index); let package = make_data(context)?; @@ -454,6 +456,7 @@ where pub fn prepare_signed_call_with_context( &self, authority_key: &A, + current_dkg_index: DkgIndex, dkg_record: &mut DkgRecord, make_data: F1, submit_call: F2, @@ -466,7 +469,8 @@ where { let context = PackageContext::default() .with_authority_index(self.authority_index) - .with_network_curve(self.network_curve); + .with_network_curve(self.network_curve) + .with_dkg_index(current_dkg_index); let package = make_data(context)?; diff --git a/pallets/exodus/src/types/packages.rs b/pallets/exodus/src/types/packages.rs index 88d0fbd..23e7fb0 100644 --- a/pallets/exodus/src/types/packages.rs +++ b/pallets/exodus/src/types/packages.rs @@ -4,7 +4,7 @@ use sp_runtime::RuntimeDebug; use codec::{Encode, Decode}; use frame_support::{BoundedVec, traits::ConstU32}; -use crate::{AuthIndex, ExodusSession, ExodusHash, ExodusError}; +use crate::{AuthIndex, DkgIndex, ExodusSession, ExodusHash, ExodusError}; pub trait PackageMetadata where @@ -18,6 +18,9 @@ where fn get_network_curve(&self) -> NetworkCurve { self.context().get_network_curve() } + fn get_dkg_index(&self) -> DkgIndex { + self.context().get_dkg_index() + } } #[derive(Encode, Decode, Clone, RuntimeDebug, TypeInfo, PartialEq, Eq)] @@ -101,7 +104,8 @@ where #[derive(Default, RuntimeDebug, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)] pub struct PackageContext { authority_index: AuthIndex, - network_curve: NetworkCurve + network_curve: NetworkCurve, + dkg_index: DkgIndex, } impl PackageContext @@ -116,6 +120,10 @@ where self.network_curve } + pub fn get_dkg_index(&self) -> DkgIndex { + self.dkg_index + } + pub fn with_network_curve(mut self, network_curve: NetworkCurve) -> Self { self.network_curve = network_curve; self @@ -125,6 +133,11 @@ where self.authority_index = authority_index; self } + + pub fn with_dkg_index(mut self, dkg_index: DkgIndex) -> Self { + self.dkg_index = dkg_index; + self + } } #[derive(RuntimeDebug, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, TypeInfo)]