539 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			539 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
use solana_runtime::{
 | 
						|
    bank::Bank,
 | 
						|
    bank_client::BankClient,
 | 
						|
    genesis_utils::{create_genesis_config_with_leader, GenesisConfigInfo},
 | 
						|
};
 | 
						|
use solana_sdk::{
 | 
						|
    account_utils::StateMut,
 | 
						|
    client::SyncClient,
 | 
						|
    message::Message,
 | 
						|
    pubkey::Pubkey,
 | 
						|
    signature::{Keypair, Signer},
 | 
						|
    system_instruction::SystemError,
 | 
						|
    sysvar::{self, stake_history::StakeHistory, Sysvar},
 | 
						|
    transaction::TransactionError,
 | 
						|
};
 | 
						|
use solana_stake_program::{
 | 
						|
    stake_instruction::{self},
 | 
						|
    stake_state::{self, StakeState},
 | 
						|
};
 | 
						|
use solana_vote_program::{
 | 
						|
    vote_instruction,
 | 
						|
    vote_state::{Vote, VoteInit, VoteState, VoteStateVersions},
 | 
						|
};
 | 
						|
use std::sync::Arc;
 | 
						|
 | 
						|
fn next_epoch(bank: &Arc<Bank>) -> Arc<Bank> {
 | 
						|
    bank.squash();
 | 
						|
 | 
						|
    Arc::new(Bank::new_from_parent(
 | 
						|
        &bank,
 | 
						|
        &Pubkey::default(),
 | 
						|
        bank.get_slots_in_epoch(bank.epoch()) + bank.slot(),
 | 
						|
    ))
 | 
						|
}
 | 
						|
 | 
						|
fn fill_epoch_with_votes(
 | 
						|
    bank: &Arc<Bank>,
 | 
						|
    vote_keypair: &Keypair,
 | 
						|
    mint_keypair: &Keypair,
 | 
						|
) -> Arc<Bank> {
 | 
						|
    let mint_pubkey = mint_keypair.pubkey();
 | 
						|
    let vote_pubkey = vote_keypair.pubkey();
 | 
						|
    let old_epoch = bank.epoch();
 | 
						|
    let mut bank = bank.clone();
 | 
						|
    while bank.epoch() != old_epoch + 1 {
 | 
						|
        bank.squash();
 | 
						|
        bank = Arc::new(Bank::new_from_parent(
 | 
						|
            &bank,
 | 
						|
            &Pubkey::default(),
 | 
						|
            1 + bank.slot(),
 | 
						|
        ));
 | 
						|
 | 
						|
        let bank_client = BankClient::new_shared(&bank);
 | 
						|
        let parent = bank.parent().unwrap();
 | 
						|
 | 
						|
        let message = Message::new_with_payer(
 | 
						|
            &[vote_instruction::vote(
 | 
						|
                &vote_pubkey,
 | 
						|
                &vote_pubkey,
 | 
						|
                Vote::new(vec![parent.slot() as u64], parent.hash()),
 | 
						|
            )],
 | 
						|
            Some(&mint_pubkey),
 | 
						|
        );
 | 
						|
        assert!(bank_client
 | 
						|
            .send_message(&[mint_keypair, vote_keypair], message)
 | 
						|
            .is_ok());
 | 
						|
    }
 | 
						|
    bank
 | 
						|
}
 | 
						|
 | 
						|
fn warmed_up(bank: &Bank, stake_pubkey: &Pubkey) -> bool {
 | 
						|
    let stake = StakeState::stake_from(&bank.get_account(stake_pubkey).unwrap()).unwrap();
 | 
						|
 | 
						|
    stake.delegation.stake
 | 
						|
        == stake.stake(
 | 
						|
            bank.epoch(),
 | 
						|
            Some(
 | 
						|
                &StakeHistory::from_account(
 | 
						|
                    &bank.get_account(&sysvar::stake_history::id()).unwrap(),
 | 
						|
                )
 | 
						|
                .unwrap(),
 | 
						|
            ),
 | 
						|
        )
 | 
						|
}
 | 
						|
 | 
						|
