1use crate::cache::StoreCache;
2use crate::data_loader_wrapper::BorrowedDataLoaderWrapper;
3use ckb_db::{
4 iter::{DBIter, Direction, IteratorMode},
5 DBPinnableSlice,
6};
7use ckb_db_schema::{
8 Col, COLUMN_BLOCK_BODY, COLUMN_BLOCK_EPOCH, COLUMN_BLOCK_EXT, COLUMN_BLOCK_EXTENSION,
9 COLUMN_BLOCK_FILTER, COLUMN_BLOCK_FILTER_HASH, COLUMN_BLOCK_HEADER, COLUMN_BLOCK_PROPOSAL_IDS,
10 COLUMN_BLOCK_UNCLE, COLUMN_CELL, COLUMN_CELL_DATA, COLUMN_CELL_DATA_HASH,
11 COLUMN_CHAIN_ROOT_MMR, COLUMN_EPOCH, COLUMN_INDEX, COLUMN_META, COLUMN_TRANSACTION_INFO,
12 COLUMN_UNCLES, META_CURRENT_EPOCH_KEY, META_LATEST_BUILT_FILTER_DATA_KEY, META_TIP_HEADER_KEY,
13};
14use ckb_freezer::Freezer;
15use ckb_types::{
16 bytes::Bytes,
17 core::{
18 cell::CellMeta, BlockExt, BlockNumber, BlockView, EpochExt, EpochNumber, HeaderView,
19 TransactionInfo, TransactionView, UncleBlockVecView,
20 },
21 packed::{self, OutPoint},
22 prelude::*,
23};
24
25pub trait ChainStore: Send + Sync + Sized {
27 fn cache(&self) -> Option<&StoreCache>;
29 fn freezer(&self) -> Option<&Freezer>;
31 fn get(&self, col: Col, key: &[u8]) -> Option<DBPinnableSlice>;
33 fn get_iter(&self, col: Col, mode: IteratorMode) -> DBIter;
35 fn borrow_as_data_loader(&self) -> BorrowedDataLoaderWrapper<Self> {
37 BorrowedDataLoaderWrapper::new(self)
38 }
39
40 fn get_block(&self, h: &packed::Byte32) -> Option<BlockView> {
42 let header = self.get_block_header(h)?;
43 if let Some(freezer) = self.freezer() {
44 if header.number() > 0 && header.number() < freezer.number() {
45 let raw_block = freezer.retrieve(header.number()).expect("block frozen")?;
46 let raw_block = packed::BlockReader::from_compatible_slice(&raw_block)
47 .expect("checked data")
48 .to_entity();
49 return Some(raw_block.into_view());
50 }
51 }
52 let body = self.get_block_body(h);
53 let uncles = self
54 .get_block_uncles(h)
55 .expect("block uncles must be stored");
56 let proposals = self
57 .get_block_proposal_txs_ids(h)
58 .expect("block proposal_ids must be stored");
59 let extension_opt = self.get_block_extension(h);
60
61 let block = if let Some(extension) = extension_opt {
62 BlockView::new_unchecked_with_extension(header, uncles, body, proposals, extension)
63 } else {
64 BlockView::new_unchecked(header, uncles, body, proposals)
65 };
66 Some(block)
67 }
68
69 fn get_block_header(&self, hash: &packed::Byte32) -> Option<HeaderView> {
71 if let Some(cache) = self.cache() {
72 if let Some(header) = cache.headers.lock().get(hash) {
73 return Some(header.clone());
74 }
75 };
76 let ret = self.get(COLUMN_BLOCK_HEADER, hash.as_slice()).map(|slice| {
77 let reader = packed::HeaderViewReader::from_slice_should_be_ok(slice.as_ref());
78 Unpack::<HeaderView>::unpack(&reader)
79 });
80
81 if let Some(cache) = self.cache() {
82 ret.inspect(|header| {
83 cache.headers.lock().put(hash.clone(), header.clone());
84 })
85 } else {
86 ret
87 }
88 }
89
90 fn get_block_body(&self, hash: &packed::Byte32) -> Vec<TransactionView> {
92 let prefix = hash.as_slice();
93 self.get_iter(
94 COLUMN_BLOCK_BODY,
95 IteratorMode::From(prefix, Direction::Forward),
96 )
97 .take_while(|(key, _)| key.starts_with(prefix))
98 .map(|(_key, value)| {
99 let reader = packed::TransactionViewReader::from_slice_should_be_ok(value.as_ref());
100 Unpack::<TransactionView>::unpack(&reader)
101 })
102 .collect()
103 }
104
105 fn get_unfrozen_block(&self, hash: &packed::Byte32) -> Option<BlockView> {
107 let header = self
108 .get(COLUMN_BLOCK_HEADER, hash.as_slice())
109 .map(|slice| {
110 let reader = packed::HeaderViewReader::from_slice_should_be_ok(slice.as_ref());
111 Unpack::<HeaderView>::unpack(&reader)
112 })?;
113
114 let body = self.get_block_body(hash);
115
116 let uncles = self
117 .get(COLUMN_BLOCK_UNCLE, hash.as_slice())
118 .map(|slice| {
119 let reader =
120 packed::UncleBlockVecViewReader::from_slice_should_be_ok(slice.as_ref());
121 Unpack::<UncleBlockVecView>::unpack(&reader)
122 })
123 .expect("block uncles must be stored");
124
125 let proposals = self
126 .get(COLUMN_BLOCK_PROPOSAL_IDS, hash.as_slice())
127 .map(|slice| {
128 packed::ProposalShortIdVecReader::from_slice_should_be_ok(slice.as_ref())
129 .to_entity()
130 })
131 .expect("block proposal_ids must be stored");
132
133 let extension_opt = self
134 .get(COLUMN_BLOCK_EXTENSION, hash.as_slice())
135 .map(|slice| packed::BytesReader::from_slice_should_be_ok(slice.as_ref()).to_entity());
136
137 let block = if let Some(extension) = extension_opt {
138 BlockView::new_unchecked_with_extension(header, uncles, body, proposals, extension)
139 } else {
140 BlockView::new_unchecked(header, uncles, body, proposals)
141 };
142
143 Some(block)
144 }
145
146 fn get_block_txs_hashes(&self, hash: &packed::Byte32) -> Vec<packed::Byte32> {
148 if let Some(cache) = self.cache() {
149 if let Some(hashes) = cache.block_tx_hashes.lock().get(hash) {
150 return hashes.clone();
151 }
152 };
153
154 let prefix = hash.as_slice();
155 let ret: Vec<_> = self
156 .get_iter(
157 COLUMN_BLOCK_BODY,
158 IteratorMode::From(prefix, Direction::Forward),
159 )
160 .take_while(|(key, _)| key.starts_with(prefix))
161 .map(|(_key, value)| {
162 let reader = packed::TransactionViewReader::from_slice_should_be_ok(value.as_ref());
163 reader.hash().to_entity()
164 })
165 .collect();
166
167 if let Some(cache) = self.cache() {
168 cache.block_tx_hashes.lock().put(hash.clone(), ret.clone());
169 }
170
171 ret
172 }
173
174 fn get_block_proposal_txs_ids(
176 &self,
177 hash: &packed::Byte32,
178 ) -> Option<packed::ProposalShortIdVec> {
179 if let Some(cache) = self.cache() {
180 if let Some(data) = cache.block_proposals.lock().get(hash) {
181 return Some(data.clone());
182 }
183 };
184
185 let ret = self
186 .get(COLUMN_BLOCK_PROPOSAL_IDS, hash.as_slice())
187 .map(|slice| {
188 packed::ProposalShortIdVecReader::from_slice_should_be_ok(slice.as_ref())
189 .to_entity()
190 });
191
192 if let Some(cache) = self.cache() {
193 ret.inspect(|data| {
194 cache.block_proposals.lock().put(hash.clone(), data.clone());
195 })
196 } else {
197 ret
198 }
199 }
200
201 fn get_block_uncles(&self, hash: &packed::Byte32) -> Option<UncleBlockVecView> {
203 if let Some(cache) = self.cache() {
204 if let Some(data) = cache.block_uncles.lock().get(hash) {
205 return Some(data.clone());
206 }
207 };
208
209 let ret = self.get(COLUMN_BLOCK_UNCLE, hash.as_slice()).map(|slice| {
210 let reader = packed::UncleBlockVecViewReader::from_slice_should_be_ok(slice.as_ref());
211 Unpack::<UncleBlockVecView>::unpack(&reader)
212 });
213
214 if let Some(cache) = self.cache() {
215 ret.inspect(|uncles| {
216 cache.block_uncles.lock().put(hash.clone(), uncles.clone());
217 })
218 } else {
219 ret
220 }
221 }
222
223 fn get_block_extension(&self, hash: &packed::Byte32) -> Option<packed::Bytes> {
225 if let Some(cache) = self.cache() {
226 if let Some(data) = cache.block_extensions.lock().get(hash) {
227 return data.clone();
228 }
229 };
230
231 let ret = self
232 .get(COLUMN_BLOCK_EXTENSION, hash.as_slice())
233 .map(|slice| packed::BytesReader::from_slice_should_be_ok(slice.as_ref()).to_entity());
234
235 if let Some(cache) = self.cache() {
236 cache.block_extensions.lock().put(hash.clone(), ret.clone());
237 }
238 ret
239 }
240
241 fn get_block_ext(&self, block_hash: &packed::Byte32) -> Option<BlockExt> {
245 self.get(COLUMN_BLOCK_EXT, block_hash.as_slice())
246 .map(|slice| {
247 let reader =
248 packed::BlockExtReader::from_compatible_slice_should_be_ok(slice.as_ref());
249 match reader.count_extra_fields() {
250 0 => reader.unpack(),
251 2 => packed::BlockExtV1Reader::from_slice_should_be_ok(slice.as_ref()).unpack(),
252 _ => {
253 panic!(
254 "BlockExt storage field count doesn't match, expect 7 or 5, actual {}",
255 reader.field_count()
256 )
257 }
258 }
259 })
260 }
261
262 fn get_block_hash(&self, number: BlockNumber) -> Option<packed::Byte32> {
264 let block_number: packed::Uint64 = number.pack();
265 self.get(COLUMN_INDEX, block_number.as_slice())
266 .map(|raw| packed::Byte32Reader::from_slice_should_be_ok(raw.as_ref()).to_entity())
267 }
268
269 fn get_block_number(&self, hash: &packed::Byte32) -> Option<BlockNumber> {
271 self.get(COLUMN_INDEX, hash.as_slice())
272 .map(|raw| packed::Uint64Reader::from_slice_should_be_ok(raw.as_ref()).unpack())
273 }
274
275 fn is_main_chain(&self, hash: &packed::Byte32) -> bool {
277 self.get(COLUMN_INDEX, hash.as_slice()).is_some()
278 }
279
280 fn get_tip_header(&self) -> Option<HeaderView> {
282 self.get(COLUMN_META, META_TIP_HEADER_KEY)
283 .and_then(|raw| {
284 self.get_block_header(
285 &packed::Byte32Reader::from_slice_should_be_ok(raw.as_ref()).to_entity(),
286 )
287 })
288 .map(Into::into)
289 }
290
291 fn transaction_exists(&self, hash: &packed::Byte32) -> bool {
296 self.get(COLUMN_TRANSACTION_INFO, hash.as_slice()).is_some()
297 }
298
299 fn get_transaction(&self, hash: &packed::Byte32) -> Option<(TransactionView, packed::Byte32)> {
301 self.get_transaction_with_info(hash)
302 .map(|(tx, tx_info)| (tx, tx_info.block_hash))
303 }
304
305 fn get_transaction_info(&self, hash: &packed::Byte32) -> Option<TransactionInfo> {
307 self.get(COLUMN_TRANSACTION_INFO, hash.as_slice())
308 .map(|slice| {
309 let reader = packed::TransactionInfoReader::from_slice_should_be_ok(slice.as_ref());
310 Unpack::<TransactionInfo>::unpack(&reader)
311 })
312 }
313
314 fn get_transaction_with_info(
316 &self,
317 hash: &packed::Byte32,
318 ) -> Option<(TransactionView, TransactionInfo)> {
319 let tx_info = self.get_transaction_info(hash)?;
320 if let Some(freezer) = self.freezer() {
321 if tx_info.block_number > 0 && tx_info.block_number < freezer.number() {
322 let raw_block = freezer
323 .retrieve(tx_info.block_number)
324 .expect("block frozen")?;
325 let raw_block_reader =
326 packed::BlockReader::from_compatible_slice(&raw_block).expect("checked data");
327 let tx_reader = raw_block_reader.transactions().get(tx_info.index)?;
328 return Some((tx_reader.to_entity().into_view(), tx_info));
329 }
330 }
331 self.get(COLUMN_BLOCK_BODY, tx_info.key().as_slice())
332 .map(|slice| {
333 let reader = packed::TransactionViewReader::from_slice_should_be_ok(slice.as_ref());
334 (reader.unpack(), tx_info)
335 })
336 }
337
338 fn have_cell(&self, out_point: &OutPoint) -> bool {
340 let key = out_point.to_cell_key();
341 self.get(COLUMN_CELL, &key).is_some()
342 }
343
344 fn get_cell(&self, out_point: &OutPoint) -> Option<CellMeta> {
346 let key = out_point.to_cell_key();
347 self.get(COLUMN_CELL, &key).map(|slice| {
348 let reader = packed::CellEntryReader::from_slice_should_be_ok(slice.as_ref());
349 build_cell_meta_from_reader(out_point.clone(), reader)
350 })
351 }
352
353 fn get_cell_data(&self, out_point: &OutPoint) -> Option<(Bytes, packed::Byte32)> {
355 let key = out_point.to_cell_key();
356 if let Some(cache) = self.cache() {
357 if let Some(cached) = cache.cell_data.lock().get(&key) {
358 return Some(cached.clone());
359 }
360 };
361
362 let ret = self.get(COLUMN_CELL_DATA, &key).map(|slice| {
363 if !slice.as_ref().is_empty() {
364 let reader = packed::CellDataEntryReader::from_slice_should_be_ok(slice.as_ref());
365 let data = reader.output_data().unpack();
366 let data_hash = reader.output_data_hash().to_entity();
367 (data, data_hash)
368 } else {
369 (Bytes::new(), packed::Byte32::zero())
370 }
371 });
372
373 if let Some(cache) = self.cache() {
374 ret.inspect(|cached| {
375 cache.cell_data.lock().put(key, cached.clone());
376 })
377 } else {
378 ret
379 }
380 }
381
382 fn get_cell_data_hash(&self, out_point: &OutPoint) -> Option<packed::Byte32> {
384 let key = out_point.to_cell_key();
385 if let Some(cache) = self.cache() {
386 if let Some(cached) = cache.cell_data_hash.lock().get(&key) {
387 return Some(cached.clone());
388 }
389 };
390
391 let ret = self.get(COLUMN_CELL_DATA_HASH, &key).map(|raw| {
392 if !raw.as_ref().is_empty() {
393 packed::Byte32Reader::from_slice_should_be_ok(raw.as_ref()).to_entity()
394 } else {
395 packed::Byte32::zero()
396 }
397 });
398
399 if let Some(cache) = self.cache() {
400 ret.inspect(|cached| {
401 cache.cell_data_hash.lock().put(key, cached.clone());
402 })
403 } else {
404 ret
405 }
406 }
407
408 fn get_current_epoch_ext(&self) -> Option<EpochExt> {
410 self.get(COLUMN_META, META_CURRENT_EPOCH_KEY)
411 .map(|slice| packed::EpochExtReader::from_slice_should_be_ok(slice.as_ref()).unpack())
412 }
413
414 fn get_epoch_ext(&self, hash: &packed::Byte32) -> Option<EpochExt> {
416 self.get(COLUMN_EPOCH, hash.as_slice())
417 .map(|slice| packed::EpochExtReader::from_slice_should_be_ok(slice.as_ref()).unpack())
418 }
419
420 fn get_epoch_index(&self, number: EpochNumber) -> Option<packed::Byte32> {
422 let epoch_number: packed::Uint64 = number.pack();
423 self.get(COLUMN_EPOCH, epoch_number.as_slice())
424 .map(|raw| packed::Byte32Reader::from_slice_should_be_ok(raw.as_ref()).to_entity())
425 }
426
427 fn get_block_epoch_index(&self, block_hash: &packed::Byte32) -> Option<packed::Byte32> {
429 self.get(COLUMN_BLOCK_EPOCH, block_hash.as_slice())
430 .map(|raw| packed::Byte32Reader::from_slice_should_be_ok(raw.as_ref()).to_entity())
431 }
432
433 fn get_block_epoch(&self, hash: &packed::Byte32) -> Option<EpochExt> {
435 self.get_block_epoch_index(hash)
436 .and_then(|index| self.get_epoch_ext(&index))
437 }
438
439 fn is_uncle(&self, hash: &packed::Byte32) -> bool {
441 self.get(COLUMN_UNCLES, hash.as_slice()).is_some()
442 }
443
444 fn get_uncle_header(&self, hash: &packed::Byte32) -> Option<HeaderView> {
446 self.get(COLUMN_UNCLES, hash.as_slice()).map(|slice| {
447 let reader = packed::HeaderViewReader::from_slice_should_be_ok(slice.as_ref());
448 Unpack::<HeaderView>::unpack(&reader)
449 })
450 }
451
452 fn block_exists(&self, hash: &packed::Byte32) -> bool {
454 if let Some(cache) = self.cache() {
455 if cache.headers.lock().get(hash).is_some() {
456 return true;
457 }
458 };
459 self.get(COLUMN_BLOCK_HEADER, hash.as_slice()).is_some()
460 }
461
462 fn get_cellbase(&self, hash: &packed::Byte32) -> Option<TransactionView> {
464 let key = packed::TransactionKey::new_builder()
465 .block_hash(hash.to_owned())
466 .build();
467 self.get(COLUMN_BLOCK_BODY, key.as_slice()).map(|slice| {
468 let reader = packed::TransactionViewReader::from_slice_should_be_ok(slice.as_ref());
469 Unpack::<TransactionView>::unpack(&reader)
470 })
471 }
472
473 fn get_latest_built_filter_data_block_hash(&self) -> Option<packed::Byte32> {
475 self.get(COLUMN_META, META_LATEST_BUILT_FILTER_DATA_KEY)
476 .map(|raw| packed::Byte32Reader::from_slice_should_be_ok(raw.as_ref()).to_entity())
477 }
478
479 fn get_block_filter(&self, hash: &packed::Byte32) -> Option<packed::Bytes> {
481 self.get(COLUMN_BLOCK_FILTER, hash.as_slice())
482 .map(|slice| packed::BytesReader::from_slice_should_be_ok(slice.as_ref()).to_entity())
483 }
484
485 fn get_block_filter_hash(&self, hash: &packed::Byte32) -> Option<packed::Byte32> {
487 self.get(COLUMN_BLOCK_FILTER_HASH, hash.as_slice())
488 .map(|slice| packed::Byte32Reader::from_slice_should_be_ok(slice.as_ref()).to_entity())
489 }
490
491 fn get_packed_block(&self, hash: &packed::Byte32) -> Option<packed::Block> {
493 let header = self
494 .get(COLUMN_BLOCK_HEADER, hash.as_slice())
495 .map(|slice| {
496 let reader = packed::HeaderViewReader::from_slice_should_be_ok(slice.as_ref());
497 reader.data().to_entity()
498 })?;
499
500 let prefix = hash.as_slice();
501 let transactions: packed::TransactionVec = self
502 .get_iter(
503 COLUMN_BLOCK_BODY,
504 IteratorMode::From(prefix, Direction::Forward),
505 )
506 .take_while(|(key, _)| key.starts_with(prefix))
507 .map(|(_key, value)| {
508 let reader = packed::TransactionViewReader::from_slice_should_be_ok(value.as_ref());
509 reader.data().to_entity()
510 })
511 .pack();
512
513 let uncles = self.get_block_uncles(hash)?;
514 let proposals = self.get_block_proposal_txs_ids(hash)?;
515 let extension_opt = self.get_block_extension(hash);
516
517 let block = if let Some(extension) = extension_opt {
518 packed::BlockV1::new_builder()
519 .header(header)
520 .uncles(uncles.data())
521 .transactions(transactions)
522 .proposals(proposals)
523 .extension(extension)
524 .build()
525 .as_v0()
526 } else {
527 packed::Block::new_builder()
528 .header(header)
529 .uncles(uncles.data())
530 .transactions(transactions)
531 .proposals(proposals)
532 .build()
533 };
534
535 Some(block)
536 }
537
538 fn get_packed_block_header(&self, hash: &packed::Byte32) -> Option<packed::Header> {
540 self.get(COLUMN_BLOCK_HEADER, hash.as_slice()).map(|slice| {
541 let reader = packed::HeaderViewReader::from_slice_should_be_ok(slice.as_ref());
542 reader.data().to_entity()
543 })
544 }
545
546 fn get_header_digest(&self, position_u64: u64) -> Option<packed::HeaderDigest> {
548 let position: packed::Uint64 = position_u64.pack();
549 self.get(COLUMN_CHAIN_ROOT_MMR, position.as_slice())
550 .map(|slice| {
551 let reader = packed::HeaderDigestReader::from_slice_should_be_ok(slice.as_ref());
552 reader.to_entity()
553 })
554 }
555
556 fn get_ancestor(&self, base: &packed::Byte32, number: BlockNumber) -> Option<HeaderView> {
558 let header = self.get_block_header(base)?;
559 if number > header.number() {
560 None
561 } else if number == header.number() {
562 Some(header)
563 } else if self.is_main_chain(base) {
564 self.get_block_hash(number)
565 .and_then(|hash| self.get_block_header(&hash))
566 } else {
567 self.get_ancestor(&header.parent_hash(), number)
568 }
569 }
570}
571
572fn build_cell_meta_from_reader(out_point: OutPoint, reader: packed::CellEntryReader) -> CellMeta {
573 CellMeta {
574 out_point,
575 cell_output: reader.output().to_entity(),
576 transaction_info: Some(TransactionInfo {
577 block_number: reader.block_number().unpack(),
578 block_hash: reader.block_hash().to_entity(),
579 block_epoch: reader.block_epoch().unpack(),
580 index: reader.index().unpack(),
581 }),
582 data_bytes: reader.data_size().unpack(),
583 mem_cell_data: None,
584 mem_cell_data_hash: None,
585 }
586}