Consensus Mechanism
Learn about consensus mechanisms in liquid staking protocols.
Last updated: 2024-03-21
Edit on GitHubOverview
Understanding and properly implementing consensus mechanisms is crucial for your liquid staking protocol's security and performance. This guide covers stake delegation, vote accounts, Tower BFT consensus, and slashing protection.
Stake Delegation
Implement secure stake delegation mechanisms to distribute stake across validators.
Stake Delegation Implementation
1pub struct StakeDelegation {
2 /// Vote account to delegate to
3 pub vote_account: Pubkey,
4
5 /// Stake authority
6 pub stake_authority: Pubkey,
7
8 /// Withdraw authority
9 pub withdraw_authority: Pubkey,
10
11 /// Stake amount in lamports
12 pub stake_amount: u64,
13
14 /// Lockup period
15 pub lockup: Option<Lockup>,
16}
17
18impl StakeDelegation {
19 pub fn create_stake_account(
20 &self,
21 payer: &Keypair,
22 stake_account: &Keypair,
23 ) -> Result<Transaction, ProgramError> {
24 let rent = Rent::get()?.minimum_balance(std::mem::size_of::<StakeState>());
25
26 let mut transaction = Transaction::new_with_payer(
27 &[
28 // Create stake account
29 system_instruction::create_account(
30 &payer.pubkey(),
31 &stake_account.pubkey(),
32 rent + self.stake_amount,
33 std::mem::size_of::<StakeState>() as u64,
34 &stake::program::id(),
35 ),
36 // Initialize stake account
37 stake::instruction::initialize(
38 &stake_account.pubkey(),
39 &stake::state::Authorized {
40 staker: self.stake_authority,
41 withdrawer: self.withdraw_authority,
42 },
43 &self.lockup.unwrap_or_default(),
44 ),
45 // Delegate stake
46 stake::instruction::delegate_stake(
47 &stake_account.pubkey(),
48 &self.stake_authority,
49 &self.vote_account,
50 ),
51 ],
52 Some(&payer.pubkey()),
53 );
54
55 Ok(transaction)
56 }
57
58 pub fn deactivate_stake(
59 &self,
60 stake_account: &Pubkey,
61 ) -> Result<Transaction, ProgramError> {
62 let transaction = Transaction::new_with_payer(
63 &[stake::instruction::deactivate_stake(
64 stake_account,
65 &self.stake_authority,
66 )],
67 Some(&self.stake_authority),
68 );
69
70 Ok(transaction)
71 }
72}
Vote Account Management
Implement vote account management and monitoring.
Vote Account Implementation
1pub struct VoteAccountManager {
2 /// RPC connection
3 pub connection: Arc<RpcClient>,
4
5 /// Vote account
6 pub vote_account: Pubkey,
7
8 /// Vote authority
9 pub vote_authority: Keypair,
10
11 /// Withdraw authority
12 pub withdraw_authority: Keypair,
13}
14
15impl VoteAccountManager {
16 pub async fn create_vote_account(
17 &self,
18 node_pubkey: &Pubkey,
19 commission: u8,
20 ) -> Result<Transaction, ProgramError> {
21 let rent = self.connection
22 .get_minimum_balance_for_rent_exemption(VoteState::size_of())
23 .await?;
24
25 let mut transaction = Transaction::new_with_payer(
26 &[
27 // Create account
28 system_instruction::create_account(
29 &self.vote_authority.pubkey(),
30 &self.vote_account,
31 rent,
32 VoteState::size_of() as u64,
33 &solana_vote_program::id(),
34 ),
35 // Initialize vote account
36 vote_instruction::initialize_account(
37 &self.vote_account,
38 node_pubkey,
39 &self.vote_authority.pubkey(),
40 &self.withdraw_authority.pubkey(),
41 commission,
42 ),
43 ],
44 Some(&self.vote_authority.pubkey()),
45 );
46
47 Ok(transaction)
48 }
49
50 pub async fn update_commission(
51 &self,
52 new_commission: u8,
53 ) -> Result<Transaction, ProgramError> {
54 let transaction = Transaction::new_with_payer(
55 &[vote_instruction::update_commission(
56 &self.vote_account,
57 &self.withdraw_authority.pubkey(),
58 new_commission,
59 )],
60 Some(&self.withdraw_authority.pubkey()),
61 );
62
63 Ok(transaction)
64 }
65
66 pub async fn withdraw_rewards(
67 &self,
68 rewards_account: &Pubkey,
69 ) -> Result<Transaction, ProgramError> {
70 let balance = self.connection
71 .get_balance(&self.vote_account)
72 .await?;
73
74 let transaction = Transaction::new_with_payer(
75 &[vote_instruction::withdraw(
76 &self.vote_account,
77 &self.withdraw_authority.pubkey(),
78 balance,
79 rewards_account,
80 )],
81 Some(&self.withdraw_authority.pubkey()),
82 );
83
84 Ok(transaction)
85 }
86}
Tower BFT Implementation
Understand and interact with Solana's Tower BFT consensus protocol.
Tower BFT Interaction
1pub struct TowerBFT {
2 /// Vote state
3 pub vote_state: VoteState,
4
5 /// Root slot
6 pub root_slot: Slot,
7
8 /// Locked out slots
9 pub lockouts: Vec<Lockout>,
10
11 /// Last voted slot
12 pub last_voted_slot: Option<Slot>,
13}
14
15impl TowerBFT {
16 pub fn process_vote(
17 &mut self,
18 slot: Slot,
19 hash: Hash,
20 ) -> Result<Vote, ProgramError> {
21 // Check if slot is locked out
22 if self.is_locked_out(slot) {
23 return Err(ProgramError::InvalidArgument);
24 }
25
26 // Create vote
27 let vote = Vote::new(vec![slot], hash);
28
29 // Update lockouts
30 self.lockouts.push(Lockout {
31 slot,
32 confirmation_count: 0,
33 });
34
35 // Update last voted slot
36 self.last_voted_slot = Some(slot);
37
38 Ok(vote)
39 }
40
41 pub fn is_locked_out(&self, slot: Slot) -> bool {
42 self.lockouts.iter().any(|lockout| {
43 lockout.slot >= slot
44 && lockout.confirmation_count > MINIMUM_CONFIRMATIONS
45 })
46 }
47
48 pub fn process_new_root(
49 &mut self,
50 root: Slot,
51 ) -> Result<(), ProgramError> {
52 // Update root
53 self.root_slot = root;
54
55 // Prune lockouts
56 self.lockouts.retain(|lockout| lockout.slot > root);
57
58 Ok(())
59 }
60}
Slashing Protection
Implement robust slashing protection mechanisms.
Slashing Protection Implementation
1pub struct SlashingProtector {
2 /// Validator vote account
3 pub vote_account: Pubkey,
4
5 /// Stake account
6 pub stake_account: Pubkey,
7
8 /// Monitoring thresholds
9 pub thresholds: SlashingThresholds,
10
11 /// Historical performance
12 pub history: VoteHistory,
13}
14
15impl SlashingProtector {
16 pub async fn check_validator_behavior(
17 &self,
18 connection: &RpcClient,
19 ) -> Result<ValidatorStatus, ProgramError> {
20 // Get vote account status
21 let vote_account = connection
22 .get_vote_account(&self.vote_account)
23 .await?;
24
25 // Check for double voting
26 if self.detect_double_voting(&vote_account)? {
27 return Ok(ValidatorStatus::DoubleVoting);
28 }
29
30 // Check for skip rate
31 let skip_rate = self.calculate_skip_rate(&vote_account)?;
32 if skip_rate > self.thresholds.max_skip_rate {
33 return Ok(ValidatorStatus::ExcessiveSkips);
34 }
35
36 // Check for downtime
37 let uptime = self.calculate_uptime(&vote_account)?;
38 if uptime < self.thresholds.min_uptime {
39 return Ok(ValidatorStatus::Downtime);
40 }
41
42 Ok(ValidatorStatus::Healthy)
43 }
44
45 pub async fn handle_slashing_event(
46 &self,
47 connection: &RpcClient,
48 status: ValidatorStatus,
49 ) -> Result<Transaction, ProgramError> {
50 match status {
51 ValidatorStatus::DoubleVoting => {
52 // Emergency unstake all funds
53 self.emergency_unstake(connection).await
54 }
55 ValidatorStatus::ExcessiveSkips | ValidatorStatus::Downtime => {
56 // Partial unstake based on severity
57 let unstake_amount = self.calculate_unstake_amount(status)?;
58 self.partial_unstake(connection, unstake_amount).await
59 }
60 ValidatorStatus::Healthy => Ok(Transaction::default()),
61 }
62 }
63
64 async fn emergency_unstake(
65 &self,
66 connection: &RpcClient,
67 ) -> Result<Transaction, ProgramError> {
68 // Create emergency unstake instruction
69 let instruction = stake::instruction::deactivate_stake(
70 &self.stake_account,
71 &self.stake_authority,
72 );
73
74 // Build and return transaction
75 let transaction = Transaction::new_with_payer(
76 &[instruction],
77 Some(&self.stake_authority),
78 );
79
80 Ok(transaction)
81 }
82
83 fn detect_double_voting(
84 &self,
85 vote_account: &VoteAccountStatus,
86 ) -> Result<bool, ProgramError> {
87 // Check for conflicting votes in history
88 for votes in vote_account.votes.windows(2) {
89 if votes[0].slot >= votes[1].slot {
90 return Ok(true);
91 }
92 }
93
94 Ok(false)
95 }
96}
Performance Monitoring
Implement comprehensive validator performance monitoring.
Performance Monitoring Implementation
1pub struct ValidatorMonitor {
2 /// RPC connection
3 pub connection: Arc<RpcClient>,
4
5 /// Metrics client
6 pub metrics: Arc<MetricsClient>,
7
8 /// Alert system
9 pub alerts: Arc<AlertSystem>,
10
11 /// Monitoring thresholds
12 pub thresholds: MonitoringThresholds,
13}
14
15impl ValidatorMonitor {
16 pub async fn monitor_validator_performance(
17 &self,
18 vote_account: &Pubkey,
19 ) -> Result<ValidatorMetrics, ProgramError> {
20 // Get vote account status
21 let status = self.connection
22 .get_vote_account(vote_account)
23 .await?;
24
25 // Calculate metrics
26 let metrics = ValidatorMetrics {
27 epoch_credits: status.epoch_credits,
28 skip_rate: self.calculate_skip_rate(&status)?,
29 uptime: self.calculate_uptime(&status)?,
30 commission: status.commission,
31 last_vote: status.last_vote,
32 };
33
34 // Check thresholds
35 self.check_thresholds(&metrics).await?;
36
37 // Record metrics
38 self.record_metrics(vote_account, &metrics).await?;
39
40 Ok(metrics)
41 }
42
43 async fn check_thresholds(
44 &self,
45 metrics: &ValidatorMetrics,
46 ) -> Result<(), ProgramError> {
47 // Check skip rate
48 if metrics.skip_rate > self.thresholds.max_skip_rate {
49 self.alerts.send_alert(
50 AlertType::HighSkipRate {
51 skip_rate: metrics.skip_rate,
52 threshold: self.thresholds.max_skip_rate,
53 },
54 ).await?;
55 }
56
57 // Check uptime
58 if metrics.uptime < self.thresholds.min_uptime {
59 self.alerts.send_alert(
60 AlertType::LowUptime {
61 uptime: metrics.uptime,
62 threshold: self.thresholds.min_uptime,
63 },
64 ).await?;
65 }
66
67 Ok(())
68 }
69
70 async fn record_metrics(
71 &self,
72 vote_account: &Pubkey,
73 metrics: &ValidatorMetrics,
74 ) -> Result<(), ProgramError> {
75 self.metrics.record_metrics(
76 vote_account,
77 &[
78 ("skip_rate", metrics.skip_rate),
79 ("uptime", metrics.uptime),
80 ("epoch_credits", metrics.epoch_credits as f64),
81 ("commission", metrics.commission as f64),
82 ],
83 ).await
84 }
85}
Consensus Considerations
- Implement proper stake delegation with lockup periods
- Monitor validator performance and vote history
- Implement robust slashing protection mechanisms
- Set up comprehensive performance monitoring
- Handle emergency situations with proper procedures
- Maintain detailed metrics and alerts