fn get_staked(bank: &Bank, stake_pubkey: &Pubkey) -> u64 {
 | 
						|
    StakeState::stake_from(&bank.get_account(stake_pubkey).unwrap())
 | 
						|
        .unwrap()
 | 
						|
        .stake(
 | 
						|
            bank.epoch(),
 | 
						|
            Some(
 | 
						|
                &StakeHistory::from_account(
 | 
						|
                    &bank.get_account(&sysvar::stake_history::id()).unwrap(),
 | 
						|
                )
 | 
						|
                .unwrap(),
 | 
						|
            ),
 | 
						|
        )
 | 
						|
}
 | 
						|
 | 
						|
#[test]
 | 
						|
fn test_stake_create_and_split_single_signature() {
 | 
						|
    solana_logger::setup();
 | 
						|
 | 
						|
    let GenesisConfigInfo {
 | 
						|
        genesis_config,
 | 
						|
        mint_keypair: staker_keypair,
 | 
						|
        ..
 | 
						|
    } = create_genesis_config_with_leader(100_000_000_000, &Pubkey::new_rand(), 1_000_000);
 | 
						|
 | 
						|
    let staker_pubkey = staker_keypair.pubkey();
 | 
						|
 | 
						|
    let bank_client = BankClient::new_shared(&Arc::new(Bank::new(&genesis_config)));
 | 
						|
 | 
						|
    let stake_address =
 | 
						|
        Pubkey::create_with_seed(&staker_pubkey, "stake", &solana_stake_program::id()).unwrap();
 | 
						|
 | 
						|
    let authorized = stake_state::Authorized::auto(&staker_pubkey);
 | 
						|
 | 
						|
    let lamports = 1_000_000;
 | 
						|
 | 
						|
    // Create stake account with seed
 | 
						|
    let message = Message::new(&stake_instruction::create_account_with_seed(
 | 
						|
        &staker_pubkey, // from
 | 
						|
        &stake_address, // to
 | 
						|
        &staker_pubkey, // base
 | 
						|
        "stake",        // seed
 | 
						|
        &authorized,
 | 
						|
        &stake_state::Lockup::default(),
 | 
						|
        lamports,
 | 
						|
    ));
 | 
						|
 | 
						|
    // only one signature required
 | 
						|
    bank_client
 | 
						|
        .send_message(&[&staker_keypair], message)
 | 
						|
        .expect("failed to create and delegate stake account");
 | 
						|
 | 
						|
    // split the stake
 | 
						|
    let split_stake_address =
 | 
						|
        Pubkey::create_with_seed(&staker_pubkey, "split_stake", &solana_stake_program::id())
 | 
						|
            .unwrap();
 | 
						|
    // Test split
 | 
						|
    let message = Message::new_with_payer(
 | 
						|
        &stake_instruction::split_with_seed(
 | 
						|
            &stake_address, // original
 | 
						|
            &staker_pubkey, // authorized
 | 
						|
            lamports / 2,
 | 
						|
            &split_stake_address, // new address
 | 
						|
            &staker_pubkey,       // base
 | 
						|
            "split_stake",        // seed
 | 
						|
        ),
 | 
						|
        Some(&staker_keypair.pubkey()),
 | 
						|
    );
 | 
						|
 | 
						|
    assert!(bank_client
 | 
						|
        .send_message(&[&staker_keypair], message)
 | 
						|
        .is_ok());
 | 
						|
 | 
						|
    // w00t!
 | 
						|
}
 | 
						|
 | 
						|
#[test]
 | 
						|
