diff --git a/core/src/blocktree.rs b/core/src/blocktree.rs index a42921022b..19fa0a8e05 100644 --- a/core/src/blocktree.rs +++ b/core/src/blocktree.rs @@ -124,8 +124,8 @@ pub trait LedgerColumnFamilyRaw { // The Meta column family pub struct SlotMeta { // The number of slots above the root (the genesis block). The first - // slot has slot_height 0. - pub slot_height: u64, + // slot has slot 0. + pub slot: u64, // The total number of consecutive blobs starting from index 0 // we have received for this slot. pub consumed: u64, @@ -141,7 +141,7 @@ pub struct SlotMeta { // from this one. pub next_slots: Vec, // True if this slot is full (consumed == last_index + 1) and if every - // slot from 0..slot_height is also rooted. + // slot that is a parent of this slot is also rooted. pub is_rooted: bool, } @@ -158,14 +158,14 @@ impl SlotMeta { self.consumed == self.last_index + 1 } - fn new(slot_height: u64, parent_slot: u64) -> Self { + fn new(slot: u64, parent_slot: u64) -> Self { SlotMeta { - slot_height, + slot, consumed: 0, received: 0, parent_slot, next_slots: vec![], - is_rooted: slot_height == 0, + is_rooted: slot == 0, last_index: std::u64::MAX, } } @@ -180,19 +180,19 @@ impl MetaCf { MetaCf { db } } - pub fn key(slot_height: u64) -> Vec { + pub fn key(slot: u64) -> Vec { let mut key = vec![0u8; 8]; - BigEndian::write_u64(&mut key[0..8], slot_height); + BigEndian::write_u64(&mut key[0..8], slot); key } - pub fn get_slot_meta(&self, slot_height: u64) -> Result> { - let key = Self::key(slot_height); + pub fn get_slot_meta(&self, slot: u64) -> Result> { + let key = Self::key(slot); self.get(&key) } - pub fn put_slot_meta(&self, slot_height: u64, slot_meta: &SlotMeta) -> Result<()> { - let key = Self::key(slot_height); + pub fn put_slot_meta(&self, slot: u64, slot_meta: &SlotMeta) -> Result<()> { + let key = Self::key(slot); self.put(&key, slot_meta) } @@ -225,34 +225,29 @@ impl DataCf { DataCf { db } } - pub fn get_by_slot_index(&self, slot_height: u64, index: u64) -> Result>> { - let key = Self::key(slot_height, index); + pub fn get_by_slot_index(&self, slot: u64, index: u64) -> Result>> { + let key = Self::key(slot, index); self.get(&key) } - pub fn delete_by_slot_index(&self, slot_height: u64, index: u64) -> Result<()> { - let key = Self::key(slot_height, index); + pub fn delete_by_slot_index(&self, slot: u64, index: u64) -> Result<()> { + let key = Self::key(slot, index); self.delete(&key) } - pub fn put_by_slot_index( - &self, - slot_height: u64, - index: u64, - serialized_value: &[u8], - ) -> Result<()> { - let key = Self::key(slot_height, index); + pub fn put_by_slot_index(&self, slot: u64, index: u64, serialized_value: &[u8]) -> Result<()> { + let key = Self::key(slot, index); self.put(&key, serialized_value) } - pub fn key(slot_height: u64, index: u64) -> Vec { + pub fn key(slot: u64, index: u64) -> Vec { let mut key = vec![0u8; 16]; - BigEndian::write_u64(&mut key[0..8], slot_height); + BigEndian::write_u64(&mut key[0..8], slot); BigEndian::write_u64(&mut key[8..16], index); key } - pub fn slot_height_from_key(key: &[u8]) -> Result { + pub fn slot_from_key(key: &[u8]) -> Result { let mut rdr = io::Cursor::new(&key[0..8]); let height = rdr.read_u64::()?; Ok(height) @@ -284,32 +279,27 @@ impl ErasureCf { pub fn new(db: Arc) -> Self { ErasureCf { db } } - pub fn delete_by_slot_index(&self, slot_height: u64, index: u64) -> Result<()> { - let key = Self::key(slot_height, index); + pub fn delete_by_slot_index(&self, slot: u64, index: u64) -> Result<()> { + let key = Self::key(slot, index); self.delete(&key) } - pub fn get_by_slot_index(&self, slot_height: u64, index: u64) -> Result>> { - let key = Self::key(slot_height, index); + pub fn get_by_slot_index(&self, slot: u64, index: u64) -> Result>> { + let key = Self::key(slot, index); self.get(&key) } - pub fn put_by_slot_index( - &self, - slot_height: u64, - index: u64, - serialized_value: &[u8], - ) -> Result<()> { - let key = Self::key(slot_height, index); + pub fn put_by_slot_index(&self, slot: u64, index: u64, serialized_value: &[u8]) -> Result<()> { + let key = Self::key(slot, index); self.put(&key, serialized_value) } - pub fn key(slot_height: u64, index: u64) -> Vec { - DataCf::key(slot_height, index) + pub fn key(slot: u64, index: u64) -> Vec { + DataCf::key(slot, index) } - pub fn slot_height_from_key(key: &[u8]) -> Result { - DataCf::slot_height_from_key(key) + pub fn slot_from_key(key: &[u8]) -> Result { + DataCf::slot_from_key(key) } pub fn index_from_key(key: &[u8]) -> Result { @@ -413,15 +403,15 @@ impl Blocktree { Ok((blocktree, signal_receiver)) } - pub fn meta(&self, slot_height: u64) -> Result> { - self.meta_cf.get(&MetaCf::key(slot_height)) + pub fn meta(&self, slot: u64) -> Result> { + self.meta_cf.get(&MetaCf::key(slot)) } - pub fn reset_slot_consumed(&self, slot_height: u64) -> Result<()> { - let meta_key = MetaCf::key(slot_height); + pub fn reset_slot_consumed(&self, slot: u64) -> Result<()> { + let meta_key = MetaCf::key(slot); if let Some(mut meta) = self.meta_cf.get(&meta_key)? { for index in 0..meta.received { - self.data_cf.delete_by_slot_index(slot_height, index)?; + self.data_cf.delete_by_slot_index(slot, index)?; } meta.consumed = 0; meta.received = 0; @@ -440,9 +430,9 @@ impl Blocktree { Ok(()) } - pub fn get_next_slot(&self, slot_height: u64) -> Result> { + pub fn get_next_slot(&self, slot: u64) -> Result> { let mut db_iterator = self.db.raw_iterator_cf(self.meta_cf.handle())?; - db_iterator.seek(&MetaCf::key(slot_height + 1)); + db_iterator.seek(&MetaCf::key(slot + 1)); if !db_iterator.valid() { Ok(None) } else { @@ -537,7 +527,7 @@ impl Blocktree { I::Item: Borrow, { let mut write_batch = WriteBatch::default(); - // A map from slot_height to a 2-tuple of metadata: (working copy, backup copy), + // A map from slot to a 2-tuple of metadata: (working copy, backup copy), // so we can detect changes to the slot metadata later let mut slot_meta_working_set = HashMap::new(); let new_blobs: Vec<_> = new_blobs.into_iter().collect(); @@ -596,14 +586,14 @@ impl Blocktree { // Check if any metadata was changed, if so, insert the new version of the // metadata into the write batch - for (slot_height, (meta_copy, meta_backup)) in slot_meta_working_set.iter() { + for (slot, (meta_copy, meta_backup)) in slot_meta_working_set.iter() { let meta: &SlotMeta = &RefCell::borrow(&*meta_copy); // Check if the working copy of the metadata has changed if Some(meta) != meta_backup.as_ref() { should_signal = should_signal || Self::slot_has_updates(meta, &meta_backup); write_batch.put_cf( self.meta_cf.handle(), - &MetaCf::key(*slot_height), + &MetaCf::key(*slot), &serialize(&meta)?, )?; } @@ -628,9 +618,9 @@ impl Blocktree { start_index: u64, num_blobs: u64, buf: &mut [u8], - slot_height: u64, + slot: u64, ) -> Result<(u64, u64)> { - let start_key = DataCf::key(slot_height, start_index); + let start_key = DataCf::key(slot, start_index); let mut db_iterator = self.db.raw_iterator_cf(self.data_cf.handle())?; db_iterator.seek(&start_key); let mut total_blobs = 0; @@ -721,11 +711,11 @@ impl Blocktree { self.data_cf.put_by_slot_index(slot, index, bytes) } - pub fn get_data_blob(&self, slot_height: u64, blob_index: u64) -> Result> { - let bytes = self.get_data_blob_bytes(slot_height, blob_index)?; + pub fn get_data_blob(&self, slot: u64, blob_index: u64) -> Result> { + let bytes = self.get_data_blob_bytes(slot, blob_index)?; Ok(bytes.map(|bytes| { let blob = Blob::new(&bytes); - assert!(blob.slot() == slot_height); + assert!(blob.slot() == slot); assert!(blob.index() == blob_index); blob })) @@ -742,14 +732,14 @@ impl Blocktree { // Given a start and end entry index, find all the missing // indexes in the ledger in the range [start_index, end_index) - // for the slot with slot_height == slot + // for the slot with the specified slot fn find_missing_indexes( db_iterator: &mut BlocktreeRawIterator, slot: u64, start_index: u64, end_index: u64, key: &dyn Fn(u64, u64) -> Vec, - slot_height_from_key: &dyn Fn(&[u8]) -> Result, + slot_from_key: &dyn Fn(&[u8]) -> Result, index_from_key: &dyn Fn(&[u8]) -> Result, max_missing: usize, ) -> Vec { @@ -775,7 +765,7 @@ impl Blocktree { break; } let current_key = db_iterator.key().expect("Expect a valid key"); - let current_slot = slot_height_from_key(¤t_key) + let current_slot = slot_from_key(¤t_key) .expect("Expect to be able to parse slot from valid key"); let current_index = { if current_slot > slot { @@ -824,7 +814,7 @@ impl Blocktree { start_index, end_index, &DataCf::key, - &DataCf::slot_height_from_key, + &DataCf::slot_from_key, &DataCf::index_from_key, max_missing, ) @@ -845,7 +835,7 @@ impl Blocktree { start_index, end_index, &ErasureCf::key, - &ErasureCf::slot_height_from_key, + &ErasureCf::slot_from_key, &ErasureCf::index_from_key, max_missing, ) @@ -854,42 +844,36 @@ impl Blocktree { /// Returns the entry vector for the slot starting with `blob_start_index` pub fn get_slot_entries( &self, - slot_height: u64, + slot: u64, blob_start_index: u64, max_entries: Option, ) -> Result> { - self.get_slot_entries_with_blob_count(slot_height, blob_start_index, max_entries) + self.get_slot_entries_with_blob_count(slot, blob_start_index, max_entries) .map(|x| x.0) } pub fn get_slot_entries_with_blob_count( &self, - slot_height: u64, + slot: u64, blob_start_index: u64, max_entries: Option, ) -> Result<(Vec, usize)> { // Find the next consecutive block of blobs. - let consecutive_blobs = self.get_slot_consecutive_blobs( - slot_height, - &HashMap::new(), - blob_start_index, - max_entries, - )?; + let consecutive_blobs = + self.get_slot_consecutive_blobs(slot, &HashMap::new(), blob_start_index, max_entries)?; let num = consecutive_blobs.len(); Ok((Self::deserialize_blobs(&consecutive_blobs), num)) } - // Returns slots connecting to any element of the list `slot_heights`. - pub fn get_slots_since(&self, slot_heights: &[u64]) -> Result>> { + // Returns slots connecting to any element of the list `slots`. + pub fn get_slots_since(&self, slots: &[u64]) -> Result>> { // Return error if there was a database error during lookup of any of the // slot indexes - let slot_metas: Result>> = slot_heights - .iter() - .map(|slot_height| self.meta(*slot_height)) - .collect(); + let slot_metas: Result>> = + slots.iter().map(|slot| self.meta(*slot)).collect(); let slot_metas = slot_metas?; - let result: HashMap> = slot_heights + let result: HashMap> = slots .iter() .zip(slot_metas) .filter_map(|(height, meta)| meta.map(|meta| (*height, meta.next_slots))) @@ -956,17 +940,17 @@ impl Blocktree { working_set: &HashMap>, Option)>, ) -> Result<()> { let mut new_chained_slots = HashMap::new(); - let working_set_slot_heights: Vec<_> = working_set.iter().map(|s| *s.0).collect(); - for slot_height in working_set_slot_heights { - self.handle_chaining_for_slot(working_set, &mut new_chained_slots, slot_height)?; + let working_set_slots: Vec<_> = working_set.iter().map(|s| *s.0).collect(); + for slot in working_set_slots { + self.handle_chaining_for_slot(working_set, &mut new_chained_slots, slot)?; } // Write all the newly changed slots in new_chained_slots to the write_batch - for (slot_height, meta_copy) in new_chained_slots.iter() { + for (slot, meta_copy) in new_chained_slots.iter() { let meta: &SlotMeta = &RefCell::borrow(&*meta_copy); write_batch.put_cf( self.meta_cf.handle(), - &MetaCf::key(*slot_height), + &MetaCf::key(*slot), &serialize(meta)?, )?; } @@ -977,35 +961,32 @@ impl Blocktree { &self, working_set: &HashMap>, Option)>, new_chained_slots: &mut HashMap>>, - slot_height: u64, + slot: u64, ) -> Result<()> { let (meta_copy, meta_backup) = working_set - .get(&slot_height) + .get(&slot) .expect("Slot must exist in the working_set hashmap"); { let mut slot_meta = meta_copy.borrow_mut(); // If: // 1) This is a new slot - // 2) slot_height != 0 + // 2) slot != 0 // then try to chain this slot to a previous slot - if slot_height != 0 { - let prev_slot_height = slot_meta.parent_slot; + if slot != 0 { + let prev_slot = slot_meta.parent_slot; // Check if slot_meta is a new slot if meta_backup.is_none() { - let prev_slot = self.find_slot_meta_else_create( - working_set, - new_chained_slots, - prev_slot_height, - )?; + let prev_slot = + self.find_slot_meta_else_create(working_set, new_chained_slots, prev_slot)?; // This is a newly inserted slot so: // 1) Chain to the previous slot, and also // 2) Determine whether to set the is_rooted flag self.chain_new_slot_to_prev_slot( &mut prev_slot.borrow_mut(), - slot_height, + slot, &mut slot_meta, ); } @@ -1018,7 +999,7 @@ impl Blocktree { // This is a newly inserted slot and slot.is_rooted is true, so go through // and update all child slots with is_rooted if applicable let mut next_slots: Vec<(u64, Rc>)> = - vec![(slot_height, meta_copy.clone())]; + vec![(slot, meta_copy.clone())]; while !next_slots.is_empty() { let (_, current_slot) = next_slots.pop().unwrap(); current_slot.borrow_mut().is_rooted = true; @@ -1042,12 +1023,12 @@ impl Blocktree { fn chain_new_slot_to_prev_slot( &self, - prev_slot: &mut SlotMeta, - current_slot_height: u64, - current_slot: &mut SlotMeta, + prev_slot_meta: &mut SlotMeta, + current_slot: u64, + current_slot_meta: &mut SlotMeta, ) { - prev_slot.next_slots.push(current_slot_height); - current_slot.is_rooted = prev_slot.is_rooted && prev_slot.is_full(); + prev_slot_meta.next_slots.push(current_slot); + current_slot_meta.is_rooted = prev_slot_meta.is_rooted && prev_slot_meta.is_full(); } fn is_newly_completed_slot( @@ -1082,21 +1063,21 @@ impl Blocktree { // create a dummy placeholder slot in the database fn find_slot_meta_in_db_else_create<'a>( &self, - slot_height: u64, + slot: u64, insert_map: &'a mut HashMap>>, ) -> Result>> { - if let Some(slot) = self.meta(slot_height)? { - insert_map.insert(slot_height, Rc::new(RefCell::new(slot))); - Ok(insert_map.get(&slot_height).unwrap().clone()) + if let Some(slot_meta) = self.meta(slot)? { + insert_map.insert(slot, Rc::new(RefCell::new(slot_meta))); + Ok(insert_map.get(&slot).unwrap().clone()) } else { // If this slot doesn't exist, make a placeholder slot. This way we // remember which slots chained to this one when we eventually get a real blob // for this slot insert_map.insert( - slot_height, - Rc::new(RefCell::new(SlotMeta::new(slot_height, std::u64::MAX))), + slot, + Rc::new(RefCell::new(SlotMeta::new(slot, std::u64::MAX))), ); - Ok(insert_map.get(&slot_height).unwrap().clone()) + Ok(insert_map.get(&slot).unwrap().clone()) } } @@ -1105,11 +1086,11 @@ impl Blocktree { &self, working_set: &'a HashMap>, Option)>, chained_slots: &'a HashMap>>, - slot_height: u64, + slot: u64, ) -> Result>>> { - if let Some((entry, _)) = working_set.get(&slot_height) { + if let Some((entry, _)) = working_set.get(&slot) { Ok(Some(entry.clone())) - } else if let Some(entry) = chained_slots.get(&slot_height) { + } else if let Some(entry) = chained_slots.get(&slot) { Ok(Some(entry.clone())) } else { Ok(None) @@ -1185,7 +1166,7 @@ impl Blocktree { /// range fn get_slot_consecutive_blobs<'a>( &self, - slot_height: u64, + slot: u64, prev_inserted_blob_datas: &HashMap<(u64, u64), &'a [u8]>, mut current_index: u64, max_blobs: Option, @@ -1196,13 +1177,9 @@ impl Blocktree { break; } // Try to find the next blob we're looking for in the prev_inserted_blob_datas - if let Some(prev_blob_data) = - prev_inserted_blob_datas.get(&(slot_height, current_index)) - { + if let Some(prev_blob_data) = prev_inserted_blob_datas.get(&(slot, current_index)) { blobs.push(Cow::Borrowed(*prev_blob_data)); - } else if let Some(blob_data) = - self.data_cf.get_by_slot_index(slot_height, current_index)? - { + } else if let Some(blob_data) = self.data_cf.get_by_slot_index(slot, current_index)? { // Try to find the next blob we're looking for in the database blobs.push(Cow::Owned(blob_data)); } else { @@ -1791,22 +1768,20 @@ pub mod tests { // Write entries let num_slots = 5 as u64; let mut index = 0; - for slot_height in 0..num_slots { - let entries = make_tiny_test_entries(slot_height as usize + 1); + for slot in 0..num_slots { + let entries = make_tiny_test_entries(slot as usize + 1); let last_entry = entries.last().unwrap().clone(); let mut blobs = entries.clone().to_blobs(); for b in blobs.iter_mut() { b.set_index(index); - b.set_slot(slot_height as u64); + b.set_slot(slot as u64); index += 1; } blocktree .write_blobs(&blobs) .expect("Expected successful write of blobs"); assert_eq!( - blocktree - .get_slot_entries(slot_height, index - 1, None) - .unwrap(), + blocktree.get_slot_entries(slot, index - 1, None).unwrap(), vec![last_entry], ); } @@ -2003,10 +1978,9 @@ pub mod tests { let num_slots = entries_per_slot; let mut blobs: Vec = vec![]; let mut missing_blobs = vec![]; - for slot_height in 1..num_slots + 1 { - let (mut slot_blobs, _) = - make_slot_entries(slot_height, slot_height - 1, entries_per_slot); - let missing_blob = slot_blobs.remove(slot_height as usize - 1); + for slot in 1..num_slots + 1 { + let (mut slot_blobs, _) = make_slot_entries(slot, slot - 1, entries_per_slot); + let missing_blob = slot_blobs.remove(slot as usize - 1); blobs.extend(slot_blobs); missing_blobs.push(missing_blob); } @@ -2018,8 +1992,8 @@ pub mod tests { // Insert a blob for each slot that doesn't make a consecutive block, we // should get no updates let blobs: Vec<_> = (1..num_slots + 1) - .flat_map(|slot_height| { - let (mut blob, _) = make_slot_entries(slot_height, slot_height - 1, 1); + .flat_map(|slot| { + let (mut blob, _) = make_slot_entries(slot, slot - 1, 1); blob[0].set_index(2 * num_slots as u64); blob }) @@ -2124,17 +2098,17 @@ pub mod tests { // Separate every other slot into two separate vectors let mut slots = vec![]; let mut missing_slots = vec![]; - for slot_height in 0..num_slots { + for slot in 0..num_slots { let parent_slot = { - if slot_height == 0 { + if slot == 0 { 0 } else { - slot_height - 1 + slot - 1 } }; - let (slot_blobs, _) = make_slot_entries(slot_height, parent_slot, entries_per_slot); + let (slot_blobs, _) = make_slot_entries(slot, parent_slot, entries_per_slot); - if slot_height % 2 == 1 { + if slot % 2 == 1 { slots.extend(slot_blobs); } else { missing_slots.extend(slot_blobs); @@ -2205,8 +2179,8 @@ pub mod tests { let (blobs, _) = make_many_slot_entries(0, num_slots, entries_per_slot); // Write the blobs such that every 3rd slot has a gap in the beginning - for (slot_height, slot_ticks) in blobs.chunks(entries_per_slot as usize).enumerate() { - if slot_height % 3 == 0 { + for (slot, slot_ticks) in blobs.chunks(entries_per_slot as usize).enumerate() { + if slot % 3 == 0 { blocktree .write_blobs(&slot_ticks[1..entries_per_slot as usize]) .unwrap(); @@ -2296,17 +2270,17 @@ pub mod tests { // Get blobs for the slot slots.shuffle(&mut thread_rng()); - for slot_height in slots { - // Get blobs for the slot "slot_height" - let slot_blobs = &mut blobs[(slot_height * entries_per_slot) as usize - ..((slot_height + 1) * entries_per_slot) as usize]; + for slot in slots { + // Get blobs for the slot "slot" + let slot_blobs = &mut blobs + [(slot * entries_per_slot) as usize..((slot + 1) * entries_per_slot) as usize]; for blob in slot_blobs.iter_mut() { // Get the parent slot of the slot in the tree let slot_parent = { - if slot_height == 0 { + if slot == 0 { 0 } else { - (slot_height - 1) / branching_factor + (slot - 1) / branching_factor } }; blob.set_parent(slot_parent); @@ -2318,27 +2292,25 @@ pub mod tests { // Make sure everything chains correctly let last_level = (branching_factor.pow(num_tree_levels - 1) - 1) / (branching_factor - 1); - for slot_height in 0..num_slots { - let slot_meta = blocktree.meta(slot_height).unwrap().unwrap(); + for slot in 0..num_slots { + let slot_meta = blocktree.meta(slot).unwrap().unwrap(); assert_eq!(slot_meta.consumed, entries_per_slot); assert_eq!(slot_meta.received, entries_per_slot); let slot_parent = { - if slot_height == 0 { + if slot == 0 { 0 } else { - (slot_height - 1) / branching_factor + (slot - 1) / branching_factor } }; assert_eq!(slot_meta.parent_slot, slot_parent); let expected_children: HashSet<_> = { - if slot_height >= last_level { + if slot >= last_level { HashSet::new() } else { - let first_child_slot = - min(num_slots - 1, slot_height * branching_factor + 1); - let last_child_slot = - min(num_slots - 1, (slot_height + 1) * branching_factor); + let first_child_slot = min(num_slots - 1, slot * branching_factor + 1); + let last_child_slot = min(num_slots - 1, (slot + 1) * branching_factor); (first_child_slot..last_child_slot + 1).collect() } }; @@ -2402,17 +2374,17 @@ pub mod tests { let num_entries = 20 as u64; let mut entries = vec![]; let mut blobs = vec![]; - for slot_height in 0..num_entries { + for slot in 0..num_entries { let parent_slot = { - if slot_height == 0 { + if slot == 0 { 0 } else { - slot_height - 1 + slot - 1 } }; - let (mut blob, entry) = make_slot_entries(slot_height, parent_slot, 1); - blob[0].set_index(slot_height); + let (mut blob, entry) = make_slot_entries(slot, parent_slot, 1); + blob[0].set_index(slot); blobs.extend(blob); entries.extend(entry); } @@ -2451,14 +2423,14 @@ pub mod tests { pub fn entries_to_blobs( entries: &Vec, - slot_height: u64, + slot: u64, parent_slot: u64, is_full_slot: bool, ) -> Vec { let mut blobs = entries.clone().to_blobs(); for (i, b) in blobs.iter_mut().enumerate() { b.set_index(i as u64); - b.set_slot(slot_height); + b.set_slot(slot); b.set_parent(parent_slot); } if is_full_slot { @@ -2468,27 +2440,26 @@ pub mod tests { } pub fn make_slot_entries( - slot_height: u64, + slot: u64, parent_slot: u64, num_entries: u64, ) -> (Vec, Vec) { let entries = make_tiny_test_entries(num_entries as usize); - let blobs = entries_to_blobs(&entries, slot_height, parent_slot, true); + let blobs = entries_to_blobs(&entries, slot, parent_slot, true); (blobs, entries) } pub fn make_many_slot_entries( - start_slot_height: u64, + start_slot: u64, num_slots: u64, entries_per_slot: u64, ) -> (Vec, Vec) { let mut blobs = vec![]; let mut entries = vec![]; - for slot_height in start_slot_height..start_slot_height + num_slots { - let parent_slot = if slot_height == 0 { 0 } else { slot_height - 1 }; + for slot in start_slot..start_slot + num_slots { + let parent_slot = if slot == 0 { 0 } else { slot - 1 }; - let (slot_blobs, slot_entries) = - make_slot_entries(slot_height, parent_slot, entries_per_slot); + let (slot_blobs, slot_entries) = make_slot_entries(slot, parent_slot, entries_per_slot); blobs.extend(slot_blobs); entries.extend(slot_entries); } diff --git a/core/src/broadcast_stage.rs b/core/src/broadcast_stage.rs index 80f1a4206d..73c10d657d 100644 --- a/core/src/broadcast_stage.rs +++ b/core/src/broadcast_stage.rs @@ -52,7 +52,6 @@ impl Broadcast { broadcast_table.truncate(DATA_PLANE_FANOUT); inc_new_counter_info!("broadcast_service-num_peers", broadcast_table.len() + 1); - let slot_height = bank.slot(); let max_tick_height = (bank.slot() + 1) * bank.ticks_per_slot() - 1; // TODO: Fix BankingStage/BroadcastStage to operate on `slot` directly instead of // `max_tick_height` @@ -91,8 +90,7 @@ impl Broadcast { }) .collect(); - // TODO: blob_index should be slot-relative... - index_blobs(&blobs, &self.id, &mut blob_index, slot_height); + index_blobs(&blobs, &self.id, &mut blob_index, bank.slot()); let parent = bank.parents().first().map(|bank| bank.slot()).unwrap_or(0); for b in blobs.iter() { b.write().unwrap().set_parent(parent); diff --git a/core/src/cluster_info.rs b/core/src/cluster_info.rs index 356c401994..abd5a02149 100644 --- a/core/src/cluster_info.rs +++ b/core/src/cluster_info.rs @@ -720,26 +720,25 @@ impl ClusterInfo { orders } - pub fn window_index_request_bytes(&self, slot_height: u64, blob_index: u64) -> Result> { - let req = Protocol::RequestWindowIndex(self.my_data().clone(), slot_height, blob_index); + pub fn window_index_request_bytes(&self, slot: u64, blob_index: u64) -> Result> { + let req = Protocol::RequestWindowIndex(self.my_data().clone(), slot, blob_index); let out = serialize(&req)?; Ok(out) } pub fn window_highest_index_request_bytes( &self, - slot_height: u64, + slot: u64, blob_index: u64, ) -> Result> { - let req = - Protocol::RequestHighestWindowIndex(self.my_data().clone(), slot_height, blob_index); + let req = Protocol::RequestHighestWindowIndex(self.my_data().clone(), slot, blob_index); let out = serialize(&req)?; Ok(out) } pub fn window_index_request( &self, - slot_height: u64, + slot: u64, blob_index: u64, get_highest: bool, ) -> Result<(SocketAddr, Vec)> { @@ -753,9 +752,9 @@ impl ClusterInfo { let addr = valid[n].gossip; // send the request to the peer's gossip port let out = { if get_highest { - self.window_highest_index_request_bytes(slot_height, blob_index)? + self.window_highest_index_request_bytes(slot, blob_index)? } else { - self.window_index_request_bytes(slot_height, blob_index)? + self.window_index_request_bytes(slot, blob_index)? } }; @@ -909,12 +908,12 @@ impl ClusterInfo { from_addr: &SocketAddr, blocktree: Option<&Arc>, me: &NodeInfo, - slot_height: u64, + slot: u64, blob_index: u64, ) -> Vec { if let Some(blocktree) = blocktree { // Try to find the requested index in one of the slots - let blob = blocktree.get_data_blob(slot_height, blob_index); + let blob = blocktree.get_data_blob(slot, blob_index); if let Ok(Some(mut blob)) = blob { inc_new_counter_info!("cluster_info-window-request-ledger", 1); @@ -929,7 +928,7 @@ impl ClusterInfo { "{}: failed RequestWindowIndex {} {} {}", me.id, from.id, - slot_height, + slot, blob_index, ); @@ -939,17 +938,17 @@ impl ClusterInfo { fn run_highest_window_request( from_addr: &SocketAddr, blocktree: Option<&Arc>, - slot_height: u64, + slot: u64, highest_index: u64, ) -> Vec { if let Some(blocktree) = blocktree { // Try to find the requested index in one of the slots - let meta = blocktree.meta(slot_height); + let meta = blocktree.meta(slot); if let Ok(Some(meta)) = meta { if meta.received > highest_index { // meta.received must be at least 1 by this point - let blob = blocktree.get_data_blob(slot_height, meta.received - 1); + let blob = blocktree.get_data_blob(slot, meta.received - 1); if let Ok(Some(mut blob)) = blob { blob.meta.set_addr(from_addr); @@ -1082,7 +1081,7 @@ impl ClusterInfo { me: &Arc>, from: &ContactInfo, blocktree: Option<&Arc>, - slot_height: u64, + slot: u64, blob_index: u64, from_addr: &SocketAddr, is_get_highest: bool, @@ -1097,7 +1096,7 @@ impl ClusterInfo { if from.id == me.read().unwrap().gossip.id { warn!( "{}: Ignored received RequestWindowIndex from ME {} {} {} ", - self_id, from.id, slot_height, blob_index, + self_id, from.id, slot, blob_index, ); inc_new_counter_info!("cluster_info-window-request-address-eq", 1); return vec![]; @@ -1107,30 +1106,23 @@ impl ClusterInfo { let my_info = me.read().unwrap().my_data().clone(); inc_new_counter_info!("cluster_info-window-request-recv", 1); trace!( - "{}: received RequestWindowIndex from: {} slot_height: {}, blob_index: {}", + "{}: received RequestWindowIndex from: {} slot: {}, blob_index: {}", self_id, from.id, - slot_height, + slot, blob_index, ); let res = { if is_get_highest { - Self::run_highest_window_request(&from_addr, blocktree, slot_height, blob_index) + Self::run_highest_window_request(&from_addr, blocktree, slot, blob_index) } else { - Self::run_window_request( - &from, - &from_addr, - blocktree, - &my_info, - slot_height, - blob_index, - ) + Self::run_window_request(&from, &from_addr, blocktree, &my_info, slot, blob_index) } }; report_time_spent( "RequestWindowIndex", &now.elapsed(), - &format!("slot_height {}, blob_index: {}", slot_height, blob_index), + &format!("slot {}, blob_index: {}", slot, blob_index), ); res } @@ -1193,23 +1185,17 @@ impl ClusterInfo { } vec![] } - Protocol::RequestWindowIndex(from, slot_height, blob_index) => { + Protocol::RequestWindowIndex(from, slot, blob_index) => { Self::handle_request_window_index( - me, - &from, - blocktree, - slot_height, - blob_index, - from_addr, - false, + me, &from, blocktree, slot, blob_index, from_addr, false, ) } - Protocol::RequestHighestWindowIndex(from, slot_height, highest_index) => { + Protocol::RequestHighestWindowIndex(from, slot, highest_index) => { Self::handle_request_window_index( me, &from, blocktree, - slot_height, + slot, highest_index, from_addr, true, diff --git a/core/src/db_window.rs b/core/src/db_window.rs index 0e67de31b9..f8786d6f61 100644 --- a/core/src/db_window.rs +++ b/core/src/db_window.rs @@ -360,10 +360,10 @@ mod test { .collect(); // For each slot, find all missing indexes in the range [0, num_entries_per_slot * nth] - for slot_height in 0..num_slots { + for slot in 0..num_slots { assert_eq!( blocktree.find_missing_data_indexes( - slot_height as u64, + slot as u64, 0, (num_entries_per_slot * nth) as u64, num_entries_per_slot * nth as usize @@ -373,10 +373,10 @@ mod test { } // Test with a limit on the number of returned entries - for slot_height in 0..num_slots { + for slot in 0..num_slots { assert_eq!( blocktree.find_missing_data_indexes( - slot_height as u64, + slot as u64, 0, (num_entries_per_slot * nth) as u64, num_entries_per_slot * (nth - 1) @@ -392,10 +392,10 @@ mod test { expected.extend(extra_entries); // For each slot, find all missing indexes in the range [0, num_entries_per_slot * nth] - for slot_height in 0..num_slots { + for slot in 0..num_slots { assert_eq!( blocktree.find_missing_data_indexes( - slot_height as u64, + slot as u64, 0, (num_entries_per_slot * (nth + 1)) as u64, num_entries_per_slot * (nth + 1), @@ -441,8 +441,8 @@ mod test { // Setup the window let offset = 0; let num_blobs = NUM_DATA + 2; - let slot_height = 0; - let mut window = setup_window_ledger(offset, num_blobs, false, slot_height); + let slot = 0; + let mut window = setup_window_ledger(offset, num_blobs, false, slot); let end_index = (offset + num_blobs) % window.len(); // Test erasing a data block and an erasure block @@ -466,7 +466,7 @@ mod test { { let data_blobs: Vec<_> = window[erased_index..end_index] .iter() - .map(|slot| slot.data.clone().unwrap()) + .map(|entry| entry.data.clone().unwrap()) .collect(); let locks: Vec<_> = data_blobs.iter().map(|blob| blob.read().unwrap()).collect(); @@ -490,7 +490,7 @@ mod test { let erased_coding_l = erased_coding.read().unwrap(); assert_eq!( &blocktree - .get_coding_blob_bytes(slot_height, erased_index as u64) + .get_coding_blob_bytes(slot, erased_index as u64) .unwrap() .unwrap()[BLOB_HEADER_SIZE..], &erased_coding_l.data()[..erased_coding_l.size() as usize], diff --git a/core/src/fullnode.rs b/core/src/fullnode.rs index 5d34919a84..04a8044ce2 100644 --- a/core/src/fullnode.rs +++ b/core/src/fullnode.rs @@ -331,7 +331,7 @@ pub fn make_active_set_entries( active_keypair: &Arc, token_source: &Keypair, stake: u64, - slot_height_to_vote_on: u64, + slot_to_vote_on: u64, blockhash: &Hash, num_ending_ticks: u64, ) -> (Vec, Keypair) { @@ -360,7 +360,7 @@ pub fn make_active_set_entries( let new_vote_account_entry = next_entry_mut(&mut last_entry_hash, 1, vec![new_vote_account_tx]); // 3) Create vote entry - let vote_tx = VoteTransaction::new_vote(&voting_keypair, slot_height_to_vote_on, *blockhash, 0); + let vote_tx = VoteTransaction::new_vote(&voting_keypair, slot_to_vote_on, *blockhash, 0); let vote_entry = next_entry_mut(&mut last_entry_hash, 1, vec![vote_tx]); // 4) Create `num_ending_ticks` empty ticks diff --git a/core/src/leader_confirmation_service.rs b/core/src/leader_confirmation_service.rs index c5b15a89a6..cd7d1769ea 100644 --- a/core/src/leader_confirmation_service.rs +++ b/core/src/leader_confirmation_service.rs @@ -37,7 +37,7 @@ impl LeaderConfirmationService { if let Some(stake_and_state) = vote_state .votes .back() - .map(|vote| (vote.slot_height, account.tokens)) + .map(|vote| (vote.slot, account.tokens)) { slots_and_stakes.push(stake_and_state); } @@ -116,6 +116,7 @@ mod tests { use bincode::serialize; use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::hash::hash; + use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_vote_api::vote_transaction::VoteTransaction; use std::sync::Arc; @@ -125,14 +126,22 @@ mod tests { solana_logger::setup(); let (genesis_block, mint_keypair) = GenesisBlock::new(1234); - let bank = Arc::new(Bank::new(&genesis_block)); + let mut tick_hash = genesis_block.hash(); + + let mut bank = Arc::new(Bank::new(&genesis_block)); // Move the bank up 10 slots - let mut tick_hash = genesis_block.hash(); - while bank.slot_height() < 10 { - tick_hash = hash(&serialize(&tick_hash).unwrap()); - bank.register_tick(&tick_hash); + for slot in 1..=10 { + let max_tick_height = slot * bank.ticks_per_slot() - 1; + + while bank.tick_height() != max_tick_height { + tick_hash = hash(&serialize(&tick_hash).unwrap()); + bank.register_tick(&tick_hash); + } + + bank = Arc::new(Bank::new_from_parent(&bank, Pubkey::default(), slot)); } + let blockhash = bank.last_blockhash(); // Create a total of 10 vote accounts, each will have a balance of 1 (after giving 1 to diff --git a/core/src/repair_service.rs b/core/src/repair_service.rs index fbf8813ca2..8670202f6e 100644 --- a/core/src/repair_service.rs +++ b/core/src/repair_service.rs @@ -62,7 +62,7 @@ impl RepairService { let reqs: Vec<_> = repairs .into_iter() .filter_map(|repair_request| { - let (slot_height, blob_index, is_highest_request) = { + let (slot, blob_index, is_highest_request) = { match repair_request { RepairType::Blob(s, i) => (s, i, false), RepairType::HighestBlob(s, i) => (s, i, true), @@ -71,20 +71,17 @@ impl RepairService { cluster_info .read() .unwrap() - .window_index_request(slot_height, blob_index, is_highest_request) - .map(|result| (result, slot_height, blob_index)) + .window_index_request(slot, blob_index, is_highest_request) + .map(|result| (result, slot, blob_index)) .ok() }) .collect(); - for ((to, req), slot_height, blob_index) in reqs { + for ((to, req), slot, blob_index) in reqs { if let Ok(local_addr) = repair_socket.local_addr() { submit( influxdb::Point::new("repair_service") - .add_field( - "repair_slot", - influxdb::Value::Integer(slot_height as i64), - ) + .add_field("repair_slot", influxdb::Value::Integer(slot as i64)) .to_owned() .add_field( "repair_blob", @@ -127,24 +124,24 @@ impl RepairService { fn process_slot( blocktree: &Blocktree, - slot_height: u64, - slot: &SlotMeta, + slot: u64, + slot_meta: &SlotMeta, max_repairs: usize, ) -> Vec { - if slot.is_full() { + if slot_meta.is_full() { vec![] - } else if slot.consumed == slot.received { - vec![RepairType::HighestBlob(slot_height, slot.received)] + } else if slot_meta.consumed == slot_meta.received { + vec![RepairType::HighestBlob(slot, slot_meta.received)] } else { let reqs = blocktree.find_missing_data_indexes( - slot_height, - slot.consumed, - slot.received, + slot, + slot_meta.consumed, + slot_meta.received, max_repairs, ); reqs.into_iter() - .map(|i| RepairType::Blob(slot_height, i)) + .map(|i| RepairType::Blob(slot, i)) .collect() } } @@ -156,25 +153,25 @@ impl RepairService { ) -> Result<(Vec)> { // Slot height and blob indexes for blobs we want to repair let mut repairs: Vec = vec![]; - let mut current_slot_height = Some(0); - while repairs.len() < max_repairs && current_slot_height.is_some() { - if current_slot_height.unwrap() > repair_info.max_slot { + let mut current_slot = Some(0); + while repairs.len() < max_repairs && current_slot.is_some() { + if current_slot.unwrap() > repair_info.max_slot { repair_info.repair_tries = 0; - repair_info.max_slot = current_slot_height.unwrap(); + repair_info.max_slot = current_slot.unwrap(); } - let slot = blocktree.meta(current_slot_height.unwrap())?; + let slot = blocktree.meta(current_slot.unwrap())?; if slot.is_some() { let slot = slot.unwrap(); let new_repairs = Self::process_slot( blocktree, - current_slot_height.unwrap(), + current_slot.unwrap(), &slot, max_repairs - repairs.len(), ); repairs.extend(new_repairs); } - current_slot_height = blocktree.get_next_slot(current_slot_height.unwrap())?; + current_slot = blocktree.get_next_slot(current_slot.unwrap())?; } // Only increment repair_tries if the ledger contains every blob for every slot @@ -308,10 +305,10 @@ mod test { .collect(); let expected: Vec = (0..num_slots) - .flat_map(|slot_height| { + .flat_map(|slot| { missing_indexes_per_slot .iter() - .map(move |blob_index| RepairType::Blob(slot_height as u64, *blob_index)) + .map(move |blob_index| RepairType::Blob(slot as u64, *blob_index)) }) .collect(); diff --git a/core/src/voting_keypair.rs b/core/src/voting_keypair.rs index 0726ea528b..fbc7a894c1 100644 --- a/core/src/voting_keypair.rs +++ b/core/src/voting_keypair.rs @@ -114,9 +114,9 @@ pub mod tests { bank.process_transaction(&tx).unwrap(); } - pub fn push_vote(voting_keypair: &T, bank: &Bank, slot_height: u64) { + pub fn push_vote(voting_keypair: &T, bank: &Bank, slot: u64) { let blockhash = bank.last_blockhash(); - let tx = VoteTransaction::new_vote(voting_keypair, slot_height, blockhash, 0); + let tx = VoteTransaction::new_vote(voting_keypair, slot, blockhash, 0); bank.process_transaction(&tx).unwrap(); } @@ -125,9 +125,9 @@ pub mod tests { voting_keypair: &T, bank: &Bank, num_tokens: u64, - slot_height: u64, + slot: u64, ) { new_vote_account(from_keypair, &voting_keypair.pubkey(), bank, num_tokens); - push_vote(voting_keypair, bank, slot_height); + push_vote(voting_keypair, bank, slot); } } diff --git a/programs/vote_api/src/vote_instruction.rs b/programs/vote_api/src/vote_instruction.rs index fa17f0047b..28a2beebee 100644 --- a/programs/vote_api/src/vote_instruction.rs +++ b/programs/vote_api/src/vote_instruction.rs @@ -6,13 +6,13 @@ use solana_sdk::transaction_builder::BuilderInstruction; #[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Clone)] pub struct Vote { // TODO: add signature of the state here as well - /// A vote for height slot_height - pub slot_height: u64, + /// A vote for height slot + pub slot: u64, } impl Vote { - pub fn new(slot_height: u64) -> Self { - Self { slot_height } + pub fn new(slot: u64) -> Self { + Self { slot } } } diff --git a/programs/vote_api/src/vote_state.rs b/programs/vote_api/src/vote_state.rs index 0bd5e8b530..71347708f1 100644 --- a/programs/vote_api/src/vote_state.rs +++ b/programs/vote_api/src/vote_state.rs @@ -17,14 +17,14 @@ pub const INITIAL_LOCKOUT: usize = 2; #[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Clone)] pub struct Lockout { - pub slot_height: u64, + pub slot: u64, pub confirmation_count: u32, } impl Lockout { pub fn new(vote: &Vote) -> Self { Self { - slot_height: vote.slot_height, + slot: vote.slot, confirmation_count: 1, } } @@ -36,8 +36,8 @@ impl Lockout { // The slot height at which this vote expires (cannot vote for any slot // less than this) - pub fn expiration_slot_height(&self) -> u64 { - self.slot_height + self.lockout() + pub fn expiration_slot(&self) -> u64 { + self.slot + self.lockout() } } @@ -87,7 +87,7 @@ impl VoteState { if self .votes .back() - .map_or(false, |old_vote| old_vote.slot_height >= vote.slot_height) + .map_or(false, |old_vote| old_vote.slot >= vote.slot) { return; } @@ -97,11 +97,11 @@ impl VoteState { // TODO: Integrity checks // Verify the vote's bank hash matches what is expected - self.pop_expired_votes(vote.slot_height); + self.pop_expired_votes(vote.slot); // Once the stack is full, pop the oldest vote and distribute rewards if self.votes.len() == MAX_LOCKOUT_HISTORY { let vote = self.votes.pop_front().unwrap(); - self.root_slot = Some(vote.slot_height); + self.root_slot = Some(vote.slot); self.credits += 1; } self.votes.push_back(vote); @@ -119,12 +119,12 @@ impl VoteState { self.credits = 0; } - fn pop_expired_votes(&mut self, slot_height: u64) { + fn pop_expired_votes(&mut self, slot: u64) { loop { if self .votes .back() - .map_or(false, |v| v.expiration_slot_height() < slot_height) + .map_or(false, |v| v.expiration_slot() < slot) { self.votes.pop_back(); } else { @@ -357,14 +357,14 @@ mod tests { // One more vote that confirms the entire stack, // the root_slot should change to the // second vote - let top_vote = vote_state.votes.front().unwrap().slot_height; + let top_vote = vote_state.votes.front().unwrap().slot; vote_state.process_vote(Vote::new( - vote_state.votes.back().unwrap().expiration_slot_height(), + vote_state.votes.back().unwrap().expiration_slot(), )); assert_eq!(Some(top_vote), vote_state.root_slot); // Expire everything except the first vote - let vote = Vote::new(vote_state.votes.front().unwrap().expiration_slot_height()); + let vote = Vote::new(vote_state.votes.front().unwrap().expiration_slot()); vote_state.process_vote(vote); // First vote and new vote are both stored for a total of 2 votes assert_eq!(vote_state.votes.len(), 2); diff --git a/programs/vote_api/src/vote_transaction.rs b/programs/vote_api/src/vote_transaction.rs index 3346655d19..bbfa24a197 100644 --- a/programs/vote_api/src/vote_transaction.rs +++ b/programs/vote_api/src/vote_transaction.rs @@ -17,11 +17,11 @@ pub struct VoteTransaction {} impl VoteTransaction { pub fn new_vote( voting_keypair: &T, - slot_height: u64, + slot: u64, recent_blockhash: Hash, fee: u64, ) -> Transaction { - let vote = Vote { slot_height }; + let vote = Vote { slot }; TransactionBuilder::new(fee) .push(VoteInstruction::new_vote(voting_keypair.pubkey(), vote)) .sign(&[voting_keypair], recent_blockhash) @@ -94,12 +94,12 @@ mod tests { #[test] fn test_get_votes() { let keypair = Keypair::new(); - let slot_height = 1; + let slot = 1; let recent_blockhash = Hash::default(); - let transaction = VoteTransaction::new_vote(&keypair, slot_height, recent_blockhash, 0); + let transaction = VoteTransaction::new_vote(&keypair, slot, recent_blockhash, 0); assert_eq!( VoteTransaction::get_votes(&transaction), - vec![(keypair.pubkey(), Vote::new(slot_height), recent_blockhash)] + vec![(keypair.pubkey(), Vote::new(slot), recent_blockhash)] ); } } diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 3cc796f34e..24fc828312 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -342,7 +342,7 @@ impl Bank { // Sort by slot height slots_and_stakes.sort_by(|a, b| a.0.cmp(&b.0)); - let max_slot = self.slot_height(); + let max_slot = self.slot(); let min_slot = max_slot.saturating_sub(MAX_RECENT_BLOCKHASHES as u64); let mut total_stake = 0; @@ -757,7 +757,7 @@ impl Bank { self.stakers_slot_offset } - /// Return the number of ticks per slot that should be used calls to slot_height(). + /// Return the number of ticks per slot pub fn ticks_per_slot(&self) -> u64 { self.ticks_per_slot } @@ -776,11 +776,6 @@ impl Bank { self.tick_height() % self.ticks_per_slot() } - /// Return the slot_height of the last registered tick. - pub fn slot_height(&self) -> u64 { - self.tick_height() / self.ticks_per_slot() - } - /// Return the number of slots per tick. pub fn slots_per_epoch(&self) -> u64 { self.slots_per_epoch @@ -804,20 +799,22 @@ impl Bank { /// Return the number of slots since the last epoch boundary. pub fn slot_index(&self) -> u64 { - self.slot_height() % self.slots_per_epoch() + self.slot() % self.slots_per_epoch() } /// Return the epoch height of the last registered tick. pub fn epoch_height(&self) -> u64 { - self.slot_height() / self.slots_per_epoch() + self.slot() / self.slots_per_epoch() } } #[cfg(test)] mod tests { use super::*; + use bincode::serialize; use hashbrown::HashSet; - use solana_sdk::genesis_block::BOOTSTRAP_LEADER_TOKENS; + use solana_sdk::genesis_block::{GenesisBlock, BOOTSTRAP_LEADER_TOKENS}; + use solana_sdk::hash::hash; use solana_sdk::native_program::ProgramError; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_instruction::SystemInstruction; @@ -1163,9 +1160,20 @@ mod tests { } // Register n ticks and return the tick, slot and epoch indexes. - fn register_ticks(bank: &Bank, n: u64) -> (u64, u64, u64) { + fn register_ticks(bank: &mut Arc, tick_hash: &mut Hash, n: u64) -> (u64, u64, u64) { + let mut max_tick_height = (bank.slot() + 1) * bank.ticks_per_slot() - 1; for _ in 0..n { - bank.register_tick(&Hash::default()); + if bank.tick_height() == max_tick_height { + *bank = Arc::new(Bank::new_from_parent( + &bank, + Pubkey::default(), + bank.slot() + 1, + )); + max_tick_height = (bank.slot() + 1) * bank.ticks_per_slot() - 1; + } + + *tick_hash = hash(&serialize(tick_hash).unwrap()); + bank.register_tick(&tick_hash); } (bank.tick_index(), bank.slot_index(), bank.epoch_height()) } @@ -1173,25 +1181,29 @@ mod tests { #[test] fn test_tick_slot_epoch_indexes() { let (genesis_block, _) = GenesisBlock::new(5); - let bank = Bank::new(&genesis_block); + let mut tick_hash = genesis_block.hash(); + let mut bank = Arc::new(Bank::new(&genesis_block)); let ticks_per_slot = bank.ticks_per_slot(); let slots_per_epoch = bank.slots_per_epoch(); let ticks_per_epoch = ticks_per_slot * slots_per_epoch; // All indexes are zero-based. - assert_eq!(register_ticks(&bank, 0), (0, 0, 0)); + assert_eq!(register_ticks(&mut bank, &mut tick_hash, 0), (0, 0, 0)); // Slot index remains zero through the last tick. assert_eq!( - register_ticks(&bank, ticks_per_slot - 1), + register_ticks(&mut bank, &mut tick_hash, ticks_per_slot - 1), (ticks_per_slot - 1, 0, 0) ); // Cross a slot boundary. - assert_eq!(register_ticks(&bank, 1), (0, 1, 0)); + assert_eq!(register_ticks(&mut bank, &mut tick_hash, 1), (0, 1, 0)); // Cross an epoch boundary. - assert_eq!(register_ticks(&bank, ticks_per_epoch), (0, 1, 1)); + assert_eq!( + register_ticks(&mut bank, &mut tick_hash, ticks_per_epoch), + (0, 1, 1) + ); } #[test]