diff --git a/pallets/dkg-metadata/src/lib.rs b/pallets/dkg-metadata/src/lib.rs index 42eaeecbc..d911dd7eb 100644 --- a/pallets/dkg-metadata/src/lib.rs +++ b/pallets/dkg-metadata/src/lib.rs @@ -141,6 +141,12 @@ use sp_std::{ use types::RoundMetadata; use weights::WeightInfo; +// Reputation assigned to genesis authorities +pub const INITIAL_REPUTATION: u32 = 1_000_000_000; + +// Reputation increase awarded to authorities on submission of next public key +pub const REPUTATION_INCREMENT: u32 = INITIAL_REPUTATION / 1000; + #[cfg(test)] mod mock; pub mod types; @@ -920,7 +926,7 @@ pub mod pallet { let reputation = AuthorityReputations::::get(authority.clone()); AuthorityReputations::::insert( authority, - decay.mul_floor(reputation).saturating_add(1_000_000_000u32.into()), + decay.mul_floor(reputation).saturating_add(INITIAL_REPUTATION.into()), ); } @@ -973,6 +979,16 @@ pub mod pallet { let bounded_key: BoundedVec<_, _> = key.clone().try_into().map_err(|_| Error::::OutOfBounds)?; NextDKGPublicKey::::put((Self::next_authority_set_id(), bounded_key)); + + // bump reputation for all accounts + for authority in accounts { + let reputation = AuthorityReputations::::get(authority.clone()); + AuthorityReputations::::insert( + authority, + reputation.saturating_add(REPUTATION_INCREMENT.into()), + ); + } + Self::deposit_event(Event::NextPublicKeySubmitted { compressed_pub_key: key.clone(), }); diff --git a/pallets/dkg-metadata/src/tests.rs b/pallets/dkg-metadata/src/tests.rs index 80d778335..339601326 100644 --- a/pallets/dkg-metadata/src/tests.rs +++ b/pallets/dkg-metadata/src/tests.rs @@ -15,9 +15,10 @@ use std::vec; use crate::{ - mock::*, AggregatedMisbehaviourReports, AuthorityReputations, Config, Error, Event, - JailedKeygenAuthorities, NextAuthorities, NextBestAuthorities, NextKeygenThreshold, - NextSignatureThreshold, + mock::*, AggregatedMisbehaviourReports, AggregatedPublicKeys, Authorities, + AuthorityReputations, BestAuthorities, Config, Error, Event, JailedKeygenAuthorities, + NextAuthorities, NextBestAuthorities, NextKeygenThreshold, NextSignatureThreshold, + INITIAL_REPUTATION, REPUTATION_INCREMENT, }; use codec::Encode; use dkg_runtime_primitives::{keccak_256, utils::ecdsa, MisbehaviourType, KEY_TYPE}; @@ -57,6 +58,13 @@ fn mock_pub_key() -> ecdsa::Public { ecdsa_generate(KEY_TYPE, None) } +fn mock_signature(pub_key: ecdsa::Public, dkg_key: ecdsa::Public) -> (Vec, Vec) { + let msg = dkg_key.encode(); + let hash = keccak_256(&msg); + let signature: ecdsa::Signature = ecdsa_sign_prehashed(KEY_TYPE, &pub_key, &hash).unwrap(); + (msg, signature.encode()) +} + fn assert_last_event(generic_event: ::RuntimeEvent) { frame_system::Pallet::::assert_last_event(generic_event.into()); } @@ -805,3 +813,65 @@ fn keygen_misbehaviour_reports_does_not_drop_threshold_below_2() { ); }); } + +#[test] +fn reputation_is_set_correctly() { + new_test_ext(vec![1, 2, 3, 4, 5]).execute_with(|| { + // setup the new threshold so our signature is accepted + let keygen_threshold = 5; + let signature_threshold = 3; + let dkg_key = ecdsa_generate(KEY_TYPE, None); + NextKeygenThreshold::::put(keygen_threshold); + NextSignatureThreshold::::put(signature_threshold); + let mut aggregated_public_keys = AggregatedPublicKeys::default(); + // prep the next authorities + let mut next_authorities: BoundedVec<_, _> = Default::default(); + let mut next_authorities_raw: Vec<_> = Default::default(); + for _ in 1..=5 { + let authority_id = mock_pub_key(); + let dkg_id = DKGId::from(authority_id); + next_authorities_raw.push(authority_id); + next_authorities.try_push(dkg_id).unwrap(); + aggregated_public_keys + .keys_and_signatures + .push(mock_signature(authority_id, dkg_key)); + } + + // load them onchain + Authorities::::put(&next_authorities); + NextAuthorities::::put(&next_authorities); + let next_best_authorities = + DKGMetadata::get_best_authorities(keygen_threshold as usize, &next_authorities); + let mut bounded_next_best_authorities: BoundedVec<_, _> = Default::default(); + for auth in next_best_authorities { + bounded_next_best_authorities.try_push(auth).unwrap(); + } + NextBestAuthorities::::put(&bounded_next_best_authorities); + BestAuthorities::::put(&bounded_next_best_authorities); + + assert_ok!(DKGMetadata::submit_public_key( + RuntimeOrigin::none(), + aggregated_public_keys.clone() + )); + + let reputations = AuthorityReputations::::iter(); + + // all authorities should have initial reputation + for rep in reputations { + assert!(rep.1 == INITIAL_REPUTATION.into()); + } + + // ---- submit next public key ---- + + assert_ok!(DKGMetadata::submit_next_public_key( + RuntimeOrigin::none(), + aggregated_public_keys + )); + let reputations = AuthorityReputations::::iter(); + + // all authorities should have initial reputation + increment + for rep in reputations { + assert!(rep.1 == (INITIAL_REPUTATION + REPUTATION_INCREMENT).into()); + } + }) +}