switch over to passive stakes (#4295)
* add failing test * switch over to passive stakes * test multiple stakers
This commit is contained in:
@ -168,10 +168,9 @@ mod tests {
|
||||
use crate::blocktree::tests::make_slot_entries;
|
||||
use crate::genesis_utils::create_genesis_block;
|
||||
use crate::genesis_utils::{create_genesis_block_with_leader, BOOTSTRAP_LEADER_LAMPORTS};
|
||||
use crate::voting_keypair::tests::new_vote_account;
|
||||
use crate::staking_utils::tests::setup_vote_and_stake_accounts;
|
||||
use solana_runtime::bank::Bank;
|
||||
use solana_runtime::epoch_schedule::{EpochSchedule, MINIMUM_SLOT_LENGTH};
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||
use std::sync::mpsc::channel;
|
||||
use std::sync::Arc;
|
||||
use std::thread::Builder;
|
||||
@ -373,25 +372,20 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_next_leader_slot_next_epoch() {
|
||||
let pubkey = Pubkey::new_rand();
|
||||
let (mut genesis_block, mint_keypair, _voting_keypair) = create_genesis_block_with_leader(
|
||||
2 * BOOTSTRAP_LEADER_LAMPORTS,
|
||||
&pubkey,
|
||||
BOOTSTRAP_LEADER_LAMPORTS,
|
||||
);
|
||||
let (mut genesis_block, mint_keypair) = create_genesis_block(10_000);
|
||||
genesis_block.epoch_warmup = false;
|
||||
|
||||
let bank = Bank::new(&genesis_block);
|
||||
let cache = Arc::new(LeaderScheduleCache::new_from_bank(&bank));
|
||||
let delegate_id = Pubkey::new_rand();
|
||||
|
||||
// Create new vote account
|
||||
let new_voting_keypair = Keypair::new();
|
||||
new_vote_account(
|
||||
&mint_keypair,
|
||||
&new_voting_keypair,
|
||||
&delegate_id,
|
||||
let node_id = Pubkey::new_rand();
|
||||
let vote_id = Pubkey::new_rand();
|
||||
setup_vote_and_stake_accounts(
|
||||
&bank,
|
||||
&mint_keypair,
|
||||
&vote_id,
|
||||
&node_id,
|
||||
BOOTSTRAP_LEADER_LAMPORTS,
|
||||
);
|
||||
|
||||
@ -412,14 +406,14 @@ mod tests {
|
||||
|
||||
let schedule = cache.compute_epoch_schedule(epoch, &bank).unwrap();
|
||||
let mut index = 0;
|
||||
while schedule[index] != delegate_id {
|
||||
index += 1
|
||||
while schedule[index] != node_id {
|
||||
index += 1;
|
||||
assert_ne!(index, genesis_block.slots_per_epoch);
|
||||
}
|
||||
|
||||
expected_slot += index;
|
||||
|
||||
assert_eq!(
|
||||
cache.next_leader_slot(&delegate_id, 0, &bank, None),
|
||||
cache.next_leader_slot(&node_id, 0, &bank, None),
|
||||
Some(expected_slot),
|
||||
);
|
||||
}
|
||||
|
@ -67,7 +67,6 @@ pub mod streamer;
|
||||
pub mod test_tx;
|
||||
pub mod tpu;
|
||||
pub mod tvu;
|
||||
pub mod voting_keypair;
|
||||
pub mod window_service;
|
||||
|
||||
#[macro_use]
|
||||
@ -83,6 +82,8 @@ extern crate log;
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
extern crate serde_json;
|
||||
|
||||
|
@ -397,7 +397,6 @@ impl LocalCluster {
|
||||
),
|
||||
client.get_recent_blockhash().unwrap().0,
|
||||
);
|
||||
dbg!(vote_account_pubkey);
|
||||
client
|
||||
.retry_transfer(&from_account, &mut transaction, 5)
|
||||
.expect("fund vote");
|
||||
@ -407,7 +406,6 @@ impl LocalCluster {
|
||||
|
||||
let stake_account_keypair = Keypair::new();
|
||||
let stake_account_pubkey = stake_account_keypair.pubkey();
|
||||
dbg!(stake_account_pubkey);
|
||||
let mut transaction = Transaction::new_signed_instructions(
|
||||
&[from_account.as_ref()],
|
||||
vec![stake_instruction::create_account(
|
||||
@ -424,7 +422,6 @@ impl LocalCluster {
|
||||
client
|
||||
.wait_for_balance(&stake_account_pubkey, Some(amount))
|
||||
.expect("get balance");
|
||||
dbg!(amount);
|
||||
|
||||
let mut transaction = Transaction::new_signed_instructions(
|
||||
&[from_account.as_ref(), &stake_account_keypair],
|
||||
@ -443,7 +440,6 @@ impl LocalCluster {
|
||||
0,
|
||||
)
|
||||
.expect("delegate stake");
|
||||
dbg!("delegated");
|
||||
}
|
||||
info!("Checking for vote account registration");
|
||||
let vote_account_user_data = client.get_account_data(&vote_account_pubkey);
|
||||
|
@ -110,15 +110,18 @@ where
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
pub(crate) mod tests {
|
||||
use super::*;
|
||||
use crate::genesis_utils::{
|
||||
create_genesis_block, create_genesis_block_with_leader, BOOTSTRAP_LEADER_LAMPORTS,
|
||||
};
|
||||
use crate::voting_keypair::tests as voting_keypair_tests;
|
||||
use hashbrown::HashSet;
|
||||
use solana_sdk::instruction::Instruction;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::transaction::Transaction;
|
||||
use solana_stake_api::stake_instruction;
|
||||
use solana_vote_api::vote_instruction;
|
||||
use std::iter::FromIterator;
|
||||
use std::sync::Arc;
|
||||
|
||||
@ -148,14 +151,65 @@ pub mod tests {
|
||||
assert_eq!(vote_account_stakes_at_epoch(&bank, 1), expected);
|
||||
}
|
||||
|
||||
pub(crate) fn setup_vote_and_stake_accounts(
|
||||
bank: &Bank,
|
||||
from_account: &Keypair,
|
||||
vote_id: &Pubkey,
|
||||
node_id: &Pubkey,
|
||||
amount: u64,
|
||||
) {
|
||||
fn process_instructions<T: KeypairUtil>(
|
||||
bank: &Bank,
|
||||
keypairs: &[&T],
|
||||
ixs: Vec<Instruction>,
|
||||
) {
|
||||
bank.process_transaction(&Transaction::new_signed_instructions(
|
||||
keypairs,
|
||||
ixs,
|
||||
bank.last_blockhash(),
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
process_instructions(
|
||||
bank,
|
||||
&[from_account],
|
||||
vote_instruction::create_account(&from_account.pubkey(), vote_id, node_id, 0, amount),
|
||||
);
|
||||
|
||||
let stake_account_keypair = Keypair::new();
|
||||
let stake_account_pubkey = stake_account_keypair.pubkey();
|
||||
|
||||
process_instructions(
|
||||
bank,
|
||||
&[from_account],
|
||||
vec![stake_instruction::create_account(
|
||||
&from_account.pubkey(),
|
||||
&stake_account_pubkey,
|
||||
amount,
|
||||
)],
|
||||
);
|
||||
|
||||
process_instructions(
|
||||
bank,
|
||||
&[from_account, &stake_account_keypair],
|
||||
vec![stake_instruction::delegate_stake(
|
||||
&from_account.pubkey(),
|
||||
&stake_account_pubkey,
|
||||
vote_id,
|
||||
)],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_epoch_stakes_and_lockouts() {
|
||||
let stake = 42;
|
||||
let validator = Keypair::new();
|
||||
|
||||
let (genesis_block, mint_keypair) = create_genesis_block(500);
|
||||
let (genesis_block, mint_keypair) = create_genesis_block(10_000);
|
||||
|
||||
let bank = Bank::new(&genesis_block);
|
||||
let bank_voter = Keypair::new();
|
||||
let vote_id = Pubkey::new_rand();
|
||||
|
||||
// Give the validator some stake but don't setup a staking account
|
||||
// Validator has no lamports staked, so they get filtered out. Only the bootstrap leader
|
||||
@ -165,12 +219,12 @@ pub mod tests {
|
||||
|
||||
// Make a mint vote account. Because the mint has nonzero stake, this
|
||||
// should show up in the active set
|
||||
voting_keypair_tests::new_vote_account(
|
||||
&mint_keypair,
|
||||
&bank_voter,
|
||||
&mint_keypair.pubkey(),
|
||||
setup_vote_and_stake_accounts(
|
||||
&bank,
|
||||
499,
|
||||
&mint_keypair,
|
||||
&vote_id,
|
||||
&mint_keypair.pubkey(),
|
||||
stake,
|
||||
);
|
||||
|
||||
// soonest slot that could be a new epoch is 1
|
||||
@ -190,7 +244,7 @@ pub mod tests {
|
||||
|
||||
let result: HashSet<_> = HashSet::from_iter(epoch_stakes_and_lockouts(&bank, epoch));
|
||||
let expected: HashSet<_> =
|
||||
HashSet::from_iter(vec![(BOOTSTRAP_LEADER_LAMPORTS, None), (499, None)]);
|
||||
HashSet::from_iter(vec![(BOOTSTRAP_LEADER_LAMPORTS, None), (stake, None)]);
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
|
@ -1,167 +0,0 @@
|
||||
//! The `vote_signer_proxy` votes on the `blockhash` of the bank at a regular cadence
|
||||
|
||||
use jsonrpc_core;
|
||||
use solana_client::rpc_client::RpcClient;
|
||||
use solana_client::rpc_request::RpcRequest;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
||||
use solana_vote_signer::rpc::LocalVoteSigner;
|
||||
use solana_vote_signer::rpc::VoteSigner;
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct RemoteVoteSigner {
|
||||
rpc_client: RpcClient,
|
||||
}
|
||||
|
||||
impl RemoteVoteSigner {
|
||||
pub fn new(signer: SocketAddr) -> Self {
|
||||
let rpc_client = RpcClient::new_socket(signer);
|
||||
Self { rpc_client }
|
||||
}
|
||||
}
|
||||
|
||||
impl VoteSigner for RemoteVoteSigner {
|
||||
fn register(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
sig: &Signature,
|
||||
msg: &[u8],
|
||||
) -> jsonrpc_core::Result<Pubkey> {
|
||||
let params = json!([pubkey, sig, msg]);
|
||||
let resp = self
|
||||
.rpc_client
|
||||
.retry_make_rpc_request(&RpcRequest::RegisterNode, Some(params), 5)
|
||||
.unwrap();
|
||||
let vote_account: Pubkey = serde_json::from_value(resp).unwrap();
|
||||
Ok(vote_account)
|
||||
}
|
||||
fn sign(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
sig: &Signature,
|
||||
msg: &[u8],
|
||||
) -> jsonrpc_core::Result<Signature> {
|
||||
let params = json!([pubkey, sig, msg]);
|
||||
let resp = self
|
||||
.rpc_client
|
||||
.retry_make_rpc_request(&RpcRequest::SignVote, Some(params), 0)
|
||||
.unwrap();
|
||||
let vote_signature: Signature = serde_json::from_value(resp).unwrap();
|
||||
Ok(vote_signature)
|
||||
}
|
||||
fn deregister(&self, pubkey: &Pubkey, sig: &Signature, msg: &[u8]) -> jsonrpc_core::Result<()> {
|
||||
let params = json!([pubkey, sig, msg]);
|
||||
let _resp = self
|
||||
.rpc_client
|
||||
.retry_make_rpc_request(&RpcRequest::DeregisterNode, Some(params), 5)
|
||||
.unwrap();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl KeypairUtil for VotingKeypair {
|
||||
/// Return a local VotingKeypair with a new keypair. Used for unit-tests.
|
||||
fn new() -> Self {
|
||||
Self::new_with_signer(
|
||||
&Arc::new(Keypair::new()),
|
||||
Box::new(LocalVoteSigner::default()),
|
||||
)
|
||||
}
|
||||
|
||||
/// Return the public key of the keypair used to sign votes
|
||||
fn pubkey(&self) -> Pubkey {
|
||||
self.vote_account
|
||||
}
|
||||
|
||||
fn sign_message(&self, msg: &[u8]) -> Signature {
|
||||
let sig = self.keypair.sign_message(msg);
|
||||
self.signer
|
||||
.sign(&self.keypair.pubkey(), &sig, &msg)
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VotingKeypair {
|
||||
keypair: Arc<Keypair>,
|
||||
signer: Box<VoteSigner + Send + Sync>,
|
||||
vote_account: Pubkey,
|
||||
}
|
||||
|
||||
impl VotingKeypair {
|
||||
pub fn new_with_signer(keypair: &Arc<Keypair>, signer: Box<VoteSigner + Send + Sync>) -> Self {
|
||||
let msg = "Registering a new node";
|
||||
let sig = keypair.sign_message(msg.as_bytes());
|
||||
let vote_account = signer
|
||||
.register(&keypair.pubkey(), &sig, msg.as_bytes())
|
||||
.unwrap();
|
||||
Self {
|
||||
keypair: keypair.clone(),
|
||||
signer,
|
||||
vote_account,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use solana_runtime::bank::Bank;
|
||||
use solana_sdk::instruction::Instruction;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||
use solana_sdk::transaction::Transaction;
|
||||
use solana_vote_api::vote_instruction;
|
||||
use solana_vote_api::vote_state::Vote;
|
||||
|
||||
fn process_instructions<T: KeypairUtil>(bank: &Bank, keypairs: &[&T], ixs: Vec<Instruction>) {
|
||||
let blockhash = bank.last_blockhash();
|
||||
let tx = Transaction::new_signed_instructions(keypairs, ixs, blockhash);
|
||||
bank.process_transaction(&tx).unwrap();
|
||||
}
|
||||
|
||||
pub fn new_vote_account(
|
||||
from_keypair: &Keypair,
|
||||
voting_keypair: &Keypair,
|
||||
node_id: &Pubkey,
|
||||
bank: &Bank,
|
||||
lamports: u64,
|
||||
) {
|
||||
let voting_pubkey = voting_keypair.pubkey();
|
||||
let ixs = vote_instruction::create_account(
|
||||
&from_keypair.pubkey(),
|
||||
&voting_pubkey,
|
||||
node_id,
|
||||
0,
|
||||
lamports,
|
||||
);
|
||||
process_instructions(bank, &[from_keypair], ixs);
|
||||
}
|
||||
|
||||
pub fn push_vote<T: KeypairUtil>(voting_keypair: &T, bank: &Bank, slot: u64) {
|
||||
let ix = vote_instruction::vote(&voting_keypair.pubkey(), vec![Vote::new(slot)]);
|
||||
process_instructions(bank, &[voting_keypair], vec![ix]);
|
||||
}
|
||||
|
||||
pub fn new_vote_account_with_vote<T: KeypairUtil>(
|
||||
from_keypair: &T,
|
||||
voting_keypair: &T,
|
||||
node_id: &Pubkey,
|
||||
bank: &Bank,
|
||||
lamports: u64,
|
||||
slot: u64,
|
||||
) {
|
||||
let voting_pubkey = voting_keypair.pubkey();
|
||||
let mut ixs = vote_instruction::create_account(
|
||||
&from_keypair.pubkey(),
|
||||
&voting_pubkey,
|
||||
node_id,
|
||||
0,
|
||||
lamports,
|
||||
);
|
||||
ixs.push(vote_instruction::vote(
|
||||
&voting_pubkey,
|
||||
vec![Vote::new(slot)],
|
||||
));
|
||||
process_instructions(bank, &[from_keypair, voting_keypair], ixs);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user