mod.rs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  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 std::sync::{Arc, Mutex};
  19. use log::debug;
  20. use sled::Transactional;
  21. use darkfi_sdk::blockchain::Slot;
  22. use darkfi_serial::{deserialize, serialize, Decodable};
  23. use crate::{tx::Transaction, Error, Result};
  24. /// Block related definitions and storage implementations
  25. pub mod block_store;
  26. pub use block_store::{
  27. Block, BlockDifficultyStore, BlockDifficultyStoreOverlay, BlockInfo, BlockOrderStore,
  28. BlockOrderStoreOverlay, BlockStore, BlockStoreOverlay,
  29. };
  30. /// Header definition and storage implementation
  31. pub mod header_store;
  32. pub use header_store::{Header, HeaderStore, HeaderStoreOverlay};
  33. /// Slots storage implementation
  34. pub mod slot_store;
  35. pub use slot_store::{BlocksSlotsStore, BlocksSlotsStoreOverlay, SlotStore, SlotStoreOverlay};
  36. /// Transactions related storage implementations
  37. pub mod tx_store;
  38. pub use tx_store::{PendingTxOrderStore, PendingTxStore, TxStore, TxStoreOverlay};
  39. /// Contracts and Wasm storage implementations
  40. pub mod contract_store;
  41. pub use contract_store::{
  42. ContractStateStore, ContractStateStoreOverlay, WasmStore, WasmStoreOverlay,
  43. };
  44. /// Structure holding all sled trees that define the concept of Blockchain.
  45. #[derive(Clone)]
  46. pub struct Blockchain {
  47. /// Main pointer to the sled db connection
  48. pub sled_db: sled::Db,
  49. /// Headers sled tree
  50. pub headers: HeaderStore,
  51. /// Blocks sled tree
  52. pub blocks: BlockStore,
  53. /// Block order sled tree
  54. pub order: BlockOrderStore,
  55. /// Slot sled tree
  56. pub slots: SlotStore,
  57. /// Blocks Slots sled tree
  58. pub blocks_slots: BlocksSlotsStore,
  59. /// Block height difficulties sled tree,
  60. pub difficulties: BlockDifficultyStore,
  61. /// Transactions sled tree
  62. pub transactions: TxStore,
  63. /// Pending transactions sled tree
  64. pub pending_txs: PendingTxStore,
  65. /// Pending transactions order sled tree
  66. pub pending_txs_order: PendingTxOrderStore,
  67. /// Contract states
  68. pub contracts: ContractStateStore,
  69. /// Wasm bincodes
  70. pub wasm_bincode: WasmStore,
  71. }
  72. impl Blockchain {
  73. /// Instantiate a new `Blockchain` with the given `sled` database.
  74. pub fn new(db: &sled::Db) -> Result<Self> {
  75. let headers = HeaderStore::new(db)?;
  76. let blocks = BlockStore::new(db)?;
  77. let order = BlockOrderStore::new(db)?;
  78. let slots = SlotStore::new(db)?;
  79. let blocks_slots = BlocksSlotsStore::new(db)?;
  80. let difficulties = BlockDifficultyStore::new(db)?;
  81. let transactions = TxStore::new(db)?;
  82. let pending_txs = PendingTxStore::new(db)?;
  83. let pending_txs_order = PendingTxOrderStore::new(db)?;
  84. let contracts = ContractStateStore::new(db)?;
  85. let wasm_bincode = WasmStore::new(db)?;
  86. Ok(Self {
  87. sled_db: db.clone(),
  88. headers,
  89. blocks,
  90. order,
  91. slots,
  92. blocks_slots,
  93. difficulties,
  94. transactions,
  95. pending_txs,
  96. pending_txs_order,
  97. contracts,
  98. wasm_bincode,
  99. })
  100. }
  101. /// Insert a given [`BlockInfo`] into the blockchain database.
  102. /// This functions wraps all the logic of separating the block into specific
  103. /// data that can be fed into the different trees of the database.
  104. /// Upon success, the functions returns the block hash that
  105. /// were given and appended to the ledger.
  106. pub fn add_block(&self, block: &BlockInfo) -> Result<blake3::Hash> {
  107. let mut trees = vec![];
  108. let mut batches = vec![];
  109. // Store transactions
  110. let (txs_batch, _) = self.transactions.insert_batch(&block.txs)?;
  111. trees.push(self.transactions.0.clone());
  112. batches.push(txs_batch);
  113. // Store header
  114. let (headers_batch, _) = self.headers.insert_batch(&[block.header.clone()])?;
  115. trees.push(self.headers.0.clone());
  116. batches.push(headers_batch);
  117. // Store block
  118. let blk: Block = Block::from_block_info(block)?;
  119. let (bocks_batch, block_hashes) = self.blocks.insert_batch(&[blk])?;
  120. let block_hash = block_hashes[0];
  121. let block_hash_vec = [block_hash];
  122. trees.push(self.blocks.0.clone());
  123. batches.push(bocks_batch);
  124. // Store block order
  125. let blocks_order_batch =
  126. self.order.insert_batch(&[block.header.height], &block_hash_vec)?;
  127. trees.push(self.order.0.clone());
  128. batches.push(blocks_order_batch);
  129. // Store block slots uids vector
  130. let slots = block.slots.iter().map(|x| x.id).collect();
  131. let blocks_slots_bactch = self.blocks_slots.insert_batch(&block_hash_vec, &[&slots])?;
  132. trees.push(self.blocks_slots.0.clone());
  133. batches.push(blocks_slots_bactch);
  134. // Store block slots
  135. let slots_batch = self.slots.insert_batch(&block.slots)?;
  136. trees.push(self.slots.0.clone());
  137. batches.push(slots_batch);
  138. // Perform an atomic transaction over the trees and apply the batches.
  139. self.atomic_write(&trees, &batches)?;
  140. Ok(block_hash)
  141. }
  142. /// Check if the given [`BlockInfo`] is in the database and all trees.
  143. pub fn has_block(&self, block: &BlockInfo) -> Result<bool> {
  144. let blockhash = match self.order.get(&[block.header.height], true) {
  145. Ok(v) => v[0].unwrap(),
  146. Err(_) => return Ok(false),
  147. };
  148. // Check if we have all transactions
  149. let txs: Vec<blake3::Hash> =
  150. block.txs.iter().map(|x| blake3::hash(&serialize(x))).collect();
  151. if self.transactions.get(&txs, true).is_err() {
  152. return Ok(false)
  153. }
  154. // Check if we have block slots uids vector
  155. let slots = match self.blocks_slots.get(&[blockhash], true) {
  156. Ok(v) => v[0].clone().unwrap(),
  157. Err(_) => return Ok(false),
  158. };
  159. let provided_block_slots: Vec<u64> = block.slots.iter().map(|x| x.id).collect();
  160. if slots != provided_block_slots {
  161. return Ok(false)
  162. }
  163. // Check if we have all slots
  164. if self.slots.get(&slots, true).is_err() {
  165. return Ok(false)
  166. }
  167. // Check provided info produces the same hash
  168. Ok(blockhash == block.hash()?)
  169. }
  170. /// Retrieve [`BlockInfo`]s by given hashes. Fails if any of them is not found.
  171. pub fn get_blocks_by_hash(&self, hashes: &[blake3::Hash]) -> Result<Vec<BlockInfo>> {
  172. let blocks = self.blocks.get(hashes, true)?;
  173. let blocks: Vec<Block> = blocks.iter().map(|x| x.clone().unwrap()).collect();
  174. let ret = self.get_blocks_infos(&blocks)?;
  175. Ok(ret)
  176. }
  177. /// Retrieve all [`BlockInfo`] for given slice of [`Block`].
  178. /// Fails if any of them is not found
  179. fn get_blocks_infos(&self, blocks: &[Block]) -> Result<Vec<BlockInfo>> {
  180. let mut ret = Vec::with_capacity(blocks.len());
  181. for block in blocks {
  182. let headers = self.headers.get(&[block.header], true)?;
  183. // Since we used strict get, its safe to unwrap here
  184. let header = headers[0].clone().unwrap();
  185. let txs = self.transactions.get(&block.txs, true)?;
  186. let txs = txs.iter().map(|x| x.clone().unwrap()).collect();
  187. let slots = self.blocks_slots.get(&[block.hash()], true)?;
  188. let slots = slots[0].clone().unwrap();
  189. let slots = self.slots.get(&slots, true)?;
  190. let block_slots = slots.iter().map(|x| x.clone().unwrap()).collect();
  191. let info = BlockInfo::new(header, txs, block.signature, block_slots);
  192. ret.push(info);
  193. }
  194. Ok(ret)
  195. }
  196. /// Retrieve [`BlockInfo`]s by given slots. Does not fail if any of them are not found.
  197. pub fn get_blocks_by_slot(&self, slots: &[u64]) -> Result<Vec<BlockInfo>> {
  198. debug!(target: "blockchain", "get_blocks_by_slot(): {:?}", slots);
  199. let blockhashes = self.order.get(slots, false)?;
  200. let mut hashes = vec![];
  201. for i in blockhashes.into_iter().flatten() {
  202. hashes.push(i);
  203. }
  204. self.get_blocks_by_hash(&hashes)
  205. }
  206. /// Retrieve n blocks after given start slot.
  207. pub fn get_blocks_after(&self, slot: u64, n: u64) -> Result<Vec<BlockInfo>> {
  208. debug!(target: "blockchain", "get_blocks_after(): {} -> {}", slot, n);
  209. let hashes = self.order.get_after(slot, n)?;
  210. self.get_blocks_by_hash(&hashes)
  211. }
  212. /// Retrieve stored blocks count
  213. pub fn len(&self) -> usize {
  214. self.order.len()
  215. }
  216. /// Retrieve stored txs count
  217. pub fn txs_len(&self) -> usize {
  218. self.transactions.len()
  219. }
  220. /// Check if blockchain contains any blocks
  221. pub fn is_empty(&self) -> bool {
  222. self.order.is_empty()
  223. }
  224. /// Retrieve genesis (first) block slot and hash.
  225. pub fn genesis(&self) -> Result<(u64, blake3::Hash)> {
  226. self.order.get_first()
  227. }
  228. /// Retrieve the last block slot and hash.
  229. pub fn last(&self) -> Result<(u64, blake3::Hash)> {
  230. self.order.get_last()
  231. }
  232. /// Retrieve the last block info.
  233. pub fn last_block(&self) -> Result<BlockInfo> {
  234. let (_, hash) = self.last()?;
  235. Ok(self.get_blocks_by_hash(&[hash])?[0].clone())
  236. }
  237. /// Retrieve the last slot.
  238. pub fn last_slot(&self) -> Result<Slot> {
  239. self.slots.get_last()
  240. }
  241. /// Retrieve n slots after given start slot.
  242. pub fn get_slots_after(&self, slot: u64, n: u64) -> Result<Vec<Slot>> {
  243. debug!(target: "blockchain", "get_slots_after(): {} -> {}", slot, n);
  244. self.slots.get_after(slot, n)
  245. }
  246. /// Retrieve [`Slot`]s by given ids. Does not fail if any of them are not found.
  247. pub fn get_slots_by_id(&self, ids: &[u64]) -> Result<Vec<Option<Slot>>> {
  248. debug!(target: "blockchain", "get_slots_by_id(): {:?}", ids);
  249. self.slots.get(ids, true)
  250. }
  251. /// Check if the given [`Slot`] is in the database and all trees.
  252. pub fn has_slot(&self, slot: &Slot) -> Result<bool> {
  253. Ok(self.slots.get(&[slot.id], true).is_ok())
  254. }
  255. /// Check if block order for the given slot is in the database.
  256. pub fn has_slot_order(&self, slot: u64) -> Result<bool> {
  257. let vec = match self.order.get(&[slot], true) {
  258. Ok(v) => v,
  259. Err(_) => return Ok(false),
  260. };
  261. Ok(!vec.is_empty())
  262. }
  263. /// Insert a given slice of pending transactions into the blockchain database.
  264. /// On success, the function returns the transaction hashes in the same order
  265. /// as the input transactions.
  266. pub fn add_pending_txs(&self, txs: &[Transaction]) -> Result<Vec<blake3::Hash>> {
  267. let (txs_batch, txs_hashes) = self.pending_txs.insert_batch(txs)?;
  268. let txs_order_batch = self.pending_txs_order.insert_batch(&txs_hashes)?;
  269. // Perform an atomic transaction over the trees and apply the batches.
  270. let trees = [self.pending_txs.0.clone(), self.pending_txs_order.0.clone()];
  271. let batches = [txs_batch, txs_order_batch];
  272. self.atomic_write(&trees, &batches)?;
  273. Ok(txs_hashes)
  274. }
  275. /// Retrieve all transactions from the pending tx store.
  276. /// Be careful as this will try to load everything in memory.
  277. pub fn get_pending_txs(&self) -> Result<Vec<Transaction>> {
  278. let txs = self.pending_txs.get_all()?;
  279. let indexes = self.pending_txs_order.get_all()?;
  280. if txs.len() != indexes.len() {
  281. return Err(Error::InvalidInputLengths)
  282. }
  283. let mut ret = Vec::with_capacity(txs.len());
  284. for index in indexes {
  285. ret.push(txs.get(&index.1).unwrap().clone());
  286. }
  287. Ok(ret)
  288. }
  289. /// Remove a given slice of pending transactions from the blockchain database.
  290. pub fn remove_pending_txs(&self, txs: &[Transaction]) -> Result<()> {
  291. let txs_hashes: Vec<blake3::Hash> =
  292. txs.iter().map(|x| blake3::hash(&serialize(x))).collect();
  293. let indexes = self.pending_txs_order.get_all()?;
  294. // We could do indexes.iter().map(|x| txs_hashes.contains(x.1)).collect.map(|x| x.0).collect
  295. // but this is faster since we don't do the second iteration
  296. let mut removed_indexes = vec![];
  297. for index in indexes {
  298. if txs_hashes.contains(&index.1) {
  299. removed_indexes.push(index.0);
  300. }
  301. }
  302. let txs_batch = self.pending_txs.remove_batch(&txs_hashes);
  303. let txs_order_batch = self.pending_txs_order.remove_batch(&removed_indexes);
  304. // Perform an atomic transaction over the trees and apply the batches.
  305. let trees = [self.pending_txs.0.clone(), self.pending_txs_order.0.clone()];
  306. let batches = [txs_batch, txs_order_batch];
  307. self.atomic_write(&trees, &batches)?;
  308. Ok(())
  309. }
  310. /// Auxiliary function to write to multiple trees completely atomic.
  311. fn atomic_write(&self, trees: &[sled::Tree], batches: &[sled::Batch]) -> Result<()> {
  312. if trees.len() != batches.len() {
  313. return Err(Error::InvalidInputLengths)
  314. }
  315. trees.transaction(|trees| {
  316. for (index, tree) in trees.iter().enumerate() {
  317. tree.apply_batch(&batches[index])?;
  318. }
  319. Ok::<(), sled::transaction::ConflictableTransactionError<sled::Error>>(())
  320. })?;
  321. Ok(())
  322. }
  323. /// Retrieve all blocks contained in the blockchain in order.
  324. /// Be careful as this will try to load everything in memory.
  325. pub fn get_all(&self) -> Result<Vec<BlockInfo>> {
  326. let order = self.order.get_all()?;
  327. let order: Vec<blake3::Hash> = order.iter().map(|x| x.1).collect();
  328. let blocks = self.get_blocks_by_hash(&order)?;
  329. Ok(blocks)
  330. }
  331. }
  332. /// Atomic pointer to sled db overlay.
  333. pub type SledDbOverlayPtr = Arc<Mutex<sled_overlay::SledDbOverlay>>;
  334. /// Atomic pointer to blockchain overlay.
  335. pub type BlockchainOverlayPtr = Arc<Mutex<BlockchainOverlay>>;
  336. /// Overlay structure over a [`Blockchain`] instance.
  337. pub struct BlockchainOverlay {
  338. /// Main [`sled_overlay::SledDbOverlay`] to the sled db connection
  339. pub overlay: SledDbOverlayPtr,
  340. /// Headers overlay
  341. pub headers: HeaderStoreOverlay,
  342. /// Blocks overlay
  343. pub blocks: BlockStoreOverlay,
  344. /// Block order overlay
  345. pub order: BlockOrderStoreOverlay,
  346. /// Slots overlay
  347. pub slots: SlotStoreOverlay,
  348. /// Blocks slots overlay
  349. pub blocks_slots: BlocksSlotsStoreOverlay,
  350. /// Block height difficulties overlay,
  351. pub difficulties: BlockDifficultyStoreOverlay,
  352. /// Transactions overlay
  353. pub transactions: TxStoreOverlay,
  354. /// Contract states overlay
  355. pub contracts: ContractStateStoreOverlay,
  356. /// Wasm bincodes overlay
  357. pub wasm_bincode: WasmStoreOverlay,
  358. }
  359. impl BlockchainOverlay {
  360. /// Instantiate a new `BlockchainOverlay` over the given [`Blockchain`] instance.
  361. pub fn new(blockchain: &Blockchain) -> Result<BlockchainOverlayPtr> {
  362. let overlay = Arc::new(Mutex::new(sled_overlay::SledDbOverlay::new(&blockchain.sled_db)));
  363. let headers = HeaderStoreOverlay::new(&overlay)?;
  364. let blocks = BlockStoreOverlay::new(&overlay)?;
  365. let order = BlockOrderStoreOverlay::new(&overlay)?;
  366. let slots = SlotStoreOverlay::new(&overlay)?;
  367. let blocks_slots = BlocksSlotsStoreOverlay::new(&overlay)?;
  368. let difficulties = BlockDifficultyStoreOverlay::new(&overlay)?;
  369. let transactions = TxStoreOverlay::new(&overlay)?;
  370. let contracts = ContractStateStoreOverlay::new(&overlay)?;
  371. let wasm_bincode = WasmStoreOverlay::new(&overlay)?;
  372. Ok(Arc::new(Mutex::new(Self {
  373. overlay,
  374. headers,
  375. blocks,
  376. order,
  377. slots,
  378. blocks_slots,
  379. difficulties,
  380. transactions,
  381. contracts,
  382. wasm_bincode,
  383. })))
  384. }
  385. /// Check if blockchain contains any blocks
  386. pub fn is_empty(&self) -> Result<bool> {
  387. self.order.is_empty()
  388. }
  389. /// Retrieve the last block slot and hash.
  390. pub fn last(&self) -> Result<(u64, blake3::Hash)> {
  391. self.order.get_last()
  392. }
  393. /// Retrieve the last block info.
  394. pub fn last_block(&self) -> Result<BlockInfo> {
  395. let (_, hash) = self.last()?;
  396. Ok(self.get_blocks_by_hash(&[hash])?[0].clone())
  397. }
  398. /// Insert a given [`BlockInfo`] into the overlay.
  399. /// This functions wraps all the logic of separating the block into specific
  400. /// data that can be fed into the different trees of the overlay.
  401. /// Upon success, the functions returns the block hash that
  402. /// were given and appended to the overlay.
  403. /// Since we are adding to the overlay, we don't need to exeucte
  404. /// the writes atomically.
  405. pub fn add_block(&self, block: &BlockInfo) -> Result<blake3::Hash> {
  406. // Store transactions
  407. self.transactions.insert(&block.txs)?;
  408. // Store header
  409. self.headers.insert(&[block.header.clone()])?;
  410. // Store block
  411. let blk: Block = Block::from_block_info(block)?;
  412. let block_hash = self.blocks.insert(&[blk])?[0];
  413. let block_hash_vec = [block_hash];
  414. // Store block order
  415. self.order.insert(&[block.header.height], &block_hash_vec)?;
  416. // Store block slots uids vector
  417. let slots = block.slots.iter().map(|x| x.id).collect();
  418. self.blocks_slots.insert(&block_hash_vec, &[&slots])?;
  419. // Store block slots
  420. self.slots.insert(&block.slots)?;
  421. Ok(block_hash)
  422. }
  423. /// Check if the given [`BlockInfo`] is in the database and all trees.
  424. pub fn has_block(&self, block: &BlockInfo) -> Result<bool> {
  425. let blockhash = match self.order.get(&[block.header.height], true) {
  426. Ok(v) => v[0].unwrap(),
  427. Err(_) => return Ok(false),
  428. };
  429. // Check if we have all transactions
  430. let txs: Vec<blake3::Hash> =
  431. block.txs.iter().map(|x| blake3::hash(&serialize(x))).collect();
  432. if self.transactions.get(&txs, true).is_err() {
  433. return Ok(false)
  434. }
  435. // Check if we have block slots uids vector
  436. let slots = match self.blocks_slots.get(&[blockhash], true) {
  437. Ok(v) => v[0].clone().unwrap(),
  438. Err(_) => return Ok(false),
  439. };
  440. let provided_block_slots: Vec<u64> = block.slots.iter().map(|x| x.id).collect();
  441. if slots != provided_block_slots {
  442. return Ok(false)
  443. }
  444. // Check if we have all slots
  445. if self.slots.get(&slots, true).is_err() {
  446. return Ok(false)
  447. }
  448. // Check provided info produces the same hash
  449. Ok(blockhash == block.hash()?)
  450. }
  451. /// Retrieve [`BlockInfo`]s by given hashes. Fails if any of them is not found.
  452. pub fn get_blocks_by_hash(&self, hashes: &[blake3::Hash]) -> Result<Vec<BlockInfo>> {
  453. let blocks = self.blocks.get(hashes, true)?;
  454. let blocks: Vec<Block> = blocks.iter().map(|x| x.clone().unwrap()).collect();
  455. let ret = self.get_blocks_infos(&blocks)?;
  456. Ok(ret)
  457. }
  458. /// Retrieve all [`BlockInfo`] for given slice of [`Block`].
  459. /// Fails if any of them is not found
  460. fn get_blocks_infos(&self, blocks: &[Block]) -> Result<Vec<BlockInfo>> {
  461. let mut ret = Vec::with_capacity(blocks.len());
  462. for block in blocks {
  463. let headers = self.headers.get(&[block.header], true)?;
  464. // Since we used strict get, its safe to unwrap here
  465. let header = headers[0].clone().unwrap();
  466. let txs = self.transactions.get(&block.txs, true)?;
  467. let txs = txs.iter().map(|x| x.clone().unwrap()).collect();
  468. let slots = self.blocks_slots.get(&[block.hash()], true)?;
  469. let slots = slots[0].clone().unwrap();
  470. let slots = self.slots.get(&slots, true)?;
  471. let block_slots = slots.iter().map(|x| x.clone().unwrap()).collect();
  472. let info = BlockInfo::new(header, txs, block.signature, block_slots);
  473. ret.push(info);
  474. }
  475. Ok(ret)
  476. }
  477. /// Checkpoint overlay so we can revert to it, if needed.
  478. pub fn checkpoint(&self) {
  479. self.overlay.lock().unwrap().checkpoint();
  480. }
  481. /// Revert to current overlay checkpoint.
  482. pub fn revert_to_checkpoint(&self) -> Result<()> {
  483. self.overlay.lock().unwrap().revert_to_checkpoint()?;
  484. Ok(())
  485. }
  486. /// Auxiliary function to create a full clone using SledDbOverlay::clone,
  487. /// generating new pointers for the underlying overlays.
  488. pub fn full_clone(&self) -> Result<BlockchainOverlayPtr> {
  489. let overlay = Arc::new(Mutex::new(self.overlay.lock().unwrap().clone()));
  490. let headers = HeaderStoreOverlay::new(&overlay)?;
  491. let blocks = BlockStoreOverlay::new(&overlay)?;
  492. let order = BlockOrderStoreOverlay::new(&overlay)?;
  493. let slots = SlotStoreOverlay::new(&overlay)?;
  494. let blocks_slots = BlocksSlotsStoreOverlay::new(&overlay)?;
  495. let difficulties = BlockDifficultyStoreOverlay::new(&overlay)?;
  496. let transactions = TxStoreOverlay::new(&overlay)?;
  497. let contracts = ContractStateStoreOverlay::new(&overlay)?;
  498. let wasm_bincode = WasmStoreOverlay::new(&overlay)?;
  499. Ok(Arc::new(Mutex::new(Self {
  500. overlay,
  501. headers,
  502. blocks,
  503. order,
  504. slots,
  505. blocks_slots,
  506. difficulties,
  507. transactions,
  508. contracts,
  509. wasm_bincode,
  510. })))
  511. }
  512. }
  513. /// Parse a sled record with a u64 keyin the form of a tuple (`key`, `value`).
  514. pub fn parse_u64_key_record<T: Decodable>(record: (sled::IVec, sled::IVec)) -> Result<(u64, T)> {
  515. let key_bytes: [u8; 8] = record.0.as_ref().try_into().unwrap();
  516. let key = u64::from_be_bytes(key_bytes);
  517. let value = deserialize(&record.1)?;
  518. Ok((key, value))
  519. }
  520. /// Parse a sled record in the form of a tuple (`key`, `value`).
  521. pub fn parse_record<T1: Decodable, T2: Decodable>(
  522. record: (sled::IVec, sled::IVec),
  523. ) -> Result<(T1, T2)> {
  524. let key = deserialize(&record.0)?;
  525. let value = deserialize(&record.1)?;
  526. Ok((key, value))
  527. }