Change replicators to slot-based (#4118)
This commit is contained in:
@ -4,10 +4,10 @@ pub mod storage_processor;
|
||||
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
|
||||
pub const ENTRIES_PER_SEGMENT: u64 = 16;
|
||||
pub const SLOTS_PER_SEGMENT: u64 = 2;
|
||||
|
||||
pub fn get_segment_from_entry(entry_height: u64) -> usize {
|
||||
(entry_height / ENTRIES_PER_SEGMENT) as usize
|
||||
pub fn get_segment_from_slot(slot: u64) -> usize {
|
||||
(slot / SLOTS_PER_SEGMENT) as usize
|
||||
}
|
||||
|
||||
const STORAGE_PROGRAM_ID: [u8; 32] = [
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::{get_segment_from_entry, ENTRIES_PER_SEGMENT};
|
||||
use crate::get_segment_from_slot;
|
||||
use log::*;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use solana_sdk::account::Account;
|
||||
@ -44,7 +44,7 @@ pub enum StorageContract {
|
||||
Default,
|
||||
|
||||
ValidatorStorage {
|
||||
entry_height: u64,
|
||||
slot: u64,
|
||||
hash: Hash,
|
||||
lockout_validations: Vec<Vec<CheckedProof>>,
|
||||
reward_validations: Vec<Vec<CheckedProof>>,
|
||||
@ -68,7 +68,7 @@ impl<'a> StorageAccount<'a> {
|
||||
&mut self,
|
||||
id: Pubkey,
|
||||
sha_state: Hash,
|
||||
entry_height: u64,
|
||||
slot: u64,
|
||||
signature: Signature,
|
||||
) -> Result<(), InstructionError> {
|
||||
let mut storage_contract = &mut self.account.state()?;
|
||||
@ -80,7 +80,7 @@ impl<'a> StorageAccount<'a> {
|
||||
};
|
||||
|
||||
if let StorageContract::ReplicatorStorage { proofs, .. } = &mut storage_contract {
|
||||
let segment_index = get_segment_from_entry(entry_height);
|
||||
let segment_index = get_segment_from_slot(slot);
|
||||
if segment_index > proofs.len() || proofs.is_empty() {
|
||||
proofs.resize(cmp::max(1, segment_index), Proof::default());
|
||||
}
|
||||
@ -91,8 +91,8 @@ impl<'a> StorageAccount<'a> {
|
||||
}
|
||||
|
||||
debug!(
|
||||
"Mining proof submitted with contract {:?} entry_height: {}",
|
||||
sha_state, entry_height
|
||||
"Mining proof submitted with contract {:?} slot: {}",
|
||||
sha_state, slot
|
||||
);
|
||||
|
||||
let proof_info = Proof {
|
||||
@ -110,12 +110,12 @@ impl<'a> StorageAccount<'a> {
|
||||
pub fn advertise_storage_recent_blockhash(
|
||||
&mut self,
|
||||
hash: Hash,
|
||||
entry_height: u64,
|
||||
slot: u64,
|
||||
) -> Result<(), InstructionError> {
|
||||
let mut storage_contract = &mut self.account.state()?;
|
||||
if let StorageContract::Default = storage_contract {
|
||||
*storage_contract = StorageContract::ValidatorStorage {
|
||||
entry_height: 0,
|
||||
slot: 0,
|
||||
hash: Hash::default(),
|
||||
lockout_validations: vec![],
|
||||
reward_validations: vec![],
|
||||
@ -123,14 +123,14 @@ impl<'a> StorageAccount<'a> {
|
||||
};
|
||||
|
||||
if let StorageContract::ValidatorStorage {
|
||||
entry_height: state_entry_height,
|
||||
slot: state_slot,
|
||||
hash: state_hash,
|
||||
reward_validations,
|
||||
lockout_validations,
|
||||
} = &mut storage_contract
|
||||
{
|
||||
let original_segments = *state_entry_height / ENTRIES_PER_SEGMENT;
|
||||
let segments = entry_height / ENTRIES_PER_SEGMENT;
|
||||
let original_segments = get_segment_from_slot(*state_slot);
|
||||
let segments = get_segment_from_slot(slot);
|
||||
debug!(
|
||||
"advertise new last id segments: {} orig: {}",
|
||||
segments, original_segments
|
||||
@ -139,7 +139,7 @@ impl<'a> StorageAccount<'a> {
|
||||
return Err(InstructionError::InvalidArgument);
|
||||
}
|
||||
|
||||
*state_entry_height = entry_height;
|
||||
*state_slot = slot;
|
||||
*state_hash = hash;
|
||||
|
||||
// move lockout_validations to reward_validations
|
||||
@ -154,14 +154,14 @@ impl<'a> StorageAccount<'a> {
|
||||
|
||||
pub fn proof_validation(
|
||||
&mut self,
|
||||
entry_height: u64,
|
||||
slot: u64,
|
||||
proofs: Vec<CheckedProof>,
|
||||
replicator_accounts: &mut [StorageAccount],
|
||||
) -> Result<(), InstructionError> {
|
||||
let mut storage_contract = &mut self.account.state()?;
|
||||
if let StorageContract::Default = storage_contract {
|
||||
*storage_contract = StorageContract::ValidatorStorage {
|
||||
entry_height: 0,
|
||||
slot: 0,
|
||||
hash: Hash::default(),
|
||||
lockout_validations: vec![],
|
||||
reward_validations: vec![],
|
||||
@ -169,16 +169,16 @@ impl<'a> StorageAccount<'a> {
|
||||
};
|
||||
|
||||
if let StorageContract::ValidatorStorage {
|
||||
entry_height: current_entry_height,
|
||||
slot: current_slot,
|
||||
lockout_validations,
|
||||
..
|
||||
} = &mut storage_contract
|
||||
{
|
||||
if entry_height >= *current_entry_height {
|
||||
if slot >= *current_slot {
|
||||
return Err(InstructionError::InvalidArgument);
|
||||
}
|
||||
|
||||
let segment_index = get_segment_from_entry(entry_height);
|
||||
let segment_index = get_segment_from_slot(slot);
|
||||
let mut previous_proofs = replicator_accounts
|
||||
.iter_mut()
|
||||
.filter_map(|account| {
|
||||
@ -224,7 +224,7 @@ impl<'a> StorageAccount<'a> {
|
||||
|
||||
pub fn claim_storage_reward(
|
||||
&mut self,
|
||||
entry_height: u64,
|
||||
slot: u64,
|
||||
tick_height: u64,
|
||||
) -> Result<(), InstructionError> {
|
||||
let mut storage_contract = &mut self.account.state()?;
|
||||
@ -236,7 +236,7 @@ impl<'a> StorageAccount<'a> {
|
||||
reward_validations, ..
|
||||
} = &mut storage_contract
|
||||
{
|
||||
let claims_index = get_segment_from_entry(entry_height);
|
||||
let claims_index = get_segment_from_slot(slot);
|
||||
let _num_validations = count_valid_proofs(&reward_validations[claims_index]);
|
||||
// TODO can't just create lamports out of thin air
|
||||
// self.account.lamports += TOTAL_VALIDATOR_REWARDS * num_validations;
|
||||
@ -248,8 +248,8 @@ impl<'a> StorageAccount<'a> {
|
||||
{
|
||||
// if current tick height is a full segment away? then allow reward collection
|
||||
// storage needs to move to tick heights too, until then this makes little sense
|
||||
let current_index = get_segment_from_entry(tick_height);
|
||||
let claims_index = get_segment_from_entry(entry_height);
|
||||
let current_index = get_segment_from_slot(tick_height);
|
||||
let claims_index = get_segment_from_slot(slot);
|
||||
if current_index <= claims_index || claims_index >= reward_validations.len() {
|
||||
debug!(
|
||||
"current {:?}, claim {:?}, rewards {:?}",
|
||||
@ -348,7 +348,7 @@ mod tests {
|
||||
}
|
||||
|
||||
contract = StorageContract::ValidatorStorage {
|
||||
entry_height: 0,
|
||||
slot: 0,
|
||||
hash: Hash::default(),
|
||||
lockout_validations: vec![],
|
||||
reward_validations: vec![],
|
||||
|
@ -11,18 +11,18 @@ use solana_sdk::signature::Signature;
|
||||
pub enum StorageInstruction {
|
||||
SubmitMiningProof {
|
||||
sha_state: Hash,
|
||||
entry_height: u64,
|
||||
slot: u64,
|
||||
signature: Signature,
|
||||
},
|
||||
AdvertiseStorageRecentBlockhash {
|
||||
hash: Hash,
|
||||
entry_height: u64,
|
||||
slot: u64,
|
||||
},
|
||||
ClaimStorageReward {
|
||||
entry_height: u64,
|
||||
slot: u64,
|
||||
},
|
||||
ProofValidation {
|
||||
entry_height: u64,
|
||||
slot: u64,
|
||||
proofs: Vec<CheckedProof>,
|
||||
},
|
||||
}
|
||||
@ -30,12 +30,12 @@ pub enum StorageInstruction {
|
||||
pub fn mining_proof(
|
||||
from_pubkey: &Pubkey,
|
||||
sha_state: Hash,
|
||||
entry_height: u64,
|
||||
slot: u64,
|
||||
signature: Signature,
|
||||
) -> Instruction {
|
||||
let storage_instruction = StorageInstruction::SubmitMiningProof {
|
||||
sha_state,
|
||||
entry_height,
|
||||
slot,
|
||||
signature,
|
||||
};
|
||||
let account_metas = vec![AccountMeta::new(*from_pubkey, true)];
|
||||
@ -45,34 +45,27 @@ pub fn mining_proof(
|
||||
pub fn advertise_recent_blockhash(
|
||||
from_pubkey: &Pubkey,
|
||||
storage_hash: Hash,
|
||||
entry_height: u64,
|
||||
slot: u64,
|
||||
) -> Instruction {
|
||||
let storage_instruction = StorageInstruction::AdvertiseStorageRecentBlockhash {
|
||||
hash: storage_hash,
|
||||
entry_height,
|
||||
slot,
|
||||
};
|
||||
let account_metas = vec![AccountMeta::new(*from_pubkey, true)];
|
||||
Instruction::new(id(), &storage_instruction, account_metas)
|
||||
}
|
||||
|
||||
pub fn proof_validation(
|
||||
from_pubkey: &Pubkey,
|
||||
entry_height: u64,
|
||||
proofs: Vec<CheckedProof>,
|
||||
) -> Instruction {
|
||||
pub fn proof_validation(from_pubkey: &Pubkey, slot: u64, proofs: Vec<CheckedProof>) -> Instruction {
|
||||
let mut account_metas = vec![AccountMeta::new(*from_pubkey, true)];
|
||||
proofs.iter().for_each(|checked_proof| {
|
||||
account_metas.push(AccountMeta::new(checked_proof.proof.id, false))
|
||||
});
|
||||
let storage_instruction = StorageInstruction::ProofValidation {
|
||||
entry_height,
|
||||
proofs,
|
||||
};
|
||||
let storage_instruction = StorageInstruction::ProofValidation { slot, proofs };
|
||||
Instruction::new(id(), &storage_instruction, account_metas)
|
||||
}
|
||||
|
||||
pub fn reward_claim(from_pubkey: &Pubkey, entry_height: u64) -> Instruction {
|
||||
let storage_instruction = StorageInstruction::ClaimStorageReward { entry_height };
|
||||
pub fn reward_claim(from_pubkey: &Pubkey, slot: u64) -> Instruction {
|
||||
let storage_instruction = StorageInstruction::ClaimStorageReward { slot };
|
||||
let account_metas = vec![AccountMeta::new(*from_pubkey, true)];
|
||||
Instruction::new(id(), &storage_instruction, account_metas)
|
||||
}
|
||||
|
@ -37,44 +37,36 @@ pub fn process_instruction(
|
||||
match bincode::deserialize(data).map_err(|_| InstructionError::InvalidInstructionData)? {
|
||||
StorageInstruction::SubmitMiningProof {
|
||||
sha_state,
|
||||
entry_height,
|
||||
slot,
|
||||
signature,
|
||||
} => {
|
||||
if num_keyed_accounts != 1 {
|
||||
Err(InstructionError::InvalidArgument)?;
|
||||
}
|
||||
storage_account.submit_mining_proof(
|
||||
storage_account_pubkey,
|
||||
sha_state,
|
||||
entry_height,
|
||||
signature,
|
||||
)
|
||||
storage_account.submit_mining_proof(storage_account_pubkey, sha_state, slot, signature)
|
||||
}
|
||||
StorageInstruction::AdvertiseStorageRecentBlockhash { hash, entry_height } => {
|
||||
StorageInstruction::AdvertiseStorageRecentBlockhash { hash, slot } => {
|
||||
if num_keyed_accounts != 1 {
|
||||
// keyed_accounts[0] should be the main storage key
|
||||
// to access its data
|
||||
Err(InstructionError::InvalidArgument)?;
|
||||
}
|
||||
storage_account.advertise_storage_recent_blockhash(hash, entry_height)
|
||||
storage_account.advertise_storage_recent_blockhash(hash, slot)
|
||||
}
|
||||
StorageInstruction::ClaimStorageReward { entry_height } => {
|
||||
StorageInstruction::ClaimStorageReward { slot } => {
|
||||
if num_keyed_accounts != 1 {
|
||||
// keyed_accounts[0] should be the main storage key
|
||||
// to access its data
|
||||
Err(InstructionError::InvalidArgument)?;
|
||||
}
|
||||
storage_account.claim_storage_reward(entry_height, tick_height)
|
||||
storage_account.claim_storage_reward(slot, tick_height)
|
||||
}
|
||||
StorageInstruction::ProofValidation {
|
||||
entry_height,
|
||||
proofs,
|
||||
} => {
|
||||
StorageInstruction::ProofValidation { slot, proofs } => {
|
||||
if num_keyed_accounts == 1 {
|
||||
// have to have at least 1 replicator to do any verification
|
||||
Err(InstructionError::InvalidArgument)?;
|
||||
}
|
||||
storage_account.proof_validation(entry_height, proofs, &mut rest)
|
||||
storage_account.proof_validation(slot, proofs, &mut rest)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -85,7 +77,7 @@ mod tests {
|
||||
use crate::id;
|
||||
use crate::storage_contract::{CheckedProof, Proof, ProofStatus, StorageContract};
|
||||
use crate::storage_instruction;
|
||||
use crate::ENTRIES_PER_SEGMENT;
|
||||
use crate::SLOTS_PER_SEGMENT;
|
||||
use bincode::deserialize;
|
||||
use solana_runtime::bank::Bank;
|
||||
use solana_runtime::bank_client::BankClient;
|
||||
@ -134,7 +126,7 @@ mod tests {
|
||||
let ix = storage_instruction::advertise_recent_blockhash(
|
||||
&pubkey,
|
||||
Hash::default(),
|
||||
ENTRIES_PER_SEGMENT,
|
||||
SLOTS_PER_SEGMENT,
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
@ -158,7 +150,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_submit_mining_invalid_entry_height() {
|
||||
fn test_submit_mining_invalid_slot() {
|
||||
solana_logger::setup();
|
||||
let pubkey = Pubkey::new_rand();
|
||||
let mut accounts = [Account::default(), Account::default()];
|
||||
@ -197,7 +189,7 @@ mod tests {
|
||||
|
||||
let mut bank = Bank::new(&genesis_block);
|
||||
bank.add_instruction_processor(id(), process_instruction);
|
||||
let entry_height = 0;
|
||||
let slot = 0;
|
||||
let bank_client = BankClient::new(bank);
|
||||
|
||||
let ix = system_instruction::create_account(&mint_pubkey, &validator, 10, 4 * 1042, &id());
|
||||
@ -209,7 +201,7 @@ mod tests {
|
||||
let ix = storage_instruction::advertise_recent_blockhash(
|
||||
&validator,
|
||||
Hash::default(),
|
||||
ENTRIES_PER_SEGMENT,
|
||||
SLOTS_PER_SEGMENT,
|
||||
);
|
||||
|
||||
bank_client
|
||||
@ -219,7 +211,7 @@ mod tests {
|
||||
let ix = storage_instruction::mining_proof(
|
||||
&replicator,
|
||||
Hash::default(),
|
||||
entry_height,
|
||||
slot,
|
||||
Signature::default(),
|
||||
);
|
||||
bank_client
|
||||
@ -229,7 +221,7 @@ mod tests {
|
||||
let ix = storage_instruction::advertise_recent_blockhash(
|
||||
&validator,
|
||||
Hash::default(),
|
||||
ENTRIES_PER_SEGMENT * 2,
|
||||
SLOTS_PER_SEGMENT * 2,
|
||||
);
|
||||
bank_client
|
||||
.send_instruction(&validator_keypair, ix)
|
||||
@ -237,7 +229,7 @@ mod tests {
|
||||
|
||||
let ix = storage_instruction::proof_validation(
|
||||
&validator,
|
||||
entry_height,
|
||||
slot,
|
||||
vec![CheckedProof {
|
||||
proof: Proof {
|
||||
id: replicator,
|
||||
@ -254,13 +246,13 @@ mod tests {
|
||||
let ix = storage_instruction::advertise_recent_blockhash(
|
||||
&validator,
|
||||
Hash::default(),
|
||||
ENTRIES_PER_SEGMENT * 3,
|
||||
SLOTS_PER_SEGMENT * 3,
|
||||
);
|
||||
bank_client
|
||||
.send_instruction(&validator_keypair, ix)
|
||||
.unwrap();
|
||||
|
||||
let ix = storage_instruction::reward_claim(&validator, entry_height);
|
||||
let ix = storage_instruction::reward_claim(&validator, slot);
|
||||
bank_client
|
||||
.send_instruction(&validator_keypair, ix)
|
||||
.unwrap();
|
||||
@ -274,7 +266,7 @@ mod tests {
|
||||
// bank.register_tick(&bank.last_blockhash());
|
||||
//}
|
||||
|
||||
let ix = storage_instruction::reward_claim(&replicator, entry_height);
|
||||
let ix = storage_instruction::reward_claim(&replicator, slot);
|
||||
bank_client
|
||||
.send_instruction(&replicator_keypair, ix)
|
||||
.unwrap();
|
||||
@ -283,21 +275,21 @@ mod tests {
|
||||
// assert_eq!(bank_client.get_balance(&replicator).unwrap(), TOTAL_REPLICATOR_REWARDS);
|
||||
}
|
||||
|
||||
fn get_storage_entry_height<C: SyncClient>(client: &C, account: &Pubkey) -> u64 {
|
||||
fn get_storage_slot<C: SyncClient>(client: &C, account: &Pubkey) -> u64 {
|
||||
match client.get_account_data(&account).unwrap() {
|
||||
Some(storage_system_account_data) => {
|
||||
let contract = deserialize(&storage_system_account_data);
|
||||
if let Ok(contract) = contract {
|
||||
match contract {
|
||||
StorageContract::ValidatorStorage { entry_height, .. } => {
|
||||
return entry_height;
|
||||
StorageContract::ValidatorStorage { slot, .. } => {
|
||||
return slot;
|
||||
}
|
||||
_ => info!("error in reading entry_height"),
|
||||
_ => info!("error in reading slot"),
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
info!("error in reading entry_height");
|
||||
info!("error in reading slot");
|
||||
}
|
||||
}
|
||||
0
|
||||
@ -357,18 +349,18 @@ mod tests {
|
||||
let ix = storage_instruction::advertise_recent_blockhash(
|
||||
&validator_pubkey,
|
||||
storage_blockhash,
|
||||
ENTRIES_PER_SEGMENT,
|
||||
SLOTS_PER_SEGMENT,
|
||||
);
|
||||
|
||||
bank_client
|
||||
.send_instruction(&validator_keypair, ix)
|
||||
.unwrap();
|
||||
|
||||
let entry_height = 0;
|
||||
let slot = 0;
|
||||
let ix = storage_instruction::mining_proof(
|
||||
&replicator_pubkey,
|
||||
Hash::default(),
|
||||
entry_height,
|
||||
slot,
|
||||
Signature::default(),
|
||||
);
|
||||
let _result = bank_client
|
||||
@ -376,8 +368,8 @@ mod tests {
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
get_storage_entry_height(&bank_client, &validator_pubkey),
|
||||
ENTRIES_PER_SEGMENT
|
||||
get_storage_slot(&bank_client, &validator_pubkey),
|
||||
SLOTS_PER_SEGMENT
|
||||
);
|
||||
assert_eq!(
|
||||
get_storage_blockhash(&bank_client, &validator_pubkey),
|
||||
|
Reference in New Issue
Block a user