Skip to content

Commit

Permalink
chore: revise-reputation-constants (#4117)
Browse files Browse the repository at this point in the history
- deletes online credits
- updates the values of chainspec constants
- updates signer nomination criteria
- revises and clarifies naming

Co-authored-by: Martin Rieke <martin@chainflip.io>
  • Loading branch information
dandanlen and martin-chainflip authored Oct 23, 2023
1 parent 0c386ff commit fd975b9
Show file tree
Hide file tree
Showing 18 changed files with 162 additions and 220 deletions.
4 changes: 2 additions & 2 deletions state-chain/cf-integration-tests/src/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ fn account_deletion_removes_relevant_storage_items() {
network::Cli::start_bidding(&backup_node);
Reputation::heartbeat(state_chain_runtime::RuntimeOrigin::signed(backup_node.clone()))
.unwrap();
assert!(Reputations::<Runtime>::get(backup_node.clone()).online_credits > 0);
assert!(Reputations::<Runtime>::contains_key(backup_node.clone()));

let elon_vanity_name = "ElonShibaMoonInu";
network::Cli::set_vanity_name(&backup_node, elon_vanity_name);
Expand Down Expand Up @@ -70,6 +70,6 @@ fn account_deletion_removes_relevant_storage_items() {
let vanity_names = VanityNames::<Runtime>::get();
assert!(vanity_names.get(&backup_node).is_none());
assert_eq!(pallet_cf_account_roles::AccountRoles::<Runtime>::get(&backup_node), None);
assert_eq!(Reputations::<Runtime>::get(backup_node).online_credits, 0);
assert_eq!(Reputations::<Runtime>::get(backup_node).online_blocks, 0);
});
}
2 changes: 2 additions & 0 deletions state-chain/cf-integration-tests/src/mock_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ pub const BACKUP_NODE_EMISSION_INFLATION_PERBILL: u32 = 6;
pub const SUPPLY_UPDATE_INTERVAL_DEFAULT: u32 = 14_400;
pub const MIN_FUNDING: FlipBalance = 10 * FLIPPERINOS_PER_FLIP;

pub const ACCRUAL_RATIO: (i32, u32) = (1, 1);

/// The offences committable within the protocol and their respective reputation penalty and
/// suspension durations.
pub const PENALTIES: &[(Offence, (i32, BlockNumber))] = &[
Expand Down
34 changes: 1 addition & 33 deletions state-chain/cf-integration-tests/src/signer_nomination.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
use std::collections::BTreeSet;

use cf_traits::{
offence_reporting::OffenceReporter, EpochInfo, SingleSignerNomination,
ThresholdSignerNomination,
};
use cf_traits::{offence_reporting::OffenceReporter, EpochInfo, ThresholdSignerNomination};
use pallet_cf_threshold_signature::PalletOffence;
use pallet_cf_validator::{CurrentAuthorities, CurrentEpoch, HistoricalAuthorities};
use sp_runtime::AccountId32;
Expand All @@ -12,9 +9,6 @@ use state_chain_runtime::{EthereumInstance, Reputation, Runtime, Validator};
type RuntimeThresholdSignerNomination =
<Runtime as pallet_cf_threshold_signature::Config<EthereumInstance>>::ThresholdSignerNomination;

type RuntimeBroadcastsignerNomination =
<Runtime as pallet_cf_broadcast::Config<EthereumInstance>>::BroadcastSignerNomination;

#[test]
fn threshold_signer_nomination_respects_epoch() {
super::genesis::default().build().execute_with(|| {
Expand Down Expand Up @@ -80,15 +74,6 @@ fn test_not_nominated_for_offence<F: Fn(crate::AccountId)>(penalise: F) {
}
}

#[test]
fn offline_nodes_are_not_nominated_for_threshold_signing() {
super::genesis::default().build().execute_with(|| {
test_not_nominated_for_offence(|node_id| {
Reputation::penalise_offline_authorities(vec![node_id])
});
});
}

#[test]
fn nodes_who_failed_to_sign_excluded_from_threshold_nomination() {
super::genesis::default().build().execute_with(|| {
Expand All @@ -97,20 +82,3 @@ fn nodes_who_failed_to_sign_excluded_from_threshold_nomination() {
});
});
}

#[test]
fn offline_nodes_are_not_nominated_transaction_signing() {
super::genesis::default().build().execute_with(|| {
let node1 = Validator::current_authorities().first().unwrap().clone();

Reputation::penalise_offline_authorities(vec![node1.clone()]);

for seed in 0..20 {
// no extra ids, excluded.
assert_ne!(
RuntimeBroadcastsignerNomination::nomination_with_seed(seed, &[]).unwrap(),
node1
);
}
});
}
6 changes: 0 additions & 6 deletions state-chain/custom-rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ pub enum RpcAccountInfo {
flip_balance: NumberOrHex,
bond: NumberOrHex,
last_heartbeat: u32,
online_credits: u32,
reputation_points: i32,
keyholder_epochs: Vec<u32>,
is_current_authority: bool,
Expand Down Expand Up @@ -106,7 +105,6 @@ impl RpcAccountInfo {
flip_balance: info.balance.into(),
bond: info.bond.into(),
last_heartbeat: info.last_heartbeat,
online_credits: info.online_credits,
reputation_points: info.reputation_points,
keyholder_epochs: info.keyholder_epochs,
is_current_authority: info.is_current_authority,
Expand All @@ -130,7 +128,6 @@ pub struct RpcAccountInfoV2 {
pub balance: NumberOrHex,
pub bond: NumberOrHex,
pub last_heartbeat: u32,
pub online_credits: u32,
pub reputation_points: i32,
pub keyholder_epochs: Vec<u32>,
pub is_current_authority: bool,
Expand Down Expand Up @@ -582,7 +579,6 @@ where
balance: account_info.balance.into(),
bond: account_info.bond.into(),
last_heartbeat: account_info.last_heartbeat,
online_credits: account_info.online_credits,
reputation_points: account_info.reputation_points,
keyholder_epochs: account_info.keyholder_epochs,
is_current_authority: account_info.is_current_authority,
Expand Down Expand Up @@ -1005,7 +1001,6 @@ mod test {
balance: 10u128.pow(18),
bond: 10u128.pow(18),
last_heartbeat: 0,
online_credits: 0,
reputation_points: 0,
keyholder_epochs: vec![123],
is_current_authority: true,
Expand All @@ -1030,7 +1025,6 @@ mod test {
"is_qualified": true,
"keyholder_epochs": [123],
"last_heartbeat": 0,
"online_credits": 0,
"reputation_points": 0,
"role": "validator",
"apy_bp": 100,
Expand Down
26 changes: 13 additions & 13 deletions state-chain/node/src/chain_spec/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,23 @@ pub const CURRENT_AUTHORITY_EMISSION_INFLATION_PERBILL: u32 = 28;
pub const BACKUP_NODE_EMISSION_INFLATION_PERBILL: u32 = 6;
pub const SUPPLY_UPDATE_INTERVAL: u32 = 24 * HOURS;

// Number of online credits required to get `ACCRUAL_REPUTATION_POINTS` of reputation
const ACCRUAL_ONLINE_CREDITS: u32 = 2500;
// Number of reputation points received for having `ACCRUAL_ONLINE_CREDITS`
const ACCRUAL_REPUTATION_POINTS: i32 = 1;
pub const ACCRUAL_RATIO: (i32, u32) = (ACCRUAL_REPUTATION_POINTS, ACCRUAL_ONLINE_CREDITS);
// This is equivalent to one reputation point for every minute of online time.
pub const REPUTATION_PER_HEARTBEAT: i32 = 15;
pub const ACCRUAL_RATIO: (i32, u32) = (REPUTATION_PER_HEARTBEAT, HEARTBEAT_BLOCK_INTERVAL);

const REPUTATION_PENALTY_SMALL: i32 = REPUTATION_PER_HEARTBEAT; // 15 minutes to recover reputation
const REPUTATION_PENALTY_MEDIUM: i32 = REPUTATION_PER_HEARTBEAT * 4; // One hour to recover reputation
const REPUTATION_PENALTY_LARGE: i32 = REPUTATION_PER_HEARTBEAT * 8; // Two hours to recover reputation

/// The offences committable within the protocol and their respective reputation penalty and
/// suspension durations.
pub const PENALTIES: &[(Offence, (i32, BlockNumber))] = &[
(Offence::ParticipateKeygenFailed, (15, HEARTBEAT_BLOCK_INTERVAL)),
(Offence::ParticipateSigningFailed, (15, HEARTBEAT_BLOCK_INTERVAL)),
(Offence::MissedAuthorshipSlot, (15, HEARTBEAT_BLOCK_INTERVAL)),
(Offence::MissedHeartbeat, (15, HEARTBEAT_BLOCK_INTERVAL)),
// We exclude them from the nomination pool of the next attempt,
// so there is no need to suspend them further.
(Offence::FailedToBroadcastTransaction, (10, 0)),
(Offence::GrandpaEquivocation, (50, HEARTBEAT_BLOCK_INTERVAL * 5)),
(Offence::MissedHeartbeat, (REPUTATION_PENALTY_SMALL, 0)),
(Offence::ParticipateKeygenFailed, (REPUTATION_PENALTY_MEDIUM, HEARTBEAT_BLOCK_INTERVAL)),
(Offence::ParticipateSigningFailed, (REPUTATION_PENALTY_MEDIUM, HEARTBEAT_BLOCK_INTERVAL)),
(Offence::MissedAuthorshipSlot, (REPUTATION_PENALTY_LARGE, HEARTBEAT_BLOCK_INTERVAL)),
(Offence::FailedToBroadcastTransaction, (REPUTATION_PENALTY_MEDIUM, HEARTBEAT_BLOCK_INTERVAL)),
(Offence::GrandpaEquivocation, (REPUTATION_PENALTY_LARGE, HEARTBEAT_BLOCK_INTERVAL * 5)),
];

pub const MINIMUM_SWAP_AMOUNTS: &[(Asset, AssetAmount)] = &[
Expand Down
4 changes: 0 additions & 4 deletions state-chain/node/src/chain_spec/perseverance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@ use cf_primitives::{AccountId, AccountRole, BlockNumber, FlipBalance, NetworkEnv
use sc_service::ChainType;
use sp_core::H256;

// *** Overrides from common
pub const ACCRUAL_RATIO: (i32, u32) = (10, 10);
// ***

pub struct Config;

pub const NETWORK_NAME: &str = "Chainflip-Perseverance";
Expand Down
10 changes: 5 additions & 5 deletions state-chain/pallets/cf-broadcast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ impl_pallet_safe_mode!(PalletSafeMode; retry_enabled);

use cf_chains::{ApiCall, Chain, ChainCrypto, FeeRefundCalculator, TransactionBuilder};
use cf_traits::{
offence_reporting::OffenceReporter, Broadcaster, Chainflip, EpochInfo, EpochKey,
OnBroadcastReady, SingleSignerNomination, ThresholdSigner,
offence_reporting::OffenceReporter, BroadcastNomination, Broadcaster, Chainflip, EpochInfo,
EpochKey, OnBroadcastReady, ThresholdSigner,
};
use codec::{Decode, Encode, MaxEncodedLen};
use frame_support::{
Expand Down Expand Up @@ -73,7 +73,7 @@ pub const PALLET_VERSION: StorageVersion = StorageVersion::new(1);
pub mod pallet {
use super::*;
use cf_chains::benchmarking_value::BenchmarkValue;
use cf_traits::{AccountRoleRegistry, KeyProvider, OnBroadcastReady, SingleSignerNomination};
use cf_traits::{AccountRoleRegistry, BroadcastNomination, KeyProvider, OnBroadcastReady};
use frame_support::{ensure, pallet_prelude::*, traits::EnsureOrigin};
use frame_system::pallet_prelude::*;

Expand Down Expand Up @@ -169,7 +169,7 @@ pub mod pallet {
>;

/// Signer nomination.
type BroadcastSignerNomination: SingleSignerNomination<SignerId = Self::ValidatorId>;
type BroadcastSignerNomination: BroadcastNomination<BroadcasterId = Self::ValidatorId>;

/// For reporting bad actors.
type OffenceReporter: OffenceReporter<
Expand Down Expand Up @@ -759,7 +759,7 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
let seed =
(broadcast_attempt.broadcast_attempt_id, broadcast_attempt.transaction_payload.clone())
.encode();
if let Some(nominated_signer) = T::BroadcastSignerNomination::nomination_with_seed(
if let Some(nominated_signer) = T::BroadcastSignerNomination::nominate_broadcaster(
seed,
&FailedBroadcasters::<T, I>::get(broadcast_attempt.broadcast_attempt_id.broadcast_id)
.unwrap_or_default(),
Expand Down
6 changes: 3 additions & 3 deletions state-chain/pallets/cf-reputation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ A module to manage offences, reputation and suspensions of our nodes for the Sta

## Overview

Nodes earn reputations points for remaining online. For every block of online time, they receive an online credit. At regular intervals dictated by the heartbeat duration, these credits are exchanged for reputation points according to an *accrual rate*.
Nodes earn reputation points for remaining online. We count the number of blocks between heartbeat submissions and, at regular intervals dictated by the heartbeat duration, these are converted to reputation points according to an *accrual rate*.

If a node is reported for committing an offence, the matching penalty is resolved. A penalty consists of a reputation penalty and a suspension duration measured in blocks. Note both the penalty and suspension can be zero.

Expand All @@ -22,9 +22,9 @@ Once every heartbeat interval, this pallet divides nodes into nodes that are 'on
- Heartbeat interval: The duration, measured in blocks, after which we consider a node to be offline if no heartbeat is received.
- Online: A node is considered online if its most recent hearbeat was at most `heartbeat_interval` blocks ago.
- Offline: A node is considered offline if its most recent heartbeat was more than `heartbeat_interval` blocks ago.
- Online credits: Online credits increase for every heartbeat interval in which a node submitted their heartbeat.
- Online Blocks: We count the number of blocks for which a validator has been online, based on heartbeat submissions.
- Reputation points: A measure of how diligently a node has been fulfilling its duties.
- Suspension: A suspension is served for a given offence and lasts for a number of blocks. The consequences of suspensions are not defined by this pallet - rather the currently suspended nodes for any collection of offences can be queried in order to act
- Offences: any event that can be reported and might incur a reputation penalty and/or suspension.
- Slashing: The process of confiscating and burning FLIP tokens from an authority.
- Accrual Ratio: A ratio of reputation points earned per number of offline credits
- Accrual Ratio: A ratio of reputation points earned per number of online blocks.
2 changes: 1 addition & 1 deletion state-chain/pallets/cf-reputation/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const MAX_VALIDATOR_COUNT: u32 = 150;

benchmarks! {
update_accrual_ratio {
let call = Call::<T>::update_accrual_ratio{ reputation_points: 2, online_credits: 151u32.into() };
let call = Call::<T>::update_accrual_ratio{ reputation_points: 2, number_of_blocks: 151u32.into() };
} : { let _ = call.dispatch_bypass_filter(T::EnsureGovernance::try_successful_origin().unwrap()); }
set_penalty {
let call = Call::<T>::set_penalty { offence: PalletOffence::MissedHeartbeat.into(), new_penalty: Default::default() };
Expand Down
Loading

0 comments on commit fd975b9

Please sign in to comment.