fn test_stake_create_and_split_to_existing_system_account() {
 | 
						|
    // Ensure stake-split does not allow the user to promote an existing system account into
 | 
						|
    // a stake account.
 | 
						|
 | 
						|
    solana_logger::setup();
 | 
						|
 | 
						|
    let GenesisConfigInfo {
 | 
						|
        genesis_config,
 | 
						|
        mint_keypair: staker_keypair,
 | 
						|
        ..
 | 
						|
    } = create_genesis_config_with_leader(100_000_000_000, &Pubkey::new_rand(), 1_000_000);
 | 
						|
 | 
						|
    let staker_pubkey = staker_keypair.pubkey();
 | 
						|
 | 
						|
    let bank_client = BankClient::new_shared(&Arc::new(Bank::new(&genesis_config)));
 | 
						|
 | 
						|
    let stake_address =
 | 
						|
        Pubkey::create_with_seed(&staker_pubkey, "stake", &solana_stake_program::id()).unwrap();
 | 
						|
 | 
						|
    let authorized = stake_state::Authorized::auto(&staker_pubkey);
 | 
						|
 | 
						|
    let lamports = 1_000_000;
 | 
						|
 | 
						|
    // Create stake account with seed
 | 
						|
    let message = Message::new(&stake_instruction::create_account_with_seed(
 | 
						|
        &staker_pubkey, // from
 | 
						|
        &stake_address, // to
 | 
						|
        &staker_pubkey, // base
 | 
						|
        "stake",        // seed
 | 
						|
        &authorized,
 | 
						|
        &stake_state::Lockup::default(),
 | 
						|
        lamports,
 | 
						|
    ));
 | 
						|
 | 
						|
    bank_client
 | 
						|
        .send_message(&[&staker_keypair], message)
 | 
						|
        .expect("failed to create and delegate stake account");
 | 
						|
 | 
						|
    let split_stake_address =
 | 
						|
        Pubkey::create_with_seed(&staker_pubkey, "split_stake", &solana_stake_program::id())
 | 
						|
            .unwrap();
 | 
						|
 | 
						|
    // First, put a system account where we want the new stake account
 | 
						|
    let existing_lamports = 42;
 | 
						|
    bank_client
 | 
						|
        .transfer(existing_lamports, &staker_keypair, &split_stake_address)
 | 
						|
        .unwrap();
 | 
						|
    assert_eq!(
 | 
						|
        bank_client.get_balance(&split_stake_address).unwrap(),
 | 
						|
        existing_lamports
 | 
						|
    );
 | 
						|
 | 
						|
    // Verify the split fails because the account is already in use
 | 
						|
    let message = Message::new_with_payer(
 | 
						|
        &stake_instruction::split_with_seed(
 | 
						|
            &stake_address, // original
 | 
						|
            &staker_pubkey, // authorized
 | 
						|
            lamports / 2,
 | 
						|
            &split_stake_address, // new address
 | 
						|
            &staker_pubkey,       // base
 | 
						|
            "split_stake",        // seed
 | 
						|
        ),
 | 
						|
        Some(&staker_keypair.pubkey()),
 | 
						|
    );
 | 
						|
    assert_eq!(
 | 
						|
        bank_client
 | 
						|
            .send_message(&[&staker_keypair], message)
 | 
						|
            .unwrap_err()
 | 
						|
            .unwrap(),
 | 
						|
        TransactionError::InstructionError(0, SystemError::AccountAlreadyInUse.into())
 | 
						|
    );
 | 
						|
    assert_eq!(
 | 
						|
        bank_client.get_balance(&split_stake_address).unwrap(),
 | 
						|
        existing_lamports
 | 
						|
    );
 | 
						|
}
 | 
						|
 | 
						|
#[test]
 | 
						|
fn test_stake_account_lifetime() {
 | 
						|
    let stake_keypair = Keypair::new();
 | 
						|
    let stake_pubkey = stake_keypair.pubkey();
 | 
						|
    let vote_keypair = Keypair::new();
 | 
						|
    let vote_pubkey = vote_keypair.pubkey();
 | 
						|
    let identity_keypair = Keypair::new();
 | 
						|
    let identity_pubkey = identity_keypair.pubkey();
 | 
						|
 | 
						|
    let GenesisConfigInfo {
 | 
						|
        genesis_config,
 | 
						|
        mint_keypair,
 | 
						|
        ..
 | 
						|
    } = create_genesis_config_with_leader(100_000_000_000, &Pubkey::new_rand(), 1_000_000);
 | 
						|
    let bank = Bank::new(&genesis_config);
 | 
						|
    let mint_pubkey = mint_keypair.pubkey();
 | 
						|
    let mut bank = Arc::new(bank);
 | 
						|
    let bank_client = BankClient::new_shared(&bank);
 | 
						|
 | 
						|
    // Create Vote Account
 | 
						|
    let message = Message::new(&vote_instruction::create_account(
 | 
						|
        &mint_pubkey,
 | 
						|
        &vote_pubkey,
 | 
						|
        &VoteInit {
 | 
						|
            node_pubkey: identity_pubkey,
 | 
						|
            authorized_voter: vote_pubkey,
 | 
						|
            authorized_withdrawer: vote_pubkey,
 | 
						|
            commission: 50,
 | 
						|
        },
 | 
						|
        10,
 | 
						|
    ));
 | 
						|
    bank_client
 | 
						|
        .send_message(&[&mint_keypair, &vote_keypair, &identity_keypair], message)
 | 
						|
        .expect("failed to create vote account");
 | 
						|
 | 
						|
    let authorized = stake_state::Authorized::auto(&stake_pubkey);
 | 
						|
    // Create stake account and delegate to vote account
 | 
						|
    let message = Message::new(&stake_instruction::create_account_and_delegate_stake(
 | 
						|
        &mint_pubkey,
 | 
						|
        &stake_pubkey,
 | 
						|
        &vote_pubkey,
 | 
						|
        &authorized,
 | 
						|
        &stake_state::Lockup::default(),
 | 
						|
        1_000_000,
 | 
						|
    ));
 | 
						|
    bank_client
 | 
						|
        .send_message(&[&mint_keypair, &stake_keypair], message)
 | 
						|
        .expect("failed to create and delegate stake account");
 | 
						|
 | 
						|
    // Test that correct lamports are staked
 | 
						|
    let account = bank.get_account(&stake_pubkey).expect("account not found");
 | 
						|
    let stake_state = account.state().expect("couldn't unpack account data");
 | 
						|
    if let StakeState::Stake(_meta, stake) = stake_state {
 | 
						|
        assert_eq!(stake.delegation.stake, 1_000_000);
 | 
						|
    } else {
 | 
						|
        panic!("wrong account type found")
 | 
						|
    }
 | 
						|
 | 
						|
    // Test that we cannot withdraw anything until deactivation
 | 
						|
    let message = Message::new_with_payer(
 | 
						|
        &[stake_instruction::withdraw(
 | 
						|
            &stake_pubkey,
 | 
						|
            &stake_pubkey,
 | 
						|
            &Pubkey::new_rand(),
 | 
						|
            1,
 | 
						|
            None,
 | 
						|
        )],
 | 
						|
        Some(&mint_pubkey),
 | 
						|
    );
 | 
						|
    assert!(bank_client
 | 
						|
        .send_message(&[&mint_keypair, &stake_keypair], message)
 | 
						|
        .is_err());
 | 
						|
 | 
						|
    // Test that lamports are still staked
 | 
						|
    let account = bank.get_account(&stake_pubkey).expect("account not found");
 | 
						|
    let stake_state = account.state().expect("couldn't unpack account data");
 | 
						|
    if let StakeState::Stake(_meta, stake) = stake_state {
 | 
						|
        assert_eq!(stake.delegation.stake, 1_000_000);
 | 
						|
    } else {
 | 
						|
        panic!("wrong account type found")
 | 
						|
    }
 | 
						|
 | 
						|
    loop {
 | 
						|
        if warmed_up(&bank, &stake_pubkey) {
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        // Cycle thru banks until we're fully warmed up
 | 
						|
        bank = next_epoch(&bank);
 | 
						|
    }
 | 
						|
 | 
						|
    // Reward redemption
 | 
						|
    // Submit enough votes to generate rewards
 | 
						|
    bank = fill_epoch_with_votes(&bank, &vote_keypair, &mint_keypair);
 | 
						|
 | 
						|
    // Test that votes and credits are there
 | 
						|
    let account = bank.get_account(&vote_pubkey).expect("account not found");
 | 
						|
    let vote_state: VoteState = StateMut::<VoteStateVersions>::state(&account)
 | 
						|
        .expect("couldn't unpack account data")
 | 
						|
        .convert_to_current();
 | 
						|
 | 
						|
    // 1 less vote, as the first vote should have cleared the lockout
 | 
						|
    assert_eq!(vote_state.votes.len(), 31);
 | 
						|
    // one vote per slot, might be more slots than 32 in the epoch
 | 
						|
    assert!(vote_state.credits() >= 1);
 | 
						|
    bank = fill_epoch_with_votes(&bank, &vote_keypair, &mint_keypair);
 | 
						|
 | 
						|
    let pre_staked = get_staked(&bank, &stake_pubkey);
 | 
						|
 | 
						|
    // next epoch bank should pay rewards
 | 
						|
    bank = next_epoch(&bank);
 | 
						|
 | 
						|
    // Test that balance increased, and that the balance got staked
 | 
						|
    let staked = get_staked(&bank, &stake_pubkey);
 | 
						|
    let lamports = bank.get_balance(&stake_pubkey);
 | 
						|
    assert!(staked > pre_staked);
 | 
						|
    assert!(lamports > 1_000_000);
 | 
						|
 | 
						|
    // split the stake
 | 
						|
    let split_stake_keypair = Keypair::new();
 | 
						|
    let split_stake_pubkey = split_stake_keypair.pubkey();
 | 
						|
 | 
						|
    let bank_client = BankClient::new_shared(&bank);
 | 
						|
    // Test split
 | 
						|
    let message = Message::new_with_payer(
 | 
						|
        &stake_instruction::split(
 | 
						|
            &stake_pubkey,
 | 
						|
            &stake_pubkey,
 | 
						|
            lamports / 2,
 | 
						|
            &split_stake_pubkey,
 | 
						|
        ),
 | 
						|
        Some(&mint_pubkey),
 | 
						|
    );
 | 
						|
    assert!(bank_client
 | 
						|
        .send_message(
 | 
						|
            &[&mint_keypair, &stake_keypair, &split_stake_keypair],
 | 
						|
            message
 | 
						|
        )
 | 
						|
        .is_ok());
 | 
						|
 | 
						|
    // Deactivate the split
 | 
						|
    let message = Message::new_with_payer(
 | 
						|
        &[stake_instruction::deactivate_stake(
 | 
						|
            &split_stake_pubkey,
 | 
						|
            &stake_pubkey,
 | 
						|
        )],
 | 
						|
        Some(&mint_pubkey),
 | 
						|
    );
 | 
						|
    assert!(bank_client
 | 
						|
        .send_message(&[&mint_keypair, &stake_keypair], message)
 | 
						|
        .is_ok());
 | 
						|
 | 
						|
    let split_staked = get_staked(&bank, &split_stake_pubkey);
 | 
						|
 | 
						|
    // Test that we cannot withdraw above what's staked
 | 
						|
    let message = Message::new_with_payer(
 | 
						|
        &[stake_instruction::withdraw(
 | 
						|
            &split_stake_pubkey,
 | 
						|
            &stake_pubkey,
 | 
						|
            &Pubkey::new_rand(),
 | 
						|
            lamports / 2 - split_staked + 1,
 | 
						|
            None,
 | 
						|
        )],
 | 
						|
        Some(&mint_pubkey),
 | 
						|
    );
 | 
						|
    assert!(bank_client
 | 
						|
        .send_message(&[&mint_keypair, &stake_keypair], message)
 | 
						|
        .is_err());
 | 
						|
 | 
						|
    let mut bank = next_epoch(&bank);
 | 
						|
    let bank_client = BankClient::new_shared(&bank);
 | 
						|
 | 
						|
    // assert we're still cooling down
 | 
						|
    let split_staked = get_staked(&bank, &split_stake_pubkey);
 | 
						|
    assert!(split_staked > 0);
 | 
						|
 | 
						|
    // withdrawal in cooldown
 | 
						|
    let message = Message::new_with_payer(
 | 
						|
        &[stake_instruction::withdraw(
 | 
						|
            &split_stake_pubkey,
 | 
						|
            &stake_pubkey,
 | 
						|
            &Pubkey::new_rand(),
 | 
						|
            lamports / 2,
 | 
						|
            None,
 | 
						|
        )],
 | 
						|
        Some(&mint_pubkey),
 | 
						|
    );
 | 
						|
 | 
						|
    assert!(bank_client
 | 
						|
        .send_message(&[&mint_keypair, &stake_keypair], message)
 | 
						|
        .is_err());
 | 
						|
 | 
						|
    // but we can withdraw unstaked
 | 
						|
    let message = Message::new_with_payer(
 | 
						|
        &[stake_instruction::withdraw(
 | 
						|
            &split_stake_pubkey,
 | 
						|
            &stake_pubkey,
 | 
						|
            &Pubkey::new_rand(),
 | 
						|
            lamports / 2 - split_staked,
 | 
						|
            None,
 | 
						|
        )],
 | 
						|
        Some(&mint_pubkey),
 | 
						|
    );
 | 
						|
    // assert we can withdraw unstaked tokens
 | 
						|
    assert!(bank_client
 | 
						|
        .send_message(&[&mint_keypair, &stake_keypair], message)
 | 
						|
        .is_ok());
 | 
						|
 | 
						|
    // finish cooldown
 | 
						|
    loop {
 | 
						|
        if get_staked(&bank, &split_stake_pubkey) == 0 {
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        bank = next_epoch(&bank);
 | 
						|
    }
 | 
						|
    let bank_client = BankClient::new_shared(&bank);
 | 
						|
 | 
						|
    // Test that we can withdraw everything else out of the split
 | 
						|
    let message = Message::new_with_payer(
 | 
						|
        &[stake_instruction::withdraw(
 | 
						|
            &split_stake_pubkey,
 | 
						|
            &stake_pubkey,
 | 
						|
            &Pubkey::new_rand(),
 | 
						|
            split_staked,
 | 
						|
            None,
 | 
						|
        )],
 | 
						|
        Some(&mint_pubkey),
 | 
						|
    );
 | 
						|
    assert!(bank_client
 | 
						|
        .send_message(&[&mint_keypair, &stake_keypair], message)
 | 
						|
        .is_ok());
 | 
						|
 | 
						|
    // verify all the math sums to zero
 | 
						|
    assert_eq!(bank.get_balance(&split_stake_pubkey), 0);
 | 
						|
    assert_eq!(bank.get_balance(&stake_pubkey), lamports - lamports / 2);
 | 
						|
}
 | 
						|
 | 
						|
#[test]
 | 
						|
fn test_create_stake_account_from_seed() {
 | 
						|
    let vote_keypair = Keypair::new();
 | 
						|
    let vote_pubkey = vote_keypair.pubkey();
 | 
						|
    let identity_keypair = Keypair::new();
 | 
						|
    let identity_pubkey = identity_keypair.pubkey();
 | 
						|
 | 
						|
    let GenesisConfigInfo {
 | 
						|
        genesis_config,
 | 
						|
        mint_keypair,
 | 
						|
        ..
 | 
						|
    } = create_genesis_config_with_leader(100_000_000_000, &Pubkey::new_rand(), 1_000_000);
 | 
						|
    let bank = Bank::new(&genesis_config);
 | 
						|
    let mint_pubkey = mint_keypair.pubkey();
 | 
						|
    let bank = Arc::new(bank);
 | 
						|
    let bank_client = BankClient::new_shared(&bank);
 | 
						|
 | 
						|
    let seed = "test-string";
 | 
						|
    let stake_pubkey =
 | 
						|
        Pubkey::create_with_seed(&mint_pubkey, seed, &solana_stake_program::id()).unwrap();
 | 
						|
 | 
						|
    // Create Vote Account
 | 
						|
    let message = Message::new(&vote_instruction::create_account(
 | 
						|
        &mint_pubkey,
 | 
						|
        &vote_pubkey,
 | 
						|
        &VoteInit {
 | 
						|
            node_pubkey: identity_pubkey,
 | 
						|
            authorized_voter: vote_pubkey,
 | 
						|
            authorized_withdrawer: vote_pubkey,
 | 
						|
            commission: 50,
 | 
						|
        },
 | 
						|
        10,
 | 
						|
    ));
 | 
						|
    bank_client
 | 
						|
        .send_message(&[&mint_keypair, &vote_keypair, &identity_keypair], message)
 | 
						|
        .expect("failed to create vote account");
 | 
						|
 | 
						|
    let authorized = stake_state::Authorized::auto(&mint_pubkey);
 | 
						|
    // Create stake account and delegate to vote account
 | 
						|
    let message = Message::new(
 | 
						|
        &stake_instruction::create_account_with_seed_and_delegate_stake(
 | 
						|
            &mint_pubkey,
 | 
						|
            &stake_pubkey,
 | 
						|
            &mint_pubkey,
 | 
						|
            seed,
 | 
						|
            &vote_pubkey,
 | 
						|
            &authorized,
 | 
						|
            &stake_state::Lockup::default(),
 | 
						|
            1_000_000,
 | 
						|
        ),
 | 
						|
    );
 | 
						|
    bank_client
 | 
						|
        .send_message(&[&mint_keypair], message)
 | 
						|
        .expect("failed to create and delegate stake account");
 | 
						|
 | 
						|
    // Test that correct lamports are staked
 | 
						|
    let account = bank.get_account(&stake_pubkey).expect("account not found");
 | 
						|
    let stake_state = account.state().expect("couldn't unpack account data");
 | 
						|
    if let StakeState::Stake(_meta, stake) = stake_state {
 | 
						|
        assert_eq!(stake.delegation.stake, 1_000_000);
 | 
						|
    } else {
 | 
						|
        panic!("wrong account type found")
 | 
						|
    }
 | 
						|
}
 |