slot_checkpoint_store.rs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2023 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use darkfi_serial::{deserialize, serialize};
  19. use crate::{blockchain::SledDbOverlayPtr, consensus::SlotCheckpoint, Error, Result};
  20. const SLED_SLOT_CHECKPOINT_TREE: &[u8] = b"_slot_checkpoints";
  21. /// The `SlotCheckpointStore` is a `sled` tree storing the checkpoints of the
  22. /// blockchain's slots, where the key is the slot uid, and the value is
  23. /// is the serialized checkpoint.
  24. #[derive(Clone)]
  25. pub struct SlotCheckpointStore(sled::Tree);
  26. impl SlotCheckpointStore {
  27. /// Opens a new or existing `SlotCheckpointStore` on the given sled database.
  28. pub fn new(db: &sled::Db) -> Result<Self> {
  29. let tree = db.open_tree(SLED_SLOT_CHECKPOINT_TREE)?;
  30. let store = Self(tree);
  31. // In case the store is empty, initialize it with the genesis checkpoint.
  32. if store.0.is_empty() {
  33. let genesis_checkpoint = SlotCheckpoint::genesis_slot_checkpoint();
  34. store.insert(&[genesis_checkpoint])?;
  35. }
  36. Ok(store)
  37. }
  38. /// Insert a slice of [`SlotCheckpoint`] into the slotcheckpointstore.
  39. /// With sled, the operation is done as a batch.
  40. /// The block slot is used as the key, while value is the serialized [`SlotCheckpoint`] itself.
  41. pub fn insert(&self, checkpoints: &[SlotCheckpoint]) -> Result<()> {
  42. let mut batch = sled::Batch::default();
  43. for checkpoint in checkpoints {
  44. let serialized = serialize(checkpoint);
  45. batch.insert(&checkpoint.slot.to_be_bytes(), serialized);
  46. }
  47. self.0.apply_batch(batch)?;
  48. Ok(())
  49. }
  50. /// Check if the slotcheckpointstore contains a given slot.
  51. pub fn contains(&self, slot: u64) -> Result<bool> {
  52. Ok(self.0.contains_key(slot.to_be_bytes())?)
  53. }
  54. /// Fetch given slots from the slotcheckpointstore.
  55. /// The resulting vector contains `Option`, which is `Some` if the slot
  56. /// was found in the slotcheckpointstore, and otherwise it is `None`, if it has not.
  57. /// The second parameter is a boolean which tells the function to fail in
  58. /// case at least one slot was not found.
  59. pub fn get(&self, slots: &[u64], strict: bool) -> Result<Vec<Option<SlotCheckpoint>>> {
  60. let mut ret = Vec::with_capacity(slots.len());
  61. for slot in slots {
  62. if let Some(found) = self.0.get(slot.to_be_bytes())? {
  63. let checkpoint = deserialize(&found)?;
  64. ret.push(Some(checkpoint));
  65. } else {
  66. if strict {
  67. return Err(Error::SlotNotFound(*slot))
  68. }
  69. ret.push(None);
  70. }
  71. }
  72. Ok(ret)
  73. }
  74. /// Retrieve all slot checkpointss from the slotcheckpointstore.
  75. /// Be careful as this will try to load everything in memory.
  76. pub fn get_all(&self) -> Result<Vec<SlotCheckpoint>> {
  77. let mut slots = vec![];
  78. for slot in self.0.iter() {
  79. let (_, value) = slot.unwrap();
  80. let checkpoint = deserialize(&value)?;
  81. slots.push(checkpoint);
  82. }
  83. Ok(slots)
  84. }
  85. /// Fetch n slot checkpoints after given slot. In the iteration, if a slot is not
  86. /// found, the iteration stops and the function returns what it has found
  87. /// so far in the `SlotCheckpointStore`.
  88. pub fn get_after(&self, slot: u64, n: u64) -> Result<Vec<SlotCheckpoint>> {
  89. let mut ret = vec![];
  90. let mut key = slot;
  91. let mut counter = 0;
  92. while counter <= n {
  93. if let Some(found) = self.0.get_gt(key.to_be_bytes())? {
  94. let key_bytes: [u8; 8] = found.0.as_ref().try_into().unwrap();
  95. key = u64::from_be_bytes(key_bytes);
  96. let checkpoint = deserialize(&found.1)?;
  97. ret.push(checkpoint);
  98. counter += 1;
  99. continue
  100. }
  101. break
  102. }
  103. Ok(ret)
  104. }
  105. /// Fetch the last slot checkpoint in the tree, based on the `Ord`
  106. /// implementation for `Vec<u8>`. This should not be able to
  107. /// fail because we initialize the store with the genesis slot checkpoint.
  108. pub fn get_last(&self) -> Result<SlotCheckpoint> {
  109. let found = self.0.last()?.unwrap();
  110. let checkpoint = deserialize(&found.1)?;
  111. Ok(checkpoint)
  112. }
  113. /// Retrieve records count
  114. pub fn len(&self) -> usize {
  115. self.0.len()
  116. }
  117. pub fn is_empty(&self) -> bool {
  118. self.0.len() == 0
  119. }
  120. }
  121. /// Overlay structure over a [`SlotCheckpointStore`] instance.
  122. pub struct SlotCheckpointStoreOverlay(SledDbOverlayPtr);
  123. impl SlotCheckpointStoreOverlay {
  124. pub fn new(overlay: SledDbOverlayPtr) -> Result<Self> {
  125. overlay.lock().unwrap().open_tree(SLED_SLOT_CHECKPOINT_TREE)?;
  126. Ok(Self(overlay))
  127. }
  128. /// Fetch given slot from the slotcheckpointstore.
  129. pub fn get(&self, slot: u64) -> Result<Vec<u8>> {
  130. match self.0.lock().unwrap().get(SLED_SLOT_CHECKPOINT_TREE, &slot.to_be_bytes())? {
  131. Some(found) => Ok(found.to_vec()),
  132. None => Err(Error::SlotNotFound(slot)),
  133. }
  134. }
  135. }