Update storage contract to use a deterministic BTreeMap (#4763)

This commit is contained in:
Sagar Dhawan 2019-06-21 09:51:05 -07:00 committed by GitHub
parent deb83cdef6
commit a40c5cf185
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 35 additions and 24 deletions

View File

@ -9,7 +9,7 @@ use solana_sdk::hash::Hash;
use solana_sdk::instruction::InstructionError;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::Signature;
use std::collections::HashMap;
use std::collections::BTreeMap;
pub const VALIDATOR_REWARD: u64 = 200;
pub const REPLICATOR_REWARD: u64 = 200;
@ -65,7 +65,7 @@ pub enum StorageContract {
hash: Hash,
// Lockouts and Rewards are per segment per replicator. It needs to remain this way until
// the challenge stage is added. Once challenges are in rewards can just be a number
lockout_validations: HashMap<usize, HashMap<Pubkey, Vec<ProofStatus>>>,
lockout_validations: BTreeMap<usize, BTreeMap<Pubkey, Vec<ProofStatus>>>,
// lamports that are ready to be claimed
pending_lamports: u64,
},
@ -73,10 +73,10 @@ pub enum StorageContract {
owner: Pubkey,
// TODO what to do about duplicate proofs across segments? - Check the blockhashes
// Map of Proofs per segment, in a Vec
proofs: HashMap<usize, Vec<Proof>>,
// Map of Rewards per segment, in a HashMap based on the validator account that verified
proofs: BTreeMap<usize, Vec<Proof>>,
// Map of Rewards per segment, in a BTreeMap based on the validator account that verified
// the proof. This can be used for challenge stage when its added
reward_validations: HashMap<usize, HashMap<Pubkey, Vec<ProofStatus>>>,
reward_validations: BTreeMap<usize, BTreeMap<Pubkey, Vec<ProofStatus>>>,
},
MiningPool,
@ -91,7 +91,7 @@ pub fn create_validator_storage_account(owner: Pubkey, lamports: u64) -> Account
owner,
slot: 0,
hash: Hash::default(),
lockout_validations: HashMap::new(),
lockout_validations: BTreeMap::new(),
pending_lamports: 0,
})
.expect("set_state");
@ -135,8 +135,8 @@ impl<'a> StorageAccount<'a> {
if let StorageContract::Uninitialized = storage_contract {
*storage_contract = StorageContract::ReplicatorStorage {
owner,
proofs: HashMap::new(),
reward_validations: HashMap::new(),
proofs: BTreeMap::new(),
reward_validations: BTreeMap::new(),
};
self.account.set_state(storage_contract)
} else {
@ -151,7 +151,7 @@ impl<'a> StorageAccount<'a> {
owner,
slot: 0,
hash: Hash::default(),
lockout_validations: HashMap::new(),
lockout_validations: BTreeMap::new(),
pending_lamports: 0,
};
self.account.set_state(storage_contract)
@ -179,8 +179,16 @@ impl<'a> StorageAccount<'a> {
// clean up the account
// TODO check for time correctness - storage seems to run at a delay of about 3
proofs.retain(|segment, _| *segment >= current_segment.saturating_sub(5));
reward_validations.retain(|segment, _| *segment >= current_segment.saturating_sub(10));
*proofs = proofs
.iter()
.filter(|(segment, _)| **segment >= current_segment.saturating_sub(5))
.map(|(segment, proofs)| (*segment, proofs.clone()))
.collect();
*reward_validations = reward_validations
.iter()
.filter(|(segment, _)| **segment >= current_segment.saturating_sub(10))
.map(|(segment, rewards)| (*segment, rewards.clone()))
.collect();
if segment_index >= current_segment {
// attempt to submit proof for unconfirmed segment
@ -261,15 +269,16 @@ impl<'a> StorageAccount<'a> {
// storage epoch updated, move the lockout_validations to pending_lamports
let num_validations = count_valid_proofs(
&lockout_validations
.drain()
.flat_map(|(_segment, mut proofs)| {
.iter()
.flat_map(|(_segment, proofs)| {
proofs
.drain()
.flat_map(|(_, proof)| proof)
.iter()
.flat_map(|(_, proof)| proof.clone())
.collect::<Vec<_>>()
})
.collect::<Vec<_>>(),
);
lockout_validations.clear();
*pending_lamports += VALIDATOR_REWARD * num_validations;
self.account.set_state(storage_contract)
} else {
@ -411,14 +420,15 @@ impl<'a> StorageAccount<'a> {
}
let checked_proofs = reward_validations
.drain()
.flat_map(|(_, mut proofs)| {
.iter()
.flat_map(|(_, proofs)| {
proofs
.drain()
.flat_map(|(_, proofs)| proofs)
.iter()
.flat_map(|(_, proofs)| proofs.clone())
.collect::<Vec<_>>()
})
.collect::<Vec<_>>();
reward_validations.clear();
let total_proofs = checked_proofs.len() as u64;
let num_validations = count_valid_proofs(&checked_proofs);
let reward = num_validations * REPLICATOR_REWARD * (num_validations / total_proofs);
@ -477,6 +487,7 @@ fn count_valid_proofs(proofs: &[ProofStatus]) -> u64 {
mod tests {
use super::*;
use crate::id;
use std::collections::BTreeMap;
#[test]
fn test_account_data() {
@ -497,7 +508,7 @@ mod tests {
owner: Pubkey::default(),
slot: 0,
hash: Hash::default(),
lockout_validations: HashMap::new(),
lockout_validations: BTreeMap::new(),
pending_lamports: 0,
};
storage_account.account.set_state(&contract).unwrap();
@ -506,8 +517,8 @@ mod tests {
}
contract = StorageContract::ReplicatorStorage {
owner: Pubkey::default(),
proofs: HashMap::new(),
reward_validations: HashMap::new(),
proofs: BTreeMap::new(),
reward_validations: BTreeMap::new(),
};
storage_account.account.set_state(&contract).unwrap();
if let StorageContract::ValidatorStorage { .. } = contract {
@ -547,12 +558,12 @@ mod tests {
.resize(STORAGE_ACCOUNT_SPACE as usize, 0);
let storage_contract = &mut account.account.state().unwrap();
if let StorageContract::Uninitialized = storage_contract {
let mut proofs = HashMap::new();
let mut proofs = BTreeMap::new();
proofs.insert(0, vec![proof.clone()]);
*storage_contract = StorageContract::ReplicatorStorage {
owner: Pubkey::default(),
proofs,
reward_validations: HashMap::new(),
reward_validations: BTreeMap::new(),
};
};
account.account.set_state(storage_contract).unwrap();