ckb_store/
data_loader_wrapper.rs

1//! Data loader wrapper for blockchain data access.
2//!
3//! This module provides a wrapper around the chain store for efficient loading
4//! of cell data and other blockchain information needed for transaction verification.
5use crate::ChainStore;
6use ckb_traits::{
7    CellDataProvider, EpochProvider, ExtensionProvider, HeaderFields, HeaderFieldsProvider,
8    HeaderProvider,
9};
10use ckb_types::{
11    bytes::Bytes,
12    core::{BlockExt, BlockNumber, EpochExt, HeaderView},
13    packed::{self, Byte32, OutPoint},
14};
15use std::sync::Arc;
16
17/// DataLoaderWrapper wrap`ChainStore`
18/// impl `HeaderProvider` `CellDataProvider` `EpochProvider`
19pub struct DataLoaderWrapper<T>(Arc<T>);
20
21// auto derive don't work
22impl<T> Clone for DataLoaderWrapper<T> {
23    fn clone(&self) -> Self {
24        DataLoaderWrapper(Arc::clone(&self.0))
25    }
26}
27
28/// Auto transform Arc wrapped `ChainStore` to `DataLoaderWrapper`
29pub trait AsDataLoader<T> {
30    /// Return arc cloned DataLoaderWrapper
31    fn as_data_loader(&self) -> DataLoaderWrapper<T>;
32}
33
34impl<T> AsDataLoader<T> for Arc<T>
35where
36    T: ChainStore,
37{
38    fn as_data_loader(&self) -> DataLoaderWrapper<T> {
39        DataLoaderWrapper(Arc::clone(self))
40    }
41}
42
43impl<T> CellDataProvider for DataLoaderWrapper<T>
44where
45    T: ChainStore,
46{
47    fn get_cell_data(&self, out_point: &OutPoint) -> Option<Bytes> {
48        ChainStore::get_cell_data(self.0.as_ref(), out_point).map(|(data, _)| data)
49    }
50
51    fn get_cell_data_hash(&self, out_point: &OutPoint) -> Option<Byte32> {
52        ChainStore::get_cell_data_hash(self.0.as_ref(), out_point)
53    }
54}
55
56impl<T> HeaderProvider for DataLoaderWrapper<T>
57where
58    T: ChainStore,
59{
60    fn get_header(&self, block_hash: &Byte32) -> Option<HeaderView> {
61        ChainStore::get_block_header(self.0.as_ref(), block_hash)
62    }
63}
64
65impl<T> HeaderFieldsProvider for DataLoaderWrapper<T>
66where
67    T: ChainStore,
68{
69    fn get_header_fields(&self, hash: &Byte32) -> Option<HeaderFields> {
70        self.0.get_block_header(hash).map(|header| HeaderFields {
71            number: header.number(),
72            epoch: header.epoch(),
73            parent_hash: header.data().raw().parent_hash(),
74            timestamp: header.timestamp(),
75            hash: header.hash(),
76        })
77    }
78}
79
80impl<T> EpochProvider for DataLoaderWrapper<T>
81where
82    T: ChainStore,
83{
84    fn get_epoch_ext(&self, header: &HeaderView) -> Option<EpochExt> {
85        ChainStore::get_block_epoch_index(self.0.as_ref(), &header.hash())
86            .and_then(|index| ChainStore::get_epoch_ext(self.0.as_ref(), &index))
87    }
88
89    fn get_block_hash(&self, number: BlockNumber) -> Option<Byte32> {
90        ChainStore::get_block_hash(self.0.as_ref(), number)
91    }
92
93    fn get_block_ext(&self, block_hash: &Byte32) -> Option<BlockExt> {
94        ChainStore::get_block_ext(self.0.as_ref(), block_hash)
95    }
96
97    fn get_block_header(&self, hash: &Byte32) -> Option<HeaderView> {
98        ChainStore::get_block_header(self.0.as_ref(), hash)
99    }
100}
101
102impl<T> ExtensionProvider for DataLoaderWrapper<T>
103where
104    T: ChainStore,
105{
106    fn get_block_extension(&self, hash: &Byte32) -> Option<packed::Bytes> {
107        ChainStore::get_block_extension(self.0.as_ref(), hash)
108    }
109}
110
111/// Borrowed DataLoaderWrapper with lifetime
112pub struct BorrowedDataLoaderWrapper<'a, T>(&'a T);
113impl<'a, T: ChainStore> BorrowedDataLoaderWrapper<'a, T> {
114    /// Construct new BorrowedDataLoaderWrapper
115    pub fn new(source: &'a T) -> Self {
116        BorrowedDataLoaderWrapper(source)
117    }
118}
119
120impl<'a, T: ChainStore> CellDataProvider for BorrowedDataLoaderWrapper<'a, T> {
121    fn get_cell_data(&self, out_point: &OutPoint) -> Option<Bytes> {
122        self.0.get_cell_data(out_point).map(|(data, _)| data)
123    }
124
125    fn get_cell_data_hash(&self, out_point: &OutPoint) -> Option<Byte32> {
126        self.0.get_cell_data_hash(out_point)
127    }
128}
129
130impl<'a, T: ChainStore> HeaderProvider for BorrowedDataLoaderWrapper<'a, T> {
131    fn get_header(&self, block_hash: &Byte32) -> Option<HeaderView> {
132        self.0.get_block_header(block_hash)
133    }
134}
135
136impl<'a, T: ChainStore> EpochProvider for BorrowedDataLoaderWrapper<'a, T> {
137    fn get_epoch_ext(&self, header: &HeaderView) -> Option<EpochExt> {
138        ChainStore::get_block_epoch_index(self.0, &header.hash())
139            .and_then(|index| ChainStore::get_epoch_ext(self.0, &index))
140    }
141
142    fn get_block_hash(&self, number: BlockNumber) -> Option<Byte32> {
143        ChainStore::get_block_hash(self.0, number)
144    }
145
146    fn get_block_ext(&self, block_hash: &Byte32) -> Option<BlockExt> {
147        ChainStore::get_block_ext(self.0, block_hash)
148    }
149
150    fn get_block_header(&self, hash: &Byte32) -> Option<HeaderView> {
151        ChainStore::get_block_header(self.0, hash)
152    }
153}
154
155impl<'a, T: ChainStore> ExtensionProvider for BorrowedDataLoaderWrapper<'a, T> {
156    fn get_block_extension(&self, hash: &Byte32) -> Option<packed::Bytes> {
157        ChainStore::get_block_extension(self.0, hash)
158    }
159}