Add storage mining pool (#4364)
* Add storage mining pool * Set gossip port * Add create-storage-mining-pool-account wallet command * Add claim-storage-reward wallet command * Create storage account upfront * Add storage program to genesis * Use STORAGE_ACCOUNT_SPACE * Fix tests * Add wallet commands to create validator/replicator storage accounts * Add create_validator_storage_account() * Storage stage no longer implicitly creates a storage account
This commit is contained in:
@ -15,6 +15,7 @@ serde = "1.0.91"
|
||||
serde_derive = "1.0.91"
|
||||
solana-logger = { path = "../../logger", version = "0.15.0" }
|
||||
solana-sdk = { path = "../../sdk", version = "0.15.0" }
|
||||
assert_matches = "1.3.0"
|
||||
|
||||
[dev-dependencies]
|
||||
solana-runtime = { path = "../../runtime", version = "0.15.0" }
|
||||
|
@ -2,6 +2,7 @@ use crate::get_segment_from_slot;
|
||||
use log::*;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use solana_sdk::account::Account;
|
||||
use solana_sdk::account::KeyedAccount;
|
||||
use solana_sdk::account_utils::State;
|
||||
use solana_sdk::hash::Hash;
|
||||
use solana_sdk::instruction::InstructionError;
|
||||
@ -42,8 +43,7 @@ pub struct CheckedProof {
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub enum StorageContract {
|
||||
//don't move this
|
||||
Default,
|
||||
Uninitialized, // Must be first (aka, 0)
|
||||
|
||||
ValidatorStorage {
|
||||
slot: u64,
|
||||
@ -58,6 +58,24 @@ pub enum StorageContract {
|
||||
/// Multiple validators can validate the same set of proofs so it needs a Vec
|
||||
reward_validations: HashMap<usize, HashMap<Hash, Vec<CheckedProof>>>,
|
||||
},
|
||||
|
||||
MiningPool,
|
||||
}
|
||||
|
||||
// utility function, used by Bank, tests, genesis
|
||||
pub fn create_validator_storage_account(lamports: u64) -> Account {
|
||||
let mut storage_account = Account::new(lamports, STORAGE_ACCOUNT_SPACE as usize, &crate::id());
|
||||
|
||||
storage_account
|
||||
.set_state(&StorageContract::ValidatorStorage {
|
||||
slot: 0,
|
||||
hash: Hash::default(),
|
||||
lockout_validations: HashMap::new(),
|
||||
reward_validations: HashMap::new(),
|
||||
})
|
||||
.expect("set_state");
|
||||
|
||||
storage_account
|
||||
}
|
||||
|
||||
pub struct StorageAccount<'a> {
|
||||
@ -69,6 +87,44 @@ impl<'a> StorageAccount<'a> {
|
||||
Self { account }
|
||||
}
|
||||
|
||||
pub fn initialize_mining_pool(&mut self) -> Result<(), InstructionError> {
|
||||
let storage_contract = &mut self.account.state()?;
|
||||
if let StorageContract::Uninitialized = storage_contract {
|
||||
*storage_contract = StorageContract::MiningPool;
|
||||
self.account.set_state(storage_contract)
|
||||
} else {
|
||||
Err(InstructionError::AccountAlreadyInitialized)?
|
||||
}
|
||||
}
|
||||
|
||||
pub fn initialize_replicator_storage(&mut self) -> Result<(), InstructionError> {
|
||||
let storage_contract = &mut self.account.state()?;
|
||||
if let StorageContract::Uninitialized = storage_contract {
|
||||
*storage_contract = StorageContract::ReplicatorStorage {
|
||||
proofs: HashMap::new(),
|
||||
reward_validations: HashMap::new(),
|
||||
};
|
||||
self.account.set_state(storage_contract)
|
||||
} else {
|
||||
Err(InstructionError::AccountAlreadyInitialized)?
|
||||
}
|
||||
}
|
||||
|
||||
pub fn initialize_validator_storage(&mut self) -> Result<(), InstructionError> {
|
||||
let storage_contract = &mut self.account.state()?;
|
||||
if let StorageContract::Uninitialized = storage_contract {
|
||||
*storage_contract = StorageContract::ValidatorStorage {
|
||||
slot: 0,
|
||||
hash: Hash::default(),
|
||||
lockout_validations: HashMap::new(),
|
||||
reward_validations: HashMap::new(),
|
||||
};
|
||||
self.account.set_state(storage_contract)
|
||||
} else {
|
||||
Err(InstructionError::AccountAlreadyInitialized)?
|
||||
}
|
||||
}
|
||||
|
||||
pub fn submit_mining_proof(
|
||||
&mut self,
|
||||
id: Pubkey,
|
||||
@ -78,13 +134,6 @@ impl<'a> StorageAccount<'a> {
|
||||
current_slot: u64,
|
||||
) -> Result<(), InstructionError> {
|
||||
let mut storage_contract = &mut self.account.state()?;
|
||||
if let StorageContract::Default = storage_contract {
|
||||
*storage_contract = StorageContract::ReplicatorStorage {
|
||||
proofs: HashMap::new(),
|
||||
reward_validations: HashMap::new(),
|
||||
};
|
||||
};
|
||||
|
||||
if let StorageContract::ReplicatorStorage { proofs, .. } = &mut storage_contract {
|
||||
let segment_index = get_segment_from_slot(slot);
|
||||
let current_segment = get_segment_from_slot(current_slot);
|
||||
@ -120,15 +169,6 @@ impl<'a> StorageAccount<'a> {
|
||||
current_slot: u64,
|
||||
) -> Result<(), InstructionError> {
|
||||
let mut storage_contract = &mut self.account.state()?;
|
||||
if let StorageContract::Default = storage_contract {
|
||||
*storage_contract = StorageContract::ValidatorStorage {
|
||||
slot: 0,
|
||||
hash: Hash::default(),
|
||||
lockout_validations: HashMap::new(),
|
||||
reward_validations: HashMap::new(),
|
||||
};
|
||||
};
|
||||
|
||||
if let StorageContract::ValidatorStorage {
|
||||
slot: state_slot,
|
||||
hash: state_hash,
|
||||
@ -165,15 +205,6 @@ impl<'a> StorageAccount<'a> {
|
||||
replicator_accounts: &mut [StorageAccount],
|
||||
) -> Result<(), InstructionError> {
|
||||
let mut storage_contract = &mut self.account.state()?;
|
||||
if let StorageContract::Default = storage_contract {
|
||||
*storage_contract = StorageContract::ValidatorStorage {
|
||||
slot: 0,
|
||||
hash: Hash::default(),
|
||||
lockout_validations: HashMap::new(),
|
||||
reward_validations: HashMap::new(),
|
||||
};
|
||||
};
|
||||
|
||||
if let StorageContract::ValidatorStorage {
|
||||
slot: state_slot,
|
||||
lockout_validations,
|
||||
@ -241,13 +272,11 @@ impl<'a> StorageAccount<'a> {
|
||||
|
||||
pub fn claim_storage_reward(
|
||||
&mut self,
|
||||
mining_pool: &mut KeyedAccount,
|
||||
slot: u64,
|
||||
current_slot: u64,
|
||||
) -> Result<(), InstructionError> {
|
||||
let mut storage_contract = &mut self.account.state()?;
|
||||
if let StorageContract::Default = storage_contract {
|
||||
Err(InstructionError::InvalidArgument)?
|
||||
};
|
||||
|
||||
if let StorageContract::ValidatorStorage {
|
||||
reward_validations,
|
||||
@ -266,14 +295,15 @@ impl<'a> StorageAccount<'a> {
|
||||
);
|
||||
return Err(InstructionError::InvalidArgument);
|
||||
}
|
||||
let _num_validations = count_valid_proofs(
|
||||
let num_validations = count_valid_proofs(
|
||||
&reward_validations
|
||||
.remove(&claim_segment)
|
||||
.map(|mut proofs| proofs.drain().map(|(_, proof)| proof).collect::<Vec<_>>())
|
||||
.unwrap_or_default(),
|
||||
);
|
||||
// TODO can't just create lamports out of thin air
|
||||
// self.account.lamports += TOTAL_VALIDATOR_REWARDS * num_validations;
|
||||
let reward = TOTAL_VALIDATOR_REWARDS * num_validations;
|
||||
mining_pool.account.lamports -= reward;
|
||||
self.account.lamports += reward;
|
||||
self.account.set_state(storage_contract)
|
||||
} else if let StorageContract::ReplicatorStorage {
|
||||
proofs,
|
||||
@ -288,7 +318,7 @@ impl<'a> StorageAccount<'a> {
|
||||
|| !reward_validations.contains_key(&claim_segment)
|
||||
|| !proofs.contains_key(&claim_segment)
|
||||
{
|
||||
debug!(
|
||||
info!(
|
||||
"current {:?}, claim {:?}, have rewards for {:?} segments",
|
||||
claim_index,
|
||||
claim_segment,
|
||||
@ -317,10 +347,15 @@ impl<'a> StorageAccount<'a> {
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let _num_validations = count_valid_proofs(&checked_proofs);
|
||||
// TODO can't just create lamports out of thin air
|
||||
// self.account.lamports += num_validations
|
||||
// * TOTAL_REPLICATOR_REWARDS
|
||||
// * (num_validations / reward_validations[claim_segment].len() as u64);
|
||||
|
||||
// TODO enable when rewards are working
|
||||
/*
|
||||
let reward = num_validations
|
||||
* TOTAL_REPLICATOR_REWARDS
|
||||
* (num_validations / reward_validations[&claim_segment].len() as u64);
|
||||
mining_pool.account.lamports -= reward;
|
||||
self.account.lamports += reward;
|
||||
*/
|
||||
self.account.set_state(storage_contract)
|
||||
} else {
|
||||
Err(InstructionError::InvalidArgument)?
|
||||
@ -399,7 +434,7 @@ mod tests {
|
||||
fn test_account_data() {
|
||||
solana_logger::setup();
|
||||
let mut account = Account::default();
|
||||
account.data.resize(4 * 1024, 0);
|
||||
account.data.resize(STORAGE_ACCOUNT_SPACE as usize, 0);
|
||||
let storage_account = StorageAccount::new(&mut account);
|
||||
// pretend it's a validator op code
|
||||
let mut contract = storage_account.account.state().unwrap();
|
||||
@ -454,9 +489,12 @@ mod tests {
|
||||
// account has no space
|
||||
process_validation(&mut account, segment_index, &proof, &checked_proof).unwrap_err();
|
||||
|
||||
account.account.data.resize(4 * 1024, 0);
|
||||
account
|
||||
.account
|
||||
.data
|
||||
.resize(STORAGE_ACCOUNT_SPACE as usize, 0);
|
||||
let storage_contract = &mut account.account.state().unwrap();
|
||||
if let StorageContract::Default = storage_contract {
|
||||
if let StorageContract::Uninitialized = storage_contract {
|
||||
let mut proof_map = HashMap::new();
|
||||
proof_map.insert(proof.sha_state, proof.clone());
|
||||
let mut proofs = HashMap::new();
|
||||
|
@ -9,6 +9,14 @@ use solana_sdk::system_instruction;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub enum StorageInstruction {
|
||||
/// Initialize the account as a mining pool, validator or replicator
|
||||
///
|
||||
/// Expects 1 Account:
|
||||
/// 0 - Account to be initialized
|
||||
InitializeMiningPool,
|
||||
InitializeValidatorStorage,
|
||||
InitializeReplicatorStorage,
|
||||
|
||||
SubmitMiningProof {
|
||||
sha_state: Hash,
|
||||
slot: u64,
|
||||
@ -18,6 +26,11 @@ pub enum StorageInstruction {
|
||||
hash: Hash,
|
||||
slot: u64,
|
||||
},
|
||||
/// Redeem storage reward credits
|
||||
///
|
||||
/// Expects 1 Account:
|
||||
/// 0 - Storage account with credits to redeem
|
||||
/// 1 - MiningPool account to redeem credits from
|
||||
ClaimStorageReward {
|
||||
slot: u64,
|
||||
},
|
||||
@ -27,12 +40,71 @@ pub enum StorageInstruction {
|
||||
},
|
||||
}
|
||||
|
||||
pub fn create_account(from: &Pubkey, to: &Pubkey, lamports: u64) -> Instruction {
|
||||
system_instruction::create_account(&from, to, lamports, STORAGE_ACCOUNT_SPACE, &id())
|
||||
pub fn create_validator_storage_account(
|
||||
from_pubkey: &Pubkey,
|
||||
storage_pubkey: &Pubkey,
|
||||
lamports: u64,
|
||||
) -> Vec<Instruction> {
|
||||
vec![
|
||||
system_instruction::create_account(
|
||||
from_pubkey,
|
||||
storage_pubkey,
|
||||
lamports,
|
||||
STORAGE_ACCOUNT_SPACE,
|
||||
&id(),
|
||||
),
|
||||
Instruction::new(
|
||||
id(),
|
||||
&StorageInstruction::InitializeValidatorStorage,
|
||||
vec![AccountMeta::new(*storage_pubkey, false)],
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn create_replicator_storage_account(
|
||||
from_pubkey: &Pubkey,
|
||||
storage_pubkey: &Pubkey,
|
||||
lamports: u64,
|
||||
) -> Vec<Instruction> {
|
||||
vec![
|
||||
system_instruction::create_account(
|
||||
from_pubkey,
|
||||
storage_pubkey,
|
||||
lamports,
|
||||
STORAGE_ACCOUNT_SPACE,
|
||||
&id(),
|
||||
),
|
||||
Instruction::new(
|
||||
id(),
|
||||
&StorageInstruction::InitializeReplicatorStorage,
|
||||
vec![AccountMeta::new(*storage_pubkey, false)],
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn create_mining_pool_account(
|
||||
from_pubkey: &Pubkey,
|
||||
storage_pubkey: &Pubkey,
|
||||
lamports: u64,
|
||||
) -> Vec<Instruction> {
|
||||
vec![
|
||||
system_instruction::create_account(
|
||||
from_pubkey,
|
||||
storage_pubkey,
|
||||
lamports,
|
||||
STORAGE_ACCOUNT_SPACE,
|
||||
&id(),
|
||||
),
|
||||
Instruction::new(
|
||||
id(),
|
||||
&StorageInstruction::InitializeMiningPool,
|
||||
vec![AccountMeta::new(*storage_pubkey, false)],
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn mining_proof(
|
||||
from_pubkey: &Pubkey,
|
||||
storage_pubkey: &Pubkey,
|
||||
sha_state: Hash,
|
||||
slot: u64,
|
||||
signature: Signature,
|
||||
@ -42,12 +114,12 @@ pub fn mining_proof(
|
||||
slot,
|
||||
signature,
|
||||
};
|
||||
let account_metas = vec![AccountMeta::new(*from_pubkey, true)];
|
||||
let account_metas = vec![AccountMeta::new(*storage_pubkey, true)];
|
||||
Instruction::new(id(), &storage_instruction, account_metas)
|
||||
}
|
||||
|
||||
pub fn advertise_recent_blockhash(
|
||||
from_pubkey: &Pubkey,
|
||||
storage_pubkey: &Pubkey,
|
||||
storage_hash: Hash,
|
||||
slot: u64,
|
||||
) -> Instruction {
|
||||
@ -55,12 +127,16 @@ pub fn advertise_recent_blockhash(
|
||||
hash: storage_hash,
|
||||
slot,
|
||||
};
|
||||
let account_metas = vec![AccountMeta::new(*from_pubkey, true)];
|
||||
let account_metas = vec![AccountMeta::new(*storage_pubkey, true)];
|
||||
Instruction::new(id(), &storage_instruction, account_metas)
|
||||
}
|
||||
|
||||
pub fn proof_validation(from_pubkey: &Pubkey, slot: u64, proofs: Vec<CheckedProof>) -> Instruction {
|
||||
let mut account_metas = vec![AccountMeta::new(*from_pubkey, true)];
|
||||
pub fn proof_validation(
|
||||
storage_pubkey: &Pubkey,
|
||||
slot: u64,
|
||||
proofs: Vec<CheckedProof>,
|
||||
) -> Instruction {
|
||||
let mut account_metas = vec![AccountMeta::new(*storage_pubkey, true)];
|
||||
proofs.iter().for_each(|checked_proof| {
|
||||
account_metas.push(AccountMeta::new(checked_proof.proof.id, false))
|
||||
});
|
||||
@ -68,8 +144,15 @@ pub fn proof_validation(from_pubkey: &Pubkey, slot: u64, proofs: Vec<CheckedProo
|
||||
Instruction::new(id(), &storage_instruction, account_metas)
|
||||
}
|
||||
|
||||
pub fn reward_claim(from_pubkey: &Pubkey, slot: u64) -> Instruction {
|
||||
pub fn claim_reward(
|
||||
storage_pubkey: &Pubkey,
|
||||
mining_pool_pubkey: &Pubkey,
|
||||
slot: u64,
|
||||
) -> Instruction {
|
||||
let storage_instruction = StorageInstruction::ClaimStorageReward { slot };
|
||||
let account_metas = vec![AccountMeta::new(*from_pubkey, true)];
|
||||
let account_metas = vec![
|
||||
AccountMeta::new(*storage_pubkey, false),
|
||||
AccountMeta::new(*mining_pool_pubkey, false),
|
||||
];
|
||||
Instruction::new(id(), &storage_instruction, account_metas)
|
||||
}
|
||||
|
@ -1,10 +1,8 @@
|
||||
//! storage program
|
||||
//! Receive mining proofs from miners, validate the answers
|
||||
//! and give reward for good proofs.
|
||||
|
||||
use crate::storage_contract::StorageAccount;
|
||||
use crate::storage_instruction::StorageInstruction;
|
||||
use log::*;
|
||||
use solana_sdk::account::KeyedAccount;
|
||||
use solana_sdk::instruction::InstructionError;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
@ -18,30 +16,37 @@ pub fn process_instruction(
|
||||
) -> Result<(), InstructionError> {
|
||||
solana_logger::setup();
|
||||
|
||||
let num_keyed_accounts = keyed_accounts.len();
|
||||
let (me, rest) = keyed_accounts.split_at_mut(1);
|
||||
|
||||
// accounts_keys[0] must be signed
|
||||
let storage_account_pubkey = me[0].signer_key();
|
||||
if storage_account_pubkey.is_none() {
|
||||
info!("account[0] is unsigned");
|
||||
Err(InstructionError::MissingRequiredSignature)?;
|
||||
}
|
||||
let storage_account_pubkey = *storage_account_pubkey.unwrap();
|
||||
|
||||
let me_unsigned = me[0].signer_key().is_none();
|
||||
let storage_account_pubkey = *me[0].unsigned_key();
|
||||
let mut storage_account = StorageAccount::new(&mut me[0].account);
|
||||
let mut rest: Vec<_> = rest
|
||||
.iter_mut()
|
||||
.map(|keyed_account| StorageAccount::new(&mut keyed_account.account))
|
||||
.collect();
|
||||
|
||||
match bincode::deserialize(data).map_err(|_| InstructionError::InvalidInstructionData)? {
|
||||
StorageInstruction::InitializeMiningPool => {
|
||||
if !rest.is_empty() {
|
||||
Err(InstructionError::InvalidArgument)?;
|
||||
}
|
||||
storage_account.initialize_mining_pool()
|
||||
}
|
||||
StorageInstruction::InitializeReplicatorStorage => {
|
||||
if !rest.is_empty() {
|
||||
Err(InstructionError::InvalidArgument)?;
|
||||
}
|
||||
storage_account.initialize_replicator_storage()
|
||||
}
|
||||
StorageInstruction::InitializeValidatorStorage => {
|
||||
if !rest.is_empty() {
|
||||
Err(InstructionError::InvalidArgument)?;
|
||||
}
|
||||
storage_account.initialize_validator_storage()
|
||||
}
|
||||
StorageInstruction::SubmitMiningProof {
|
||||
sha_state,
|
||||
slot,
|
||||
signature,
|
||||
} => {
|
||||
if num_keyed_accounts != 1 {
|
||||
if me_unsigned || !rest.is_empty() {
|
||||
// This instruction must be signed by `me`
|
||||
Err(InstructionError::InvalidArgument)?;
|
||||
}
|
||||
storage_account.submit_mining_proof(
|
||||
@ -53,9 +58,8 @@ pub fn process_instruction(
|
||||
)
|
||||
}
|
||||
StorageInstruction::AdvertiseStorageRecentBlockhash { hash, slot } => {
|
||||
if num_keyed_accounts != 1 {
|
||||
// keyed_accounts[0] should be the main storage key
|
||||
// to access its data
|
||||
if me_unsigned || !rest.is_empty() {
|
||||
// This instruction must be signed by `me`
|
||||
Err(InstructionError::InvalidArgument)?;
|
||||
}
|
||||
storage_account.advertise_storage_recent_blockhash(
|
||||
@ -65,18 +69,24 @@ pub fn process_instruction(
|
||||
)
|
||||
}
|
||||
StorageInstruction::ClaimStorageReward { slot } => {
|
||||
if num_keyed_accounts != 1 {
|
||||
// keyed_accounts[0] should be the main storage key
|
||||
// to access its data
|
||||
if rest.len() != 1 {
|
||||
Err(InstructionError::InvalidArgument)?;
|
||||
}
|
||||
storage_account.claim_storage_reward(slot, tick_height / DEFAULT_TICKS_PER_SLOT)
|
||||
storage_account.claim_storage_reward(
|
||||
&mut rest[0],
|
||||
slot,
|
||||
tick_height / DEFAULT_TICKS_PER_SLOT,
|
||||
)
|
||||
}
|
||||
StorageInstruction::ProofValidation { slot, proofs } => {
|
||||
if num_keyed_accounts == 1 {
|
||||
// have to have at least 1 replicator to do any verification
|
||||
if me_unsigned || rest.is_empty() {
|
||||
// This instruction must be signed by `me`
|
||||
Err(InstructionError::InvalidArgument)?;
|
||||
}
|
||||
let mut rest: Vec<_> = rest
|
||||
.iter_mut()
|
||||
.map(|keyed_account| StorageAccount::new(&mut keyed_account.account))
|
||||
.collect();
|
||||
storage_account.proof_validation(slot, proofs, &mut rest)
|
||||
}
|
||||
}
|
||||
@ -88,10 +98,13 @@ mod tests {
|
||||
use crate::id;
|
||||
use crate::storage_contract::{
|
||||
CheckedProof, Proof, ProofStatus, StorageContract, STORAGE_ACCOUNT_SPACE,
|
||||
TOTAL_VALIDATOR_REWARDS,
|
||||
};
|
||||
use crate::storage_instruction;
|
||||
use crate::SLOTS_PER_SEGMENT;
|
||||
use assert_matches::assert_matches;
|
||||
use bincode::deserialize;
|
||||
use log::*;
|
||||
use solana_runtime::bank::Bank;
|
||||
use solana_runtime::bank_client::BankClient;
|
||||
use solana_sdk::account::{create_keyed_accounts, Account};
|
||||
@ -99,6 +112,7 @@ mod tests {
|
||||
use solana_sdk::genesis_block::create_genesis_block;
|
||||
use solana_sdk::hash::{hash, Hash};
|
||||
use solana_sdk::instruction::Instruction;
|
||||
use solana_sdk::message::Message;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
||||
use std::sync::Arc;
|
||||
@ -127,10 +141,14 @@ mod tests {
|
||||
#[test]
|
||||
fn test_proof_bounds() {
|
||||
let pubkey = Pubkey::new_rand();
|
||||
let account = Account {
|
||||
let mut account = Account {
|
||||
data: vec![0; STORAGE_ACCOUNT_SPACE as usize],
|
||||
..Account::default()
|
||||
};
|
||||
{
|
||||
let mut storage_account = StorageAccount::new(&mut account);
|
||||
storage_account.initialize_replicator_storage().unwrap();
|
||||
}
|
||||
|
||||
let ix = storage_instruction::mining_proof(
|
||||
&pubkey,
|
||||
@ -212,13 +230,20 @@ mod tests {
|
||||
let pubkey = Pubkey::new_rand();
|
||||
let mut accounts = [Account::default(), Account::default()];
|
||||
accounts[0].data.resize(STORAGE_ACCOUNT_SPACE as usize, 0);
|
||||
{
|
||||
let mut storage_account = StorageAccount::new(&mut accounts[0]);
|
||||
storage_account.initialize_replicator_storage().unwrap();
|
||||
}
|
||||
|
||||
let ix =
|
||||
storage_instruction::mining_proof(&pubkey, Hash::default(), 0, Signature::default());
|
||||
// move tick height into segment 1
|
||||
let ticks_till_next_segment = TICKS_IN_SEGMENT + 1;
|
||||
|
||||
test_instruction(&ix, &mut accounts, ticks_till_next_segment).unwrap();
|
||||
assert_matches!(
|
||||
test_instruction(&ix, &mut accounts, ticks_till_next_segment),
|
||||
Ok(_)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -230,6 +255,8 @@ mod tests {
|
||||
let replicator = replicator_keypair.pubkey();
|
||||
let validator_keypair = Keypair::new();
|
||||
let validator = validator_keypair.pubkey();
|
||||
let mining_pool_keypair = Keypair::new();
|
||||
let mining_pool = mining_pool_keypair.pubkey();
|
||||
|
||||
let mut bank = Bank::new(&genesis_block);
|
||||
bank.add_instruction_processor(id(), process_instruction);
|
||||
@ -237,11 +264,26 @@ mod tests {
|
||||
let slot = 0;
|
||||
let bank_client = BankClient::new_shared(&bank);
|
||||
|
||||
let ix = storage_instruction::create_account(&mint_pubkey, &validator, 10);
|
||||
bank_client.send_instruction(&mint_keypair, ix).unwrap();
|
||||
let message = Message::new(storage_instruction::create_validator_storage_account(
|
||||
&mint_pubkey,
|
||||
&validator,
|
||||
10,
|
||||
));
|
||||
bank_client.send_message(&[&mint_keypair], message).unwrap();
|
||||
|
||||
let ix = storage_instruction::create_account(&mint_pubkey, &replicator, 10);
|
||||
bank_client.send_instruction(&mint_keypair, ix).unwrap();
|
||||
let message = Message::new(storage_instruction::create_replicator_storage_account(
|
||||
&mint_pubkey,
|
||||
&replicator,
|
||||
10,
|
||||
));
|
||||
bank_client.send_message(&[&mint_keypair], message).unwrap();
|
||||
|
||||
let message = Message::new(storage_instruction::create_mining_pool_account(
|
||||
&mint_pubkey,
|
||||
&mining_pool,
|
||||
100,
|
||||
));
|
||||
bank_client.send_message(&[&mint_keypair], message).unwrap();
|
||||
|
||||
// tick the bank up until it's moved into storage segment 2 because the next advertise is for segment 1
|
||||
let next_storage_segment_tick_height = TICKS_IN_SEGMENT * 2;
|
||||
@ -256,9 +298,7 @@ mod tests {
|
||||
SLOTS_PER_SEGMENT,
|
||||
);
|
||||
|
||||
bank_client
|
||||
.send_instruction(&validator_keypair, ix)
|
||||
.unwrap();
|
||||
assert_matches!(bank_client.send_instruction(&validator_keypair, ix), Ok(_));
|
||||
|
||||
let ix = storage_instruction::mining_proof(
|
||||
&replicator,
|
||||
@ -266,9 +306,8 @@ mod tests {
|
||||
slot,
|
||||
Signature::default(),
|
||||
);
|
||||
bank_client
|
||||
.send_instruction(&replicator_keypair, ix)
|
||||
.unwrap();
|
||||
|
||||
assert_matches!(bank_client.send_instruction(&replicator_keypair, ix), Ok(_));
|
||||
|
||||
let ix = storage_instruction::advertise_recent_blockhash(
|
||||
&validator,
|
||||
@ -281,10 +320,7 @@ mod tests {
|
||||
bank.register_tick(&bank.last_blockhash());
|
||||
}
|
||||
|
||||
bank_client
|
||||
.send_instruction(&validator_keypair, ix)
|
||||
.unwrap();
|
||||
|
||||
assert_matches!(bank_client.send_instruction(&validator_keypair, ix), Ok(_));
|
||||
let ix = storage_instruction::proof_validation(
|
||||
&validator,
|
||||
slot,
|
||||
@ -297,9 +333,8 @@ mod tests {
|
||||
status: ProofStatus::Valid,
|
||||
}],
|
||||
);
|
||||
bank_client
|
||||
.send_instruction(&validator_keypair, ix)
|
||||
.unwrap();
|
||||
|
||||
assert_matches!(bank_client.send_instruction(&validator_keypair, ix), Ok(_));
|
||||
|
||||
let ix = storage_instruction::advertise_recent_blockhash(
|
||||
&validator,
|
||||
@ -312,30 +347,50 @@ mod tests {
|
||||
bank.register_tick(&bank.last_blockhash());
|
||||
}
|
||||
|
||||
bank_client
|
||||
.send_instruction(&validator_keypair, ix)
|
||||
.unwrap();
|
||||
assert_matches!(bank_client.send_instruction(&validator_keypair, ix), Ok(_));
|
||||
|
||||
let ix = storage_instruction::reward_claim(&validator, slot);
|
||||
bank_client
|
||||
.send_instruction(&validator_keypair, ix)
|
||||
.unwrap();
|
||||
assert_eq!(bank_client.get_balance(&validator).unwrap(), 10,);
|
||||
|
||||
// TODO enable when rewards are working
|
||||
// assert_eq!(bank_client.get_balance(&validator).unwrap(), TOTAL_VALIDATOR_REWARDS);
|
||||
let message = Message::new_with_payer(
|
||||
vec![storage_instruction::claim_reward(
|
||||
&validator,
|
||||
&mining_pool,
|
||||
slot,
|
||||
)],
|
||||
Some(&validator),
|
||||
);
|
||||
assert_matches!(
|
||||
bank_client.send_message(&[&validator_keypair], message),
|
||||
Ok(_)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
bank_client.get_balance(&validator).unwrap(),
|
||||
10 + TOTAL_VALIDATOR_REWARDS
|
||||
);
|
||||
|
||||
// tick the bank into the next storage epoch so that rewards can be claimed
|
||||
for _ in 0..=TICKS_IN_SEGMENT {
|
||||
bank.register_tick(&bank.last_blockhash());
|
||||
}
|
||||
|
||||
let ix = storage_instruction::reward_claim(&replicator, slot);
|
||||
bank_client
|
||||
.send_instruction(&replicator_keypair, ix)
|
||||
.unwrap();
|
||||
assert_eq!(bank_client.get_balance(&replicator).unwrap(), 10);
|
||||
|
||||
let message = Message::new_with_payer(
|
||||
vec![storage_instruction::claim_reward(
|
||||
&replicator,
|
||||
&mining_pool,
|
||||
slot,
|
||||
)],
|
||||
Some(&replicator),
|
||||
);
|
||||
assert_matches!(
|
||||
bank_client.send_message(&[&replicator_keypair], message),
|
||||
Ok(_)
|
||||
);
|
||||
|
||||
// TODO enable when rewards are working
|
||||
// assert_eq!(bank_client.get_balance(&replicator).unwrap(), TOTAL_REPLICATOR_REWARDS);
|
||||
// assert_eq!(bank_client.get_balance(&replicator).unwrap(), 10 + TOTAL_REPLICATOR_REWARDS);
|
||||
}
|
||||
|
||||
fn get_storage_slot<C: SyncClient>(client: &C, account: &Pubkey) -> u64 {
|
||||
@ -399,13 +454,19 @@ mod tests {
|
||||
.transfer(10, &mint_keypair, &replicator_pubkey)
|
||||
.unwrap();
|
||||
|
||||
let ix = storage_instruction::create_account(&mint_pubkey, &replicator_pubkey, 1);
|
||||
let message = Message::new(storage_instruction::create_replicator_storage_account(
|
||||
&mint_pubkey,
|
||||
&replicator_pubkey,
|
||||
1,
|
||||
));
|
||||
bank_client.send_message(&[&mint_keypair], message).unwrap();
|
||||
|
||||
bank_client.send_instruction(&mint_keypair, ix).unwrap();
|
||||
|
||||
let ix = storage_instruction::create_account(&mint_pubkey, &validator_pubkey, 1);
|
||||
|
||||
bank_client.send_instruction(&mint_keypair, ix).unwrap();
|
||||
let message = Message::new(storage_instruction::create_validator_storage_account(
|
||||
&mint_pubkey,
|
||||
&validator_pubkey,
|
||||
1,
|
||||
));
|
||||
bank_client.send_message(&[&mint_keypair], message).unwrap();
|
||||
|
||||
let ix = storage_instruction::advertise_recent_blockhash(
|
||||
&validator_pubkey,
|
||||
|
Reference in New Issue
Block a user