Add method to return hash of bank state

This commit is contained in:
Tyera Eulberg 2018-09-07 13:55:30 -06:00 committed by Tyera Eulberg
parent 0d945e6a92
commit 5169c8d08f
1 changed files with 64 additions and 3 deletions

View File

@ -3,10 +3,11 @@
//! on behalf of the caller, and a low-level API for when they have
//! already been signed and verified.
use bincode::serialize;
use chrono::prelude::*;
use counter::Counter;
use entry::Entry;
use hash::Hash;
use hash::{hash, Hash};
use itertools::Itertools;
use ledger::Block;
use log::Level;
@ -15,7 +16,7 @@ use payment_plan::{Payment, PaymentPlan, Witness};
use signature::{Keypair, Pubkey, Signature};
use std;
use std::collections::hash_map::Entry::Occupied;
use std::collections::{HashMap, HashSet, VecDeque};
use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
use std::result;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::RwLock;
@ -637,6 +638,16 @@ impl Bank {
false
}
/// Hash the `accounts` HashMap. This represents a validator's interpretation
/// of the ledger up to the `last_id`, to be sent back to the leader when voting.
pub fn hash_internal_state(&self) -> Hash {
let mut ordered_accounts = BTreeMap::new();
for (pubkey, account) in self.accounts.read().unwrap().iter() {
ordered_accounts.insert(*pubkey, account.clone());
}
hash(&serialize(&ordered_accounts).unwrap())
}
pub fn finality(&self) -> usize {
self.finality_time.load(Ordering::Relaxed)
}
@ -656,7 +667,7 @@ mod tests {
use hash::hash;
use ledger;
use packet::BLOB_DATA_SIZE;
use signature::KeypairUtil;
use signature::{GenKeys, KeypairUtil};
use std;
use std::io::{BufReader, Cursor, Seek, SeekFrom};
use std::mem::size_of;
@ -945,6 +956,19 @@ mod tests {
entries.into_iter()
}
fn create_sample_block_with_next_entries_using_keypairs(
mint: &Mint,
keypairs: &[Keypair],
) -> impl Iterator<Item = Entry> {
let hash = mint.last_id();
let transactions: Vec<_> = keypairs
.iter()
.map(|keypair| Transaction::new(&mint.keypair(), keypair.pubkey(), 1, hash))
.collect();
let entries = ledger::next_entries(&hash, 0, transactions);
entries.into_iter()
}
fn create_sample_block(mint: &Mint, length: usize) -> impl Iterator<Item = Entry> {
let mut entries = Vec::with_capacity(length);
let mut hash = mint.last_id();
@ -974,6 +998,15 @@ mod tests {
(genesis.into_iter().chain(block), mint.pubkey())
}
fn create_sample_ledger_with_mint_and_keypairs(
mint: &Mint,
keypairs: &[Keypair],
) -> impl Iterator<Item = Entry> {
let genesis = mint.create_entries();
let block = create_sample_block_with_next_entries_using_keypairs(mint, keypairs);
genesis.into_iter().chain(block)
}
#[test]
fn test_process_ledger() {
let (ledger, pubkey) = create_sample_ledger(1);
@ -1061,6 +1094,34 @@ mod tests {
assert!(!validator_bank.is_leader);
}
#[test]
fn test_hash_internal_state() {
let mint = Mint::new(2_000);
let seed = [0u8; 32];
let mut rnd = GenKeys::new(seed);
let keypairs = rnd.gen_n_keypairs(5);
let ledger0 = create_sample_ledger_with_mint_and_keypairs(&mint, &keypairs);
let ledger1 = create_sample_ledger_with_mint_and_keypairs(&mint, &keypairs);
let bank0 = Bank::default();
bank0.process_ledger(ledger0).unwrap();
let bank1 = Bank::default();
bank1.process_ledger(ledger1).unwrap();
let initial_state = bank0.hash_internal_state();
assert_eq!(bank1.hash_internal_state(), initial_state);
let pubkey = keypairs[0].pubkey();
bank0
.transfer(1_000, &mint.keypair(), pubkey, mint.last_id())
.unwrap();
assert_ne!(bank0.hash_internal_state(), initial_state);
bank1
.transfer(1_000, &mint.keypair(), pubkey, mint.last_id())
.unwrap();
assert_eq!(bank0.hash_internal_state(), bank1.hash_internal_state());
}
#[test]
fn test_finality() {
let def_bank = Bank::default();
assert_eq!(def_bank.finality(), std::usize::MAX);