1use std::{
20 slice,
21 sync::{Arc, Mutex},
22};
23
24use darkfi_sdk::tx::TransactionHash;
25use darkfi_serial::{deserialize, Decodable};
26use sled_overlay::{
27 sled,
28 sled::{IVec, Transactional},
29};
30use tracing::debug;
31
32#[cfg(feature = "async-serial")]
33use darkfi_serial::{deserialize_async, AsyncDecodable};
34
35use crate::{tx::Transaction, util::time::Timestamp, Error, Result};
36
37pub mod block_store;
39pub use block_store::{
40 Block, BlockDifficulty, BlockInfo, BlockStore, BlockStoreOverlay, SLED_BLOCK_DIFFICULTY_TREE,
41 SLED_BLOCK_ORDER_TREE, SLED_BLOCK_STATE_INVERSE_DIFF_TREE, SLED_BLOCK_TREE,
42};
43
44pub mod header_store;
46pub use header_store::{
47 Header, HeaderHash, HeaderStore, HeaderStoreOverlay, SLED_HEADER_TREE, SLED_SYNC_HEADER_TREE,
48};
49
50pub mod tx_store;
52pub use tx_store::{
53 TxStore, TxStoreOverlay, SLED_PENDING_TX_TREE, SLED_TX_LOCATION_TREE, SLED_TX_TREE,
54};
55
56pub mod contract_store;
58pub use contract_store::{
59 ContractStore, ContractStoreOverlay, SLED_BINCODE_TREE, SLED_CONTRACTS_TREE,
60 SLED_CONTRACTS_TREES_TREE,
61};
62
63pub mod monero;
65
66#[derive(Clone)]
68pub struct Blockchain {
69 pub sled_db: sled::Db,
71 pub headers: HeaderStore,
73 pub blocks: BlockStore,
75 pub transactions: TxStore,
77 pub contracts: ContractStore,
79}
80
81impl Blockchain {
82 pub fn new(db: &sled::Db) -> Result<Self> {
84 let headers = HeaderStore::new(db)?;
85 let blocks = BlockStore::new(db)?;
86 let transactions = TxStore::new(db)?;
87 let contracts = ContractStore::new(db)?;
88
89 Ok(Self { sled_db: db.clone(), headers, blocks, transactions, contracts })
90 }
91
92 pub fn add_block(&self, block: &BlockInfo) -> Result<HeaderHash> {
98 let mut trees = vec![];
99 let mut batches = vec![];
100
101 let (headers_batch, _) = self.headers.insert_batch(slice::from_ref(&block.header));
103 trees.push(self.headers.main.clone());
104 batches.push(headers_batch);
105
106 let blk: Block = Block::from_block_info(block);
108 let (bocks_batch, block_hashes) = self.blocks.insert_batch(&[blk]);
109 let block_hash = block_hashes[0];
110 let block_hash_vec = [block_hash];
111 trees.push(self.blocks.main.clone());
112 batches.push(bocks_batch);
113
114 let blocks_order_batch =
116 self.blocks.insert_batch_order(&[block.header.height], &block_hash_vec);
117 trees.push(self.blocks.order.clone());
118 batches.push(blocks_order_batch);
119
120 let (txs_batch, txs_hashes) = self.transactions.insert_batch(&block.txs);
122 trees.push(self.transactions.main.clone());
123 batches.push(txs_batch);
124
125 let txs_locations_batch =
127 self.transactions.insert_batch_location(&txs_hashes, block.header.height);
128 trees.push(self.transactions.location.clone());
129 batches.push(txs_locations_batch);
130
131 self.atomic_write(&trees, &batches)?;
133
134 Ok(block_hash)
135 }
136
137 pub fn has_block(&self, block: &BlockInfo) -> Result<bool> {
139 let blockhash = match self.blocks.get_order(&[block.header.height], true) {
140 Ok(v) => v[0].unwrap(),
141 Err(_) => return Ok(false),
142 };
143
144 let txs: Vec<TransactionHash> = block.txs.iter().map(|tx| tx.hash()).collect();
146 if self.transactions.get(&txs, true).is_err() {
147 return Ok(false)
148 }
149
150 Ok(blockhash == block.hash())
152 }
153
154 pub fn get_blocks_by_hash(&self, hashes: &[HeaderHash]) -> Result<Vec<BlockInfo>> {
156 let blocks = self.blocks.get(hashes, true)?;
157 let blocks: Vec<Block> = blocks.iter().map(|x| x.clone().unwrap()).collect();
158 let ret = self.get_blocks_infos(&blocks)?;
159
160 Ok(ret)
161 }
162
163 fn get_blocks_infos(&self, blocks: &[Block]) -> Result<Vec<BlockInfo>> {
166 let mut ret = Vec::with_capacity(blocks.len());
167 for block in blocks {
168 let headers = self.headers.get(&[block.header], true)?;
169 let header = headers[0].clone().unwrap();
171
172 let txs = self.transactions.get(&block.txs, true)?;
173 let txs = txs.iter().map(|x| x.clone().unwrap()).collect();
174
175 let info = BlockInfo::new(header, txs, block.signature);
176 ret.push(info);
177 }
178
179 Ok(ret)
180 }
181
182 pub fn get_blocks_by_heights(&self, heights: &[u32]) -> Result<Vec<BlockInfo>> {
184 debug!(target: "blockchain", "get_blocks_by_heights(): {heights:?}");
185 let blockhashes = self.blocks.get_order(heights, false)?;
186
187 let mut hashes = vec![];
188 for i in blockhashes.into_iter().flatten() {
189 hashes.push(i);
190 }
191
192 self.get_blocks_by_hash(&hashes)
193 }
194
195 pub fn get_headers_by_hash(&self, hashes: &[HeaderHash]) -> Result<Vec<Header>> {
197 let headers = self.headers.get(hashes, true)?;
198 let ret: Vec<Header> = headers.iter().map(|x| x.clone().unwrap()).collect();
199
200 Ok(ret)
201 }
202
203 pub fn get_headers_by_heights(&self, heights: &[u32]) -> Result<Vec<Header>> {
205 debug!(target: "blockchain", "get_headers_by_heights(): {heights:?}");
206 let blockhashes = self.blocks.get_order(heights, true)?;
207
208 let mut hashes = vec![];
209 for i in blockhashes.into_iter().flatten() {
210 hashes.push(i);
211 }
212
213 self.get_headers_by_hash(&hashes)
214 }
215
216 pub fn get_headers_before(&self, height: u32, n: usize) -> Result<Vec<Header>> {
218 debug!(target: "blockchain", "get_headers_before(): {height} -> {n}");
219 let hashes = self.blocks.get_before(height, n)?;
220 let headers = self.headers.get(&hashes, true)?;
221 Ok(headers.iter().map(|h| h.clone().unwrap()).collect())
222 }
223
224 pub fn len(&self) -> usize {
226 self.blocks.len()
227 }
228
229 pub fn txs_len(&self) -> usize {
231 self.transactions.len()
232 }
233
234 pub fn is_empty(&self) -> bool {
236 self.blocks.is_empty()
237 }
238
239 pub fn genesis(&self) -> Result<(u32, HeaderHash)> {
241 self.blocks.get_first()
242 }
243
244 pub fn genesis_block(&self) -> Result<BlockInfo> {
246 let (_, hash) = self.genesis()?;
247 Ok(self.get_blocks_by_hash(&[hash])?[0].clone())
248 }
249
250 pub fn last(&self) -> Result<(u32, HeaderHash)> {
252 self.blocks.get_last()
253 }
254
255 pub fn last_header(&self) -> Result<Header> {
257 let (_, hash) = self.last()?;
258 Ok(self.headers.get(&[hash], true)?[0].clone().unwrap())
259 }
260
261 pub fn last_block(&self) -> Result<BlockInfo> {
263 let (_, hash) = self.last()?;
264 Ok(self.get_blocks_by_hash(&[hash])?[0].clone())
265 }
266
267 pub fn last_block_difficulty(&self) -> Result<BlockDifficulty> {
270 if let Some(found) = self.blocks.get_last_difficulty()? {
271 return Ok(found)
272 }
273
274 let genesis_block = self.genesis_block()?;
275 Ok(BlockDifficulty::genesis(genesis_block.header.timestamp))
276 }
277
278 pub fn has_height(&self, height: u32) -> Result<bool> {
280 let vec = match self.blocks.get_order(&[height], true) {
281 Ok(v) => v,
282 Err(_) => return Ok(false),
283 };
284 Ok(!vec.is_empty())
285 }
286
287 pub fn add_pending_txs(&self, txs: &[Transaction]) -> Result<Vec<TransactionHash>> {
291 self.transactions.insert_pending(txs)
292 }
293
294 pub fn get_pending_txs(&self) -> Result<Vec<Transaction>> {
297 let txs = self.transactions.get_all_pending()?;
298
299 let mut ret = Vec::with_capacity(txs.len());
300 for (_, tx) in txs {
301 ret.push(tx);
302 }
303
304 Ok(ret)
305 }
306
307 pub fn remove_pending_txs(&self, txs: &[Transaction]) -> Result<()> {
309 let txs_hashes: Vec<TransactionHash> = txs.iter().map(|tx| tx.hash()).collect();
310 self.remove_pending_txs_hashes(&txs_hashes)
311 }
312
313 pub fn remove_pending_txs_hashes(&self, txs: &[TransactionHash]) -> Result<()> {
315 self.transactions.remove_pending(txs)
316 }
317
318 fn atomic_write(&self, trees: &[sled::Tree], batches: &[sled::Batch]) -> Result<()> {
320 if trees.len() != batches.len() {
321 return Err(Error::InvalidInputLengths)
322 }
323
324 trees.transaction(|trees| {
325 for (index, tree) in trees.iter().enumerate() {
326 tree.apply_batch(&batches[index])?;
327 }
328
329 Ok::<(), sled::transaction::ConflictableTransactionError<sled::Error>>(())
330 })?;
331
332 Ok(())
333 }
334
335 pub fn get_all(&self) -> Result<Vec<BlockInfo>> {
338 let order = self.blocks.get_all_order()?;
339 let order: Vec<HeaderHash> = order.iter().map(|x| x.1).collect();
340 let blocks = self.get_blocks_by_hash(&order)?;
341
342 Ok(blocks)
343 }
344
345 pub fn get_by_range(&self, start: u32, end: u32) -> Result<Vec<BlockInfo>> {
347 let blockhashes = self.blocks.get_order_by_range(start, end)?;
348 let hashes: Vec<HeaderHash> = blockhashes.into_iter().map(|(_, hash)| hash).collect();
349 self.get_blocks_by_hash(&hashes)
350 }
351
352 pub fn get_last_n(&self, n: usize) -> Result<Vec<BlockInfo>> {
354 let records = self.blocks.get_last_n_orders(n)?;
355
356 let mut last_n = vec![];
357 for record in records {
358 let header_hash = record.1;
359 let blocks = self.get_blocks_by_hash(&[header_hash])?;
360 for block in blocks {
361 last_n.push(block.clone());
362 }
363 }
364
365 Ok(last_n)
366 }
367
368 pub fn reset_to_height(&self, height: u32) -> Result<()> {
371 let (last, _) = self.last()?;
373
374 if height >= last {
376 return Ok(())
377 }
378
379 let heights: Vec<u32> = (height + 1..=last).rev().collect();
382 let inverse_diffs = self.blocks.get_state_inverse_diff(&heights, true)?;
383
384 let overlay = BlockchainOverlay::new(self)?;
386
387 let overlay_lock = overlay.lock().unwrap();
389 let mut lock = overlay_lock.overlay.lock().unwrap();
390 for inverse_diff in inverse_diffs {
391 let inverse_diff = inverse_diff.unwrap();
393 lock.add_diff(&inverse_diff)?;
394 lock.apply_diff(&inverse_diff)?;
395 self.sled_db.flush()?;
396 }
397 drop(lock);
398 drop(overlay_lock);
399
400 Ok(())
401 }
402
403 pub fn get_randomx_vm_keys(
410 &self,
411 key_change_height: &u32,
412 key_change_delay: &u32,
413 height: Option<u32>,
414 ) -> Result<(HeaderHash, Option<HeaderHash>)> {
415 let last = match height {
417 Some(h) => &self.get_headers_by_heights(&[if h != 0 { h - 1 } else { 0 }])?[0],
418 None => &self.last_header()?,
419 };
420
421 if &last.height <= key_change_height {
423 let current = self.genesis()?.1;
425
426 let next = if &last.height == key_change_height { Some(last.hash()) } else { None };
428
429 return Ok((current, next))
430 }
431
432 let distance = last.height % key_change_height;
435
436 if distance == 0 {
440 return Ok((
441 self.get_headers_by_heights(&[last.height - key_change_height])?[0].hash(),
442 Some(last.hash()),
443 ))
444 }
445
446 if &distance < key_change_delay {
451 return Ok((
452 self.get_headers_by_heights(&[last.height - (distance + key_change_height)])?[0]
453 .hash(),
454 Some(self.get_headers_by_heights(&[last.height - distance])?[0].hash()),
455 ))
456 }
457
458 let current = self.get_headers_by_heights(&[last.height - distance])?[0].hash();
462 Ok((current, None))
463 }
464}
465
466pub type SledDbOverlayPtr = Arc<Mutex<sled_overlay::SledDbOverlay>>;
468
469pub type BlockchainOverlayPtr = Arc<Mutex<BlockchainOverlay>>;
471
472pub struct BlockchainOverlay {
474 pub overlay: SledDbOverlayPtr,
476 pub headers: HeaderStoreOverlay,
478 pub blocks: BlockStoreOverlay,
480 pub transactions: TxStoreOverlay,
482 pub contracts: ContractStoreOverlay,
484}
485
486impl BlockchainOverlay {
487 pub fn new(blockchain: &Blockchain) -> Result<BlockchainOverlayPtr> {
489 let protected_trees = vec![
491 SLED_BLOCK_TREE,
492 SLED_BLOCK_ORDER_TREE,
493 SLED_BLOCK_DIFFICULTY_TREE,
494 SLED_BLOCK_STATE_INVERSE_DIFF_TREE,
495 SLED_HEADER_TREE,
496 SLED_SYNC_HEADER_TREE,
497 SLED_TX_TREE,
498 SLED_TX_LOCATION_TREE,
499 SLED_PENDING_TX_TREE,
500 SLED_CONTRACTS_TREE,
501 SLED_CONTRACTS_TREES_TREE,
502 SLED_BINCODE_TREE,
503 ];
504 let overlay = Arc::new(Mutex::new(sled_overlay::SledDbOverlay::new(
505 &blockchain.sled_db,
506 protected_trees,
507 )));
508 let headers = HeaderStoreOverlay::new(&overlay)?;
509 let blocks = BlockStoreOverlay::new(&overlay)?;
510 let transactions = TxStoreOverlay::new(&overlay)?;
511 let contracts = ContractStoreOverlay::new(&overlay)?;
512
513 Ok(Arc::new(Mutex::new(Self { overlay, headers, blocks, transactions, contracts })))
514 }
515
516 pub fn is_empty(&self) -> Result<bool> {
518 self.blocks.is_empty()
519 }
520
521 pub fn last(&self) -> Result<(u32, HeaderHash)> {
523 self.blocks.get_last()
524 }
525
526 pub fn last_block(&self) -> Result<BlockInfo> {
528 let (_, hash) = self.last()?;
529 Ok(self.get_blocks_by_hash(&[hash])?[0].clone())
530 }
531
532 pub fn last_block_height(&self) -> Result<u32> {
534 Ok(self.last()?.0)
535 }
536
537 pub fn last_block_timestamp(&self) -> Result<Timestamp> {
539 let (_, hash) = self.last()?;
540 Ok(self.get_blocks_by_hash(&[hash])?[0].header.timestamp)
541 }
542
543 pub fn add_block(&self, block: &BlockInfo) -> Result<HeaderHash> {
551 self.headers.insert(slice::from_ref(&block.header))?;
553
554 let blk: Block = Block::from_block_info(block);
556 let txs_hashes = blk.txs.clone();
557 let block_hash = self.blocks.insert(&[blk])?[0];
558 let block_hash_vec = [block_hash];
559
560 self.blocks.insert_order(&[block.header.height], &block_hash_vec)?;
562
563 self.transactions.insert(&block.txs)?;
565
566 self.transactions.insert_location(&txs_hashes, block.header.height)?;
568
569 Ok(block_hash)
570 }
571
572 pub fn has_block(&self, block: &BlockInfo) -> Result<bool> {
574 let blockhash = match self.blocks.get_order(&[block.header.height], true) {
575 Ok(v) => v[0].unwrap(),
576 Err(_) => return Ok(false),
577 };
578
579 let txs: Vec<TransactionHash> = block.txs.iter().map(|tx| tx.hash()).collect();
581 if self.transactions.get(&txs, true).is_err() {
582 return Ok(false)
583 }
584
585 Ok(blockhash == block.hash())
587 }
588
589 pub fn get_headers_by_hash(&self, hashes: &[HeaderHash]) -> Result<Vec<Header>> {
591 let headers = self.headers.get(hashes, true)?;
592 let ret: Vec<Header> = headers.iter().map(|x| x.clone().unwrap()).collect();
593
594 Ok(ret)
595 }
596
597 pub fn get_blocks_by_hash(&self, hashes: &[HeaderHash]) -> Result<Vec<BlockInfo>> {
599 let blocks = self.blocks.get(hashes, true)?;
600 let blocks: Vec<Block> = blocks.iter().map(|x| x.clone().unwrap()).collect();
601 let ret = self.get_blocks_infos(&blocks)?;
602
603 Ok(ret)
604 }
605
606 fn get_blocks_infos(&self, blocks: &[Block]) -> Result<Vec<BlockInfo>> {
609 let mut ret = Vec::with_capacity(blocks.len());
610 for block in blocks {
611 let headers = self.headers.get(&[block.header], true)?;
612 let header = headers[0].clone().unwrap();
614
615 let txs = self.transactions.get(&block.txs, true)?;
616 let txs = txs.iter().map(|x| x.clone().unwrap()).collect();
617
618 let info = BlockInfo::new(header, txs, block.signature);
619 ret.push(info);
620 }
621
622 Ok(ret)
623 }
624
625 pub fn get_blocks_txs_hashes(&self, hashes: &[HeaderHash]) -> Result<Vec<TransactionHash>> {
627 let blocks = self.blocks.get(hashes, true)?;
628 let mut ret = vec![];
629 for block in blocks {
630 ret.extend_from_slice(&block.unwrap().txs);
631 }
632
633 Ok(ret)
634 }
635
636 pub fn checkpoint(&self) {
638 self.overlay.lock().unwrap().checkpoint();
639 }
640
641 pub fn revert_to_checkpoint(&self) {
643 self.overlay.lock().unwrap().revert_to_checkpoint();
644 }
645
646 pub fn full_clone(&self) -> Result<BlockchainOverlayPtr> {
649 let overlay = Arc::new(Mutex::new(self.overlay.lock().unwrap().clone()));
650 let headers = HeaderStoreOverlay::new(&overlay)?;
651 let blocks = BlockStoreOverlay::new(&overlay)?;
652 let transactions = TxStoreOverlay::new(&overlay)?;
653 let contracts = ContractStoreOverlay::new(&overlay)?;
654
655 Ok(Arc::new(Mutex::new(Self { overlay, headers, blocks, transactions, contracts })))
656 }
657}
658
659pub fn parse_record<T1: Decodable, T2: Decodable>(record: (IVec, IVec)) -> Result<(T1, T2)> {
661 let key = deserialize(&record.0)?;
662 let value = deserialize(&record.1)?;
663
664 Ok((key, value))
665}
666
667pub fn parse_u32_key_record<T: Decodable>(record: (IVec, IVec)) -> Result<(u32, T)> {
670 let key_bytes: [u8; 4] = record.0.as_ref().try_into().unwrap();
671 let key = u32::from_be_bytes(key_bytes);
672 let value = deserialize(&record.1)?;
673
674 Ok((key, value))
675}
676
677pub fn parse_u64_key_record<T: Decodable>(record: (IVec, IVec)) -> Result<(u64, T)> {
680 let key_bytes: [u8; 8] = record.0.as_ref().try_into().unwrap();
681 let key = u64::from_be_bytes(key_bytes);
682 let value = deserialize(&record.1)?;
683
684 Ok((key, value))
685}
686
687#[cfg(feature = "async-serial")]
688pub async fn parse_record_async<T1: AsyncDecodable, T2: AsyncDecodable>(
690 record: (IVec, IVec),
691) -> Result<(T1, T2)> {
692 let key = deserialize_async(&record.0).await?;
693 let value = deserialize_async(&record.1).await?;
694
695 Ok((key, value))
696}
697
698#[cfg(feature = "async-serial")]
699pub async fn parse_u32_key_record_async<T: AsyncDecodable>(
702 record: (IVec, IVec),
703) -> Result<(u32, T)> {
704 let key_bytes: [u8; 4] = record.0.as_ref().try_into().unwrap();
705 let key = u32::from_be_bytes(key_bytes);
706 let value = deserialize_async(&record.1).await?;
707
708 Ok((key, value))
709}
710
711#[cfg(feature = "async-serial")]
712pub async fn parse_u64_key_record_async<T: AsyncDecodable>(
715 record: (IVec, IVec),
716) -> Result<(u64, T)> {
717 let key_bytes: [u8; 8] = record.0.as_ref().try_into().unwrap();
718 let key = u64::from_be_bytes(key_bytes);
719 let value = deserialize_async(&record.1).await?;
720
721 Ok((key, value))
722}
723
724#[cfg(test)]
725mod tests {
726 use crate::validator::pow::{RANDOMX_KEY_CHANGE_DELAY, RANDOMX_KEY_CHANGING_HEIGHT};
727
728 fn get_randomx_vm_keys_heights(last: u32) -> (u32, Option<u32>) {
731 if last <= RANDOMX_KEY_CHANGING_HEIGHT {
733 let current = 0;
735
736 let next = if last == RANDOMX_KEY_CHANGING_HEIGHT { Some(last) } else { None };
738
739 return (current, next)
740 }
741
742 let distance = last % RANDOMX_KEY_CHANGING_HEIGHT;
745
746 if distance == 0 {
749 return (last - RANDOMX_KEY_CHANGING_HEIGHT, Some(last))
750 }
751
752 if distance < RANDOMX_KEY_CHANGE_DELAY {
756 return (last - (distance + RANDOMX_KEY_CHANGING_HEIGHT), Some(last - distance))
757 }
758
759 let current = last - distance;
763 (current, None)
764 }
765
766 #[test]
767 fn test_randomx_keys_retrieval_logic() {
768 let (current, next) = get_randomx_vm_keys_heights(2047);
770 assert_eq!(current, 0);
771 assert!(next.is_none());
772
773 let (current, next) = get_randomx_vm_keys_heights(2048);
775 assert_eq!(current, 0);
776 assert_eq!(next, Some(2048));
777
778 let (current, next) = get_randomx_vm_keys_heights(4096);
781 assert_eq!(current, 2048);
782 assert_eq!(next, Some(4096));
783
784 let (current, next) = get_randomx_vm_keys_heights(4097);
786 assert_eq!(current, 2048);
787 assert_eq!(next, Some(4096));
788
789 let (current, next) = get_randomx_vm_keys_heights(4160);
791 assert_eq!(current, 4096);
792 assert!(next.is_none());
793
794 let (current, next) = get_randomx_vm_keys_heights(4161);
796 assert_eq!(current, 4096);
797 assert!(next.is_none());
798 }
799}