uses Option<Slot> for SlotMeta.parent_slot (#21808)
SlotMeta.parent_slot for the head of a detached chain of slots is unknown and that is indicated by u64::MAX which lacks type-safety: https://github.com/solana-labs/solana/blob/6c108c8fc/ledger/src/blockstore_meta.rs#L203-L205 The commit changes the type to Option<Slot>. Backward compatibility is maintained by customizing serde serialize/deserialize implementations.
This commit is contained in:
parent
d13a5056f1
commit
8d980f07ba
|
@ -86,17 +86,17 @@ fn get_unrepaired_path(
|
||||||
) -> Vec<Slot> {
|
) -> Vec<Slot> {
|
||||||
let mut path = Vec::new();
|
let mut path = Vec::new();
|
||||||
let mut slot = start_slot;
|
let mut slot = start_slot;
|
||||||
while !visited.contains(&slot) {
|
while visited.insert(slot) {
|
||||||
visited.insert(slot);
|
|
||||||
let slot_meta = slot_meta_cache
|
let slot_meta = slot_meta_cache
|
||||||
.entry(slot)
|
.entry(slot)
|
||||||
.or_insert_with(|| blockstore.meta(slot).unwrap());
|
.or_insert_with(|| blockstore.meta(slot).unwrap());
|
||||||
if let Some(slot_meta) = slot_meta {
|
if let Some(slot_meta) = slot_meta {
|
||||||
if slot_meta.is_full() {
|
if !slot_meta.is_full() {
|
||||||
break;
|
|
||||||
}
|
|
||||||
path.push(slot);
|
path.push(slot);
|
||||||
slot = slot_meta.parent_slot;
|
if let Some(parent_slot) = slot_meta.parent_slot {
|
||||||
|
slot = parent_slot
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
path.reverse();
|
path.reverse();
|
||||||
|
|
|
@ -706,8 +706,8 @@ impl ServeRepair {
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if meta.is_parent_set() && res.packets.len() <= max_responses {
|
if meta.parent_slot.is_some() && res.packets.len() <= max_responses {
|
||||||
slot = meta.parent_slot;
|
slot = meta.parent_slot.unwrap();
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,7 +201,7 @@ fn output_slot(
|
||||||
println!(" Slot Meta {:?} is_full: {}", meta, is_full);
|
println!(" Slot Meta {:?} is_full: {}", meta, is_full);
|
||||||
} else {
|
} else {
|
||||||
println!(
|
println!(
|
||||||
" num_shreds: {}, parent_slot: {}, num_entries: {}, is_full: {}",
|
" num_shreds: {}, parent_slot: {:?}, num_entries: {}, is_full: {}",
|
||||||
num_shreds,
|
num_shreds,
|
||||||
meta.parent_slot,
|
meta.parent_slot,
|
||||||
entries.len(),
|
entries.len(),
|
||||||
|
|
|
@ -11,8 +11,8 @@ pub struct AncestorIterator<'a> {
|
||||||
impl<'a> AncestorIterator<'a> {
|
impl<'a> AncestorIterator<'a> {
|
||||||
pub fn new(start_slot: Slot, blockstore: &'a Blockstore) -> Self {
|
pub fn new(start_slot: Slot, blockstore: &'a Blockstore) -> Self {
|
||||||
let current = blockstore.meta(start_slot).unwrap().and_then(|slot_meta| {
|
let current = blockstore.meta(start_slot).unwrap().and_then(|slot_meta| {
|
||||||
if slot_meta.is_parent_set() && start_slot != 0 {
|
if start_slot != 0 {
|
||||||
Some(slot_meta.parent_slot)
|
slot_meta.parent_slot
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -37,13 +37,11 @@ impl<'a> Iterator for AncestorIterator<'a> {
|
||||||
let current = self.current;
|
let current = self.current;
|
||||||
current.map(|slot| {
|
current.map(|slot| {
|
||||||
if slot != 0 {
|
if slot != 0 {
|
||||||
self.current = self.blockstore.meta(slot).unwrap().and_then(|slot_meta| {
|
self.current = self
|
||||||
if slot_meta.is_parent_set() {
|
.blockstore
|
||||||
Some(slot_meta.parent_slot)
|
.meta(slot)
|
||||||
} else {
|
.unwrap()
|
||||||
None
|
.and_then(|slot_meta| slot_meta.parent_slot);
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
self.current = None;
|
self.current = None;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1414,7 +1414,12 @@ impl Blockstore {
|
||||||
}
|
}
|
||||||
|
|
||||||
let last_root = *last_root.read().unwrap();
|
let last_root = *last_root.read().unwrap();
|
||||||
verify_shred_slots(slot, slot_meta.parent_slot, last_root)
|
// TODO Shouldn't this use shred.parent() instead and update
|
||||||
|
// slot_meta.parent_slot accordingly?
|
||||||
|
slot_meta
|
||||||
|
.parent_slot
|
||||||
|
.map(|parent_slot| verify_shred_slots(slot, parent_slot, last_root))
|
||||||
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_data_shred(
|
fn insert_data_shred(
|
||||||
|
@ -1873,8 +1878,12 @@ impl Blockstore {
|
||||||
}
|
}
|
||||||
transaction
|
transaction
|
||||||
});
|
});
|
||||||
let parent_slot_entries = self
|
let parent_slot_entries = slot_meta
|
||||||
.get_slot_entries(slot_meta.parent_slot, 0)
|
.parent_slot
|
||||||
|
.and_then(|parent_slot| {
|
||||||
|
self.get_slot_entries(parent_slot, /*shred_start_index:*/ 0)
|
||||||
|
.ok()
|
||||||
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
if parent_slot_entries.is_empty() && require_previous_blockhash {
|
if parent_slot_entries.is_empty() && require_previous_blockhash {
|
||||||
return Err(BlockstoreError::ParentEntriesUnavailable);
|
return Err(BlockstoreError::ParentEntriesUnavailable);
|
||||||
|
@ -1900,7 +1909,9 @@ impl Blockstore {
|
||||||
let block = ConfirmedBlock {
|
let block = ConfirmedBlock {
|
||||||
previous_blockhash: previous_blockhash.to_string(),
|
previous_blockhash: previous_blockhash.to_string(),
|
||||||
blockhash: blockhash.to_string(),
|
blockhash: blockhash.to_string(),
|
||||||
parent_slot: slot_meta.parent_slot,
|
// If the slot is full it should have parent_slot populated
|
||||||
|
// from shreds received.
|
||||||
|
parent_slot: slot_meta.parent_slot.unwrap(),
|
||||||
transactions: self
|
transactions: self
|
||||||
.map_transactions_to_statuses(slot, slot_transaction_iterator)?,
|
.map_transactions_to_statuses(slot, slot_transaction_iterator)?,
|
||||||
rewards,
|
rewards,
|
||||||
|
@ -3226,18 +3237,18 @@ fn get_slot_meta_entry<'a>(
|
||||||
// Store a 2-tuple of the metadata (working copy, backup copy)
|
// Store a 2-tuple of the metadata (working copy, backup copy)
|
||||||
if let Some(mut meta) = meta_cf.get(slot).expect("Expect database get to succeed") {
|
if let Some(mut meta) = meta_cf.get(slot).expect("Expect database get to succeed") {
|
||||||
let backup = Some(meta.clone());
|
let backup = Some(meta.clone());
|
||||||
// If parent_slot == std::u64::MAX, then this is one of the orphans inserted
|
// If parent_slot == None, then this is one of the orphans inserted
|
||||||
// during the chaining process, see the function find_slot_meta_in_cached_state()
|
// during the chaining process, see the function find_slot_meta_in_cached_state()
|
||||||
// for details. Slots that are orphans are missing a parent_slot, so we should
|
// for details. Slots that are orphans are missing a parent_slot, so we should
|
||||||
// fill in the parent now that we know it.
|
// fill in the parent now that we know it.
|
||||||
if is_orphan(&meta) {
|
if is_orphan(&meta) {
|
||||||
meta.parent_slot = parent_slot;
|
meta.parent_slot = Some(parent_slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
SlotMetaWorkingSetEntry::new(Rc::new(RefCell::new(meta)), backup)
|
SlotMetaWorkingSetEntry::new(Rc::new(RefCell::new(meta)), backup)
|
||||||
} else {
|
} else {
|
||||||
SlotMetaWorkingSetEntry::new(
|
SlotMetaWorkingSetEntry::new(
|
||||||
Rc::new(RefCell::new(SlotMeta::new(slot, parent_slot))),
|
Rc::new(RefCell::new(SlotMeta::new(slot, Some(parent_slot)))),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -3408,8 +3419,8 @@ fn handle_chaining_for_slot(
|
||||||
// 1) This is a new slot
|
// 1) This is a new slot
|
||||||
// 2) slot != 0
|
// 2) slot != 0
|
||||||
// then try to chain this slot to a previous slot
|
// then try to chain this slot to a previous slot
|
||||||
if slot != 0 {
|
if slot != 0 && meta_mut.parent_slot.is_some() {
|
||||||
let prev_slot = meta_mut.parent_slot;
|
let prev_slot = meta_mut.parent_slot.unwrap();
|
||||||
|
|
||||||
// Check if the slot represented by meta_mut is either a new slot or a orphan.
|
// Check if the slot represented by meta_mut is either a new slot or a orphan.
|
||||||
// In both cases we need to run the chaining logic b/c the parent on the slot was
|
// In both cases we need to run the chaining logic b/c the parent on the slot was
|
||||||
|
@ -3503,7 +3514,7 @@ where
|
||||||
fn is_orphan(meta: &SlotMeta) -> bool {
|
fn is_orphan(meta: &SlotMeta) -> bool {
|
||||||
// If we have no parent, then this is the head of a detached chain of
|
// If we have no parent, then this is the head of a detached chain of
|
||||||
// slots
|
// slots
|
||||||
!meta.is_parent_set()
|
meta.parent_slot.is_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1) Chain current_slot to the previous slot defined by prev_slot_meta
|
// 1) Chain current_slot to the previous slot defined by prev_slot_meta
|
||||||
|
@ -4038,9 +4049,9 @@ pub mod tests {
|
||||||
assert_eq!(meta.next_slots, vec![i + 1]);
|
assert_eq!(meta.next_slots, vec![i + 1]);
|
||||||
}
|
}
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
assert_eq!(meta.parent_slot, 0);
|
assert_eq!(meta.parent_slot, Some(0));
|
||||||
} else {
|
} else {
|
||||||
assert_eq!(meta.parent_slot, i - 1);
|
assert_eq!(meta.parent_slot, Some(i - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -4098,7 +4109,7 @@ pub mod tests {
|
||||||
let blockstore = Blockstore::open(ledger_path.path()).unwrap();
|
let blockstore = Blockstore::open(ledger_path.path()).unwrap();
|
||||||
|
|
||||||
// Test meta column family
|
// Test meta column family
|
||||||
let meta = SlotMeta::new(0, 1);
|
let meta = SlotMeta::new(0, Some(1));
|
||||||
blockstore.meta_cf.put(0, &meta).unwrap();
|
blockstore.meta_cf.put(0, &meta).unwrap();
|
||||||
let result = blockstore
|
let result = blockstore
|
||||||
.meta_cf
|
.meta_cf
|
||||||
|
@ -4255,7 +4266,7 @@ pub mod tests {
|
||||||
.expect("Expected new metadata object to exist");
|
.expect("Expected new metadata object to exist");
|
||||||
assert_eq!(meta.consumed, num_shreds);
|
assert_eq!(meta.consumed, num_shreds);
|
||||||
assert_eq!(meta.received, num_shreds);
|
assert_eq!(meta.received, num_shreds);
|
||||||
assert_eq!(meta.parent_slot, 0);
|
assert_eq!(meta.parent_slot, Some(0));
|
||||||
assert_eq!(meta.last_index, Some(num_shreds - 1));
|
assert_eq!(meta.last_index, Some(num_shreds - 1));
|
||||||
assert!(meta.next_slots.is_empty());
|
assert!(meta.next_slots.is_empty());
|
||||||
assert!(meta.is_connected);
|
assert!(meta.is_connected);
|
||||||
|
@ -4286,7 +4297,7 @@ pub mod tests {
|
||||||
assert_eq!(result.len(), 0);
|
assert_eq!(result.len(), 0);
|
||||||
assert!(meta.consumed == 0 && meta.received == num_shreds as u64);
|
assert!(meta.consumed == 0 && meta.received == num_shreds as u64);
|
||||||
} else {
|
} else {
|
||||||
assert_eq!(meta.parent_slot, 0);
|
assert_eq!(meta.parent_slot, Some(0));
|
||||||
assert_eq!(result, entries);
|
assert_eq!(result, entries);
|
||||||
assert!(meta.consumed == num_shreds as u64 && meta.received == num_shreds as u64);
|
assert!(meta.consumed == num_shreds as u64 && meta.received == num_shreds as u64);
|
||||||
}
|
}
|
||||||
|
@ -4474,7 +4485,7 @@ pub mod tests {
|
||||||
let meta = blockstore.meta(slot).unwrap().unwrap();
|
let meta = blockstore.meta(slot).unwrap().unwrap();
|
||||||
assert_eq!(meta.received, num_shreds);
|
assert_eq!(meta.received, num_shreds);
|
||||||
assert_eq!(meta.consumed, num_shreds);
|
assert_eq!(meta.consumed, num_shreds);
|
||||||
assert_eq!(meta.parent_slot, parent_slot);
|
assert_eq!(meta.parent_slot, Some(parent_slot));
|
||||||
assert_eq!(meta.last_index, Some(num_shreds - 1));
|
assert_eq!(meta.last_index, Some(num_shreds - 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4728,7 +4739,7 @@ pub mod tests {
|
||||||
assert!(s1.next_slots.is_empty());
|
assert!(s1.next_slots.is_empty());
|
||||||
// Slot 1 is not trunk because slot 0 hasn't been inserted yet
|
// Slot 1 is not trunk because slot 0 hasn't been inserted yet
|
||||||
assert!(!s1.is_connected);
|
assert!(!s1.is_connected);
|
||||||
assert_eq!(s1.parent_slot, 0);
|
assert_eq!(s1.parent_slot, Some(0));
|
||||||
assert_eq!(s1.last_index, Some(shreds_per_slot as u64 - 1));
|
assert_eq!(s1.last_index, Some(shreds_per_slot as u64 - 1));
|
||||||
|
|
||||||
// 2) Write to the second slot
|
// 2) Write to the second slot
|
||||||
|
@ -4740,7 +4751,7 @@ pub mod tests {
|
||||||
assert!(s2.next_slots.is_empty());
|
assert!(s2.next_slots.is_empty());
|
||||||
// Slot 2 is not trunk because slot 0 hasn't been inserted yet
|
// Slot 2 is not trunk because slot 0 hasn't been inserted yet
|
||||||
assert!(!s2.is_connected);
|
assert!(!s2.is_connected);
|
||||||
assert_eq!(s2.parent_slot, 1);
|
assert_eq!(s2.parent_slot, Some(1));
|
||||||
assert_eq!(s2.last_index, Some(shreds_per_slot as u64 - 1));
|
assert_eq!(s2.last_index, Some(shreds_per_slot as u64 - 1));
|
||||||
|
|
||||||
// Check the first slot again, it should chain to the second slot,
|
// Check the first slot again, it should chain to the second slot,
|
||||||
|
@ -4748,7 +4759,7 @@ pub mod tests {
|
||||||
let s1 = blockstore.meta(1).unwrap().unwrap();
|
let s1 = blockstore.meta(1).unwrap().unwrap();
|
||||||
assert_eq!(s1.next_slots, vec![2]);
|
assert_eq!(s1.next_slots, vec![2]);
|
||||||
assert!(!s1.is_connected);
|
assert!(!s1.is_connected);
|
||||||
assert_eq!(s1.parent_slot, 0);
|
assert_eq!(s1.parent_slot, Some(0));
|
||||||
assert_eq!(s1.last_index, Some(shreds_per_slot as u64 - 1));
|
assert_eq!(s1.last_index, Some(shreds_per_slot as u64 - 1));
|
||||||
|
|
||||||
// 3) Write to the zeroth slot, check that every slot
|
// 3) Write to the zeroth slot, check that every slot
|
||||||
|
@ -4761,9 +4772,9 @@ pub mod tests {
|
||||||
assert_eq!(s.next_slots, vec![i + 1]);
|
assert_eq!(s.next_slots, vec![i + 1]);
|
||||||
}
|
}
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
assert_eq!(s.parent_slot, 0);
|
assert_eq!(s.parent_slot, Some(0));
|
||||||
} else {
|
} else {
|
||||||
assert_eq!(s.parent_slot, i - 1);
|
assert_eq!(s.parent_slot, Some(i - 1));
|
||||||
}
|
}
|
||||||
assert_eq!(s.last_index, Some(shreds_per_slot as u64 - 1));
|
assert_eq!(s.last_index, Some(shreds_per_slot as u64 - 1));
|
||||||
assert!(s.is_connected);
|
assert!(s.is_connected);
|
||||||
|
@ -4813,10 +4824,10 @@ pub mod tests {
|
||||||
let s = blockstore.meta(i as u64).unwrap().unwrap();
|
let s = blockstore.meta(i as u64).unwrap().unwrap();
|
||||||
if i % 2 == 0 {
|
if i % 2 == 0 {
|
||||||
assert_eq!(s.next_slots, vec![i as u64 + 1]);
|
assert_eq!(s.next_slots, vec![i as u64 + 1]);
|
||||||
assert_eq!(s.parent_slot, std::u64::MAX);
|
assert_eq!(s.parent_slot, None);
|
||||||
} else {
|
} else {
|
||||||
assert!(s.next_slots.is_empty());
|
assert!(s.next_slots.is_empty());
|
||||||
assert_eq!(s.parent_slot, i - 1);
|
assert_eq!(s.parent_slot, Some(i - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
|
@ -4842,9 +4853,9 @@ pub mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
assert_eq!(s.parent_slot, 0);
|
assert_eq!(s.parent_slot, Some(0));
|
||||||
} else {
|
} else {
|
||||||
assert_eq!(s.parent_slot, i - 1);
|
assert_eq!(s.parent_slot, Some(i - 1));
|
||||||
}
|
}
|
||||||
assert_eq!(s.last_index, Some(shreds_per_slot as u64 - 1));
|
assert_eq!(s.last_index, Some(shreds_per_slot as u64 - 1));
|
||||||
assert!(s.is_connected);
|
assert!(s.is_connected);
|
||||||
|
@ -4890,9 +4901,9 @@ pub mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
assert_eq!(s.parent_slot, 0);
|
assert_eq!(s.parent_slot, Some(0));
|
||||||
} else {
|
} else {
|
||||||
assert_eq!(s.parent_slot, i - 1);
|
assert_eq!(s.parent_slot, Some(i - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(s.last_index, Some(shreds_per_slot as u64 - 1));
|
assert_eq!(s.last_index, Some(shreds_per_slot as u64 - 1));
|
||||||
|
@ -4926,9 +4937,9 @@ pub mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
assert_eq!(s.parent_slot, 0);
|
assert_eq!(s.parent_slot, Some(0));
|
||||||
} else {
|
} else {
|
||||||
assert_eq!(s.parent_slot, i - 1);
|
assert_eq!(s.parent_slot, Some(i - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(s.last_index, Some(shreds_per_slot as u64 - 1));
|
assert_eq!(s.last_index, Some(shreds_per_slot as u64 - 1));
|
||||||
|
@ -5010,7 +5021,7 @@ pub mod tests {
|
||||||
(slot - 1) / branching_factor
|
(slot - 1) / branching_factor
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
assert_eq!(slot_meta.parent_slot, slot_parent);
|
assert_eq!(slot_meta.parent_slot, Some(slot_parent));
|
||||||
|
|
||||||
let expected_children: HashSet<_> = {
|
let expected_children: HashSet<_> = {
|
||||||
if slot >= last_level {
|
if slot >= last_level {
|
||||||
|
@ -5044,7 +5055,7 @@ pub mod tests {
|
||||||
// Slot doesn't exist
|
// Slot doesn't exist
|
||||||
assert!(blockstore.get_slots_since(&[0]).unwrap().is_empty());
|
assert!(blockstore.get_slots_since(&[0]).unwrap().is_empty());
|
||||||
|
|
||||||
let mut meta0 = SlotMeta::new(0, 0);
|
let mut meta0 = SlotMeta::new(0, Some(0));
|
||||||
blockstore.meta_cf.put(0, &meta0).unwrap();
|
blockstore.meta_cf.put(0, &meta0).unwrap();
|
||||||
|
|
||||||
// Slot exists, chains to nothing
|
// Slot exists, chains to nothing
|
||||||
|
@ -5058,7 +5069,7 @@ pub mod tests {
|
||||||
assert_eq!(blockstore.get_slots_since(&[0]).unwrap(), expected);
|
assert_eq!(blockstore.get_slots_since(&[0]).unwrap(), expected);
|
||||||
assert_eq!(blockstore.get_slots_since(&[0, 1]).unwrap(), expected);
|
assert_eq!(blockstore.get_slots_since(&[0, 1]).unwrap(), expected);
|
||||||
|
|
||||||
let mut meta3 = SlotMeta::new(3, 1);
|
let mut meta3 = SlotMeta::new(3, Some(1));
|
||||||
meta3.next_slots = vec![10, 5];
|
meta3.next_slots = vec![10, 5];
|
||||||
blockstore.meta_cf.put(3, &meta3).unwrap();
|
blockstore.meta_cf.put(3, &meta3).unwrap();
|
||||||
let expected: HashMap<u64, Vec<u64>> = vec![(0, vec![1, 2]), (3, vec![10, 5])]
|
let expected: HashMap<u64, Vec<u64>> = vec![(0, vec![1, 2]), (3, vec![10, 5])]
|
||||||
|
@ -5187,10 +5198,10 @@ pub mod tests {
|
||||||
assert_eq!(meta.received, 1);
|
assert_eq!(meta.received, 1);
|
||||||
assert_eq!(meta.last_index, Some(0));
|
assert_eq!(meta.last_index, Some(0));
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
assert_eq!(meta.parent_slot, i - 1);
|
assert_eq!(meta.parent_slot, Some(i - 1));
|
||||||
assert_eq!(meta.consumed, 1);
|
assert_eq!(meta.consumed, 1);
|
||||||
} else {
|
} else {
|
||||||
assert_eq!(meta.parent_slot, 0);
|
assert_eq!(meta.parent_slot, Some(0));
|
||||||
assert_eq!(meta.consumed, num_shreds_per_slot);
|
assert_eq!(meta.consumed, num_shreds_per_slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6016,10 +6027,7 @@ pub mod tests {
|
||||||
.set_roots(vec![slot - 1, slot, slot + 1].iter())
|
.set_roots(vec![slot - 1, slot, slot + 1].iter())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let parent_meta = SlotMeta {
|
let parent_meta = SlotMeta::default();
|
||||||
parent_slot: std::u64::MAX,
|
|
||||||
..SlotMeta::default()
|
|
||||||
};
|
|
||||||
blockstore
|
blockstore
|
||||||
.put_meta_bytes(slot - 1, &serialize(&parent_meta).unwrap())
|
.put_meta_bytes(slot - 1, &serialize(&parent_meta).unwrap())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -6554,13 +6562,13 @@ pub mod tests {
|
||||||
// 2 (root)
|
// 2 (root)
|
||||||
// |
|
// |
|
||||||
// 3
|
// 3
|
||||||
let meta0 = SlotMeta::new(0, 0);
|
let meta0 = SlotMeta::new(0, Some(0));
|
||||||
blockstore.meta_cf.put(0, &meta0).unwrap();
|
blockstore.meta_cf.put(0, &meta0).unwrap();
|
||||||
let meta1 = SlotMeta::new(1, 0);
|
let meta1 = SlotMeta::new(1, Some(0));
|
||||||
blockstore.meta_cf.put(1, &meta1).unwrap();
|
blockstore.meta_cf.put(1, &meta1).unwrap();
|
||||||
let meta2 = SlotMeta::new(2, 0);
|
let meta2 = SlotMeta::new(2, Some(0));
|
||||||
blockstore.meta_cf.put(2, &meta2).unwrap();
|
blockstore.meta_cf.put(2, &meta2).unwrap();
|
||||||
let meta3 = SlotMeta::new(3, 2);
|
let meta3 = SlotMeta::new(3, Some(2));
|
||||||
blockstore.meta_cf.put(3, &meta3).unwrap();
|
blockstore.meta_cf.put(3, &meta3).unwrap();
|
||||||
|
|
||||||
blockstore.set_roots(vec![0, 2].iter()).unwrap();
|
blockstore.set_roots(vec![0, 2].iter()).unwrap();
|
||||||
|
@ -6737,13 +6745,13 @@ pub mod tests {
|
||||||
let signature2 = Signature::new(&[3u8; 64]);
|
let signature2 = Signature::new(&[3u8; 64]);
|
||||||
|
|
||||||
// Insert rooted slots 0..=3 with no fork
|
// Insert rooted slots 0..=3 with no fork
|
||||||
let meta0 = SlotMeta::new(0, 0);
|
let meta0 = SlotMeta::new(0, Some(0));
|
||||||
blockstore.meta_cf.put(0, &meta0).unwrap();
|
blockstore.meta_cf.put(0, &meta0).unwrap();
|
||||||
let meta1 = SlotMeta::new(1, 0);
|
let meta1 = SlotMeta::new(1, Some(0));
|
||||||
blockstore.meta_cf.put(1, &meta1).unwrap();
|
blockstore.meta_cf.put(1, &meta1).unwrap();
|
||||||
let meta2 = SlotMeta::new(2, 1);
|
let meta2 = SlotMeta::new(2, Some(1));
|
||||||
blockstore.meta_cf.put(2, &meta2).unwrap();
|
blockstore.meta_cf.put(2, &meta2).unwrap();
|
||||||
let meta3 = SlotMeta::new(3, 2);
|
let meta3 = SlotMeta::new(3, Some(2));
|
||||||
blockstore.meta_cf.put(3, &meta3).unwrap();
|
blockstore.meta_cf.put(3, &meta3).unwrap();
|
||||||
|
|
||||||
blockstore.set_roots(vec![0, 1, 2, 3].iter()).unwrap();
|
blockstore.set_roots(vec![0, 1, 2, 3].iter()).unwrap();
|
||||||
|
@ -8449,7 +8457,7 @@ pub mod tests {
|
||||||
assert_eq!(blockstore.get_slot_entries(0, 0).unwrap(), vec![]);
|
assert_eq!(blockstore.get_slot_entries(0, 0).unwrap(), vec![]);
|
||||||
assert_eq!(meta.consumed, 0);
|
assert_eq!(meta.consumed, 0);
|
||||||
assert_eq!(meta.received, last_index + 1);
|
assert_eq!(meta.received, last_index + 1);
|
||||||
assert_eq!(meta.parent_slot, 0);
|
assert_eq!(meta.parent_slot, Some(0));
|
||||||
assert_eq!(meta.last_index, Some(last_index));
|
assert_eq!(meta.last_index, Some(last_index));
|
||||||
assert!(!blockstore.is_full(0));
|
assert!(!blockstore.is_full(0));
|
||||||
}
|
}
|
||||||
|
@ -8465,7 +8473,7 @@ pub mod tests {
|
||||||
let meta = blockstore.meta(0).unwrap().unwrap();
|
let meta = blockstore.meta(0).unwrap().unwrap();
|
||||||
assert_eq!(meta.consumed, num_shreds);
|
assert_eq!(meta.consumed, num_shreds);
|
||||||
assert_eq!(meta.received, num_shreds);
|
assert_eq!(meta.received, num_shreds);
|
||||||
assert_eq!(meta.parent_slot, 0);
|
assert_eq!(meta.parent_slot, Some(0));
|
||||||
assert_eq!(meta.last_index, Some(num_shreds - 1));
|
assert_eq!(meta.last_index, Some(num_shreds - 1));
|
||||||
assert!(blockstore.is_full(0));
|
assert!(blockstore.is_full(0));
|
||||||
assert!(!blockstore.is_dead(0));
|
assert!(!blockstore.is_dead(0));
|
||||||
|
|
|
@ -27,11 +27,13 @@ pub struct SlotMeta {
|
||||||
// The timestamp of the first time a shred was added for this slot
|
// The timestamp of the first time a shred was added for this slot
|
||||||
pub first_shred_timestamp: u64,
|
pub first_shred_timestamp: u64,
|
||||||
// The index of the shred that is flagged as the last shred for this slot.
|
// The index of the shred that is flagged as the last shred for this slot.
|
||||||
|
// None until the shred with LAST_SHRED_IN_SLOT flag is received.
|
||||||
#[serde(with = "serde_compat")]
|
#[serde(with = "serde_compat")]
|
||||||
pub last_index: Option<u64>,
|
pub last_index: Option<u64>,
|
||||||
// The slot height of the block this one derives from.
|
// The slot height of the block this one derives from.
|
||||||
// TODO use Option<Slot> instead.
|
// The parent slot of the head of a detached chain of slots is None.
|
||||||
pub parent_slot: Slot,
|
#[serde(with = "serde_compat")]
|
||||||
|
pub parent_slot: Option<Slot>,
|
||||||
// The list of slots, each of which contains a block that derives
|
// The list of slots, each of which contains a block that derives
|
||||||
// from this one.
|
// from this one.
|
||||||
pub next_slots: Vec<Slot>,
|
pub next_slots: Vec<Slot>,
|
||||||
|
@ -217,17 +219,13 @@ impl SlotMeta {
|
||||||
Some(self.consumed) == self.last_index.map(|ix| ix + 1)
|
Some(self.consumed) == self.last_index.map(|ix| ix + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_parent_set(&self) -> bool {
|
|
||||||
self.parent_slot != std::u64::MAX
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear_unconfirmed_slot(&mut self) {
|
pub fn clear_unconfirmed_slot(&mut self) {
|
||||||
let mut new_self = SlotMeta::new_orphan(self.slot);
|
let mut new_self = SlotMeta::new_orphan(self.slot);
|
||||||
std::mem::swap(&mut new_self.next_slots, &mut self.next_slots);
|
std::mem::swap(&mut new_self.next_slots, &mut self.next_slots);
|
||||||
std::mem::swap(self, &mut new_self);
|
std::mem::swap(self, &mut new_self);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn new(slot: Slot, parent_slot: Slot) -> Self {
|
pub(crate) fn new(slot: Slot, parent_slot: Option<Slot>) -> Self {
|
||||||
SlotMeta {
|
SlotMeta {
|
||||||
slot,
|
slot,
|
||||||
parent_slot,
|
parent_slot,
|
||||||
|
@ -237,7 +235,7 @@ impl SlotMeta {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn new_orphan(slot: Slot) -> Self {
|
pub(crate) fn new_orphan(slot: Slot) -> Self {
|
||||||
Self::new(slot, std::u64::MAX)
|
Self::new(slot, /*parent_slot:*/ None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2761,7 +2761,7 @@ fn test_no_voting() {
|
||||||
let meta = ledger.meta(i as u64).unwrap().unwrap();
|
let meta = ledger.meta(i as u64).unwrap().unwrap();
|
||||||
let parent = meta.parent_slot;
|
let parent = meta.parent_slot;
|
||||||
let expected_parent = i.saturating_sub(1);
|
let expected_parent = i.saturating_sub(1);
|
||||||
assert_eq!(parent, expected_parent as u64);
|
assert_eq!(parent, Some(expected_parent as u64));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue