1use std::{collections::HashMap, fmt::Debug, hash::Hash};
14
15use committable::{Commitment, Committable};
16use hotshot_types::{
17 data::{Leaf, Leaf2, VidCommitment, VidCommon, VidShare},
18 simple_certificate::QuorumCertificate2,
19 traits::{
20 self, EncodeBytes,
21 block_contents::{BlockHeader, GENESIS_VID_NUM_STORAGE_NODES},
22 node_implementation::NodeType,
23 },
24 vid::advz::{ADVZCommitment, ADVZCommon, advz_scheme},
25};
26use jf_advz::VidScheme;
27use serde::{Deserialize, Serialize, de::DeserializeOwned};
28use snafu::{Snafu, ensure};
29use vbs::version::Version;
30use versions::Upgrade;
31
32use crate::{Header, Metadata, Payload, QuorumCertificate, Transaction, types::HeightIndexed};
33
34pub type LeafHash<Types> = Commitment<Leaf2<Types>>;
35pub type LeafHashLegacy<Types> = Commitment<Leaf<Types>>;
36pub type QcHash<Types> = Commitment<QuorumCertificate2<Types>>;
37
38pub type BlockHash<Types> = Commitment<Header<Types>>;
43pub type TransactionHash<Types> = Commitment<Transaction<Types>>;
44pub type TransactionInclusionProof<Types> =
45 <Payload<Types> as QueryablePayload<Types>>::InclusionProof;
46pub type NamespaceIndex<Types> = <Header<Types> as QueryableHeader<Types>>::NamespaceIndex;
47pub type NamespaceId<Types> = <Header<Types> as QueryableHeader<Types>>::NamespaceId;
48
49pub type Timestamp = time::OffsetDateTime;
50
51pub trait QueryableHeader<Types: NodeType>: BlockHeader<Types> + HeightIndexed {
52 type NamespaceIndex: Clone + Debug + Hash + PartialEq + Eq + From<i64> + Into<i64> + Send + Sync;
54
55 type NamespaceId: Clone
57 + Debug
58 + Serialize
59 + DeserializeOwned
60 + Send
61 + Sync
62 + Hash
63 + PartialEq
64 + Eq
65 + Copy
66 + From<i64>
67 + Into<i64>;
68
69 fn namespace_id(&self, i: &Self::NamespaceIndex) -> Option<Self::NamespaceId>;
71
72 fn namespace_size(&self, i: &Self::NamespaceIndex, payload_size: usize) -> u64;
74
75 fn ns_table(&self) -> String;
77}
78
79#[derive(Clone, Debug, PartialEq, Eq)]
80pub struct TransactionIndex<Types: NodeType>
81where
82 Header<Types>: QueryableHeader<Types>,
83{
84 pub ns_index: NamespaceIndex<Types>,
86 pub position: u32,
88}
89
90pub trait VerifiableInclusion<Types: NodeType>:
97 Clone + Debug + PartialEq + Eq + Serialize + DeserializeOwned + Send + Sync
98{
99 fn verify(
102 &self,
103 metadata: &Metadata<Types>,
104 tx: &Transaction<Types>,
105 payload_commitment: &VidCommitment,
106 common: &VidCommon,
107 ) -> bool;
108}
109
110pub trait QueryablePayload<Types: NodeType>: traits::BlockPayload<Types>
119where
120 Header<Types>: QueryableHeader<Types>,
121{
122 type Iter<'a>: Iterator<Item = TransactionIndex<Types>>
124 where
125 Self: 'a;
126
127 type InclusionProof: VerifiableInclusion<Types>;
129
130 fn len(&self, meta: &Self::Metadata) -> usize;
132
133 fn is_empty(&self, meta: &Self::Metadata) -> bool {
135 self.len(meta) == 0
136 }
137
138 fn iter<'a>(&'a self, meta: &'a Self::Metadata) -> Self::Iter<'a>;
140
141 fn enumerate<'a>(
143 &'a self,
144 meta: &'a Self::Metadata,
145 ) -> Box<dyn 'a + Iterator<Item = (TransactionIndex<Types>, Self::Transaction)>> {
146 Box::new(self.iter(meta).map(|ix| {
147 let tx = self.transaction(meta, &ix).unwrap();
150 (ix, tx)
151 }))
152 }
153
154 fn transaction(
156 &self,
157 meta: &Self::Metadata,
158 index: &TransactionIndex<Types>,
159 ) -> Option<Self::Transaction>;
160
161 fn transaction_proof(
165 &self,
166 meta: &Self::Metadata,
167 vid: &VidCommonQueryData<Types>,
168 index: &TransactionIndex<Types>,
169 ) -> Option<Self::InclusionProof>;
170
171 fn nth(&self, meta: &Self::Metadata, n: usize) -> Option<TransactionIndex<Types>> {
173 self.iter(meta).nth(n)
174 }
175
176 fn nth_transaction(&self, meta: &Self::Metadata, n: usize) -> Option<Self::Transaction> {
178 self.transaction(meta, &self.nth(meta, n)?)
179 }
180
181 fn by_hash(
183 &self,
184 meta: &Self::Metadata,
185 hash: Commitment<Self::Transaction>,
186 ) -> Option<TransactionIndex<Types>> {
187 self.iter(meta).find(|i| {
188 if let Some(tx) = self.transaction(meta, i) {
189 tx.commit() == hash
190 } else {
191 false
192 }
193 })
194 }
195
196 fn transaction_by_hash(
198 &self,
199 meta: &Self::Metadata,
200 hash: Commitment<Self::Transaction>,
201 ) -> Option<Self::Transaction> {
202 self.transaction(meta, &self.by_hash(meta, hash)?)
203 }
204}
205
206#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
207#[serde(bound = "")]
208#[serde(try_from = "LeafQueryDataRaw<Types>", into = "LeafQueryDataRaw<Types>")]
210pub struct LeafQueryData<Types: NodeType> {
211 pub(crate) leaf: Leaf2<Types>,
212 pub(crate) qc: QuorumCertificate2<Types>,
213}
214
215impl<Types: NodeType> AsRef<Header<Types>> for LeafQueryData<Types> {
216 fn as_ref(&self) -> &Header<Types> {
217 self.leaf.block_header()
218 }
219}
220
221#[derive(Deserialize, Serialize)]
231#[serde(bound = "")]
232struct LeafQueryDataRaw<Types: NodeType> {
233 leaf: Leaf2<Types>,
234 qc: QuorumCertificate2<Types>,
235}
236
237impl<Types: NodeType> From<LeafQueryData<Types>> for LeafQueryDataRaw<Types> {
238 fn from(value: LeafQueryData<Types>) -> Self {
239 Self {
240 leaf: value.leaf,
241 qc: value.qc,
242 }
243 }
244}
245
246impl<Types: NodeType> TryFrom<LeafQueryDataRaw<Types>> for LeafQueryData<Types> {
247 type Error = InconsistentLeafError<Types>;
248
249 fn try_from(value: LeafQueryDataRaw<Types>) -> Result<Self, Self::Error> {
250 Self::new(value.leaf, value.qc)
251 }
252}
253
254#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
255#[serde(bound = "")]
256pub struct LeafQueryDataLegacy<Types: NodeType> {
257 pub(crate) leaf: Leaf<Types>,
258 pub(crate) qc: QuorumCertificate<Types>,
259}
260
261impl<Types: NodeType> From<LeafQueryDataLegacy<Types>> for LeafQueryData<Types> {
262 fn from(legacy: LeafQueryDataLegacy<Types>) -> Self {
263 Self {
264 leaf: legacy.leaf.into(),
265 qc: legacy.qc.to_qc2(),
266 }
267 }
268}
269
270#[derive(Clone, Debug, Snafu)]
271#[snafu(display("QC references leaf {qc_leaf}, but expected {leaf}"))]
272pub struct InconsistentLeafError<Types: NodeType> {
273 pub leaf: LeafHash<Types>,
274 pub qc_leaf: LeafHash<Types>,
275}
276
277#[derive(Clone, Debug, Snafu)]
278#[snafu(display("QC references leaf {qc_leaf}, but expected {leaf}"))]
279pub struct InconsistentLeafLegacyError<Types: NodeType> {
280 pub leaf: LeafHashLegacy<Types>,
281 pub qc_leaf: LeafHashLegacy<Types>,
282}
283
284impl<Types: NodeType> LeafQueryDataLegacy<Types> {
285 pub fn new(
293 mut leaf: Leaf<Types>,
294 qc: QuorumCertificate<Types>,
295 ) -> Result<Self, InconsistentLeafLegacyError<Types>> {
296 let leaf_commit = <Leaf<Types> as Committable>::commit(&leaf);
300 ensure!(
301 qc.data.leaf_commit == leaf_commit,
302 InconsistentLeafLegacySnafu {
303 leaf: leaf_commit,
304 qc_leaf: qc.data.leaf_commit
305 }
306 );
307
308 leaf.unfill_block_payload();
311
312 Ok(Self { leaf, qc })
313 }
314
315 pub async fn genesis(
316 validated_state: &Types::ValidatedState,
317 instance_state: &Types::InstanceState,
318 upgrade: Upgrade,
319 ) -> Self {
320 Self {
321 leaf: Leaf::genesis(validated_state, instance_state, upgrade.base).await,
322 qc: QuorumCertificate::genesis(validated_state, instance_state, upgrade).await,
323 }
324 }
325
326 pub fn leaf(&self) -> &Leaf<Types> {
327 &self.leaf
328 }
329
330 pub fn qc(&self) -> &QuorumCertificate<Types> {
331 &self.qc
332 }
333
334 pub fn header(&self) -> &Header<Types> {
335 self.leaf.block_header()
336 }
337
338 pub fn hash(&self) -> LeafHashLegacy<Types> {
339 <Leaf<Types> as Committable>::commit(&self.leaf)
343 }
344
345 pub fn block_hash(&self) -> BlockHash<Types> {
346 self.header().commit()
347 }
348
349 pub fn payload_hash(&self) -> VidCommitment {
350 self.header().payload_commitment()
351 }
352}
353
354impl<Types: NodeType> LeafQueryData<Types> {
355 pub fn new(
363 mut leaf: Leaf2<Types>,
364 qc: QuorumCertificate2<Types>,
365 ) -> Result<Self, InconsistentLeafError<Types>> {
366 let leaf_commit = <Leaf2<Types> as Committable>::commit(&leaf);
370 ensure!(
371 qc.data.leaf_commit == leaf_commit,
372 InconsistentLeafSnafu {
373 leaf: leaf_commit,
374 qc_leaf: qc.data.leaf_commit
375 }
376 );
377
378 leaf.unfill_block_payload();
381
382 Ok(Self { leaf, qc })
383 }
384
385 pub async fn genesis(
386 validated_state: &Types::ValidatedState,
387 instance_state: &Types::InstanceState,
388 upgrade: Upgrade,
389 ) -> Self {
390 Self {
391 leaf: Leaf2::genesis(validated_state, instance_state, upgrade.base).await,
392 qc: QuorumCertificate2::genesis(validated_state, instance_state, upgrade).await,
393 }
394 }
395
396 pub fn leaf(&self) -> &Leaf2<Types> {
397 &self.leaf
398 }
399
400 pub fn qc(&self) -> &QuorumCertificate2<Types> {
401 &self.qc
402 }
403
404 pub fn header(&self) -> &Header<Types> {
405 self.leaf.block_header()
406 }
407
408 pub fn hash(&self) -> LeafHash<Types> {
409 <Leaf2<Types> as Committable>::commit(&self.leaf)
413 }
414
415 pub fn block_hash(&self) -> BlockHash<Types> {
416 self.header().commit()
417 }
418
419 pub fn payload_hash(&self) -> VidCommitment {
420 self.header().payload_commitment()
421 }
422}
423
424impl<Types: NodeType> HeightIndexed for LeafQueryData<Types> {
425 fn height(&self) -> u64 {
426 self.header().block_number()
427 }
428}
429
430impl<Types: NodeType> HeightIndexed for LeafQueryDataLegacy<Types> {
431 fn height(&self) -> u64 {
432 self.header().block_number()
433 }
434}
435
436#[derive(Clone, Debug, Serialize, serde::Deserialize, PartialEq, Eq)]
437#[serde(bound = "")]
438pub struct HeaderQueryData<Types: NodeType> {
439 pub header: Header<Types>,
440}
441
442impl<Types: NodeType> HeaderQueryData<Types> {
443 pub fn new(header: Header<Types>) -> Self {
444 Self { header }
445 }
446
447 pub fn header(&self) -> &Header<Types> {
448 &self.header
449 }
450}
451
452#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
453#[serde(bound = "")]
454pub struct BlockQueryData<Types: NodeType> {
455 pub(crate) header: Header<Types>,
456 pub(crate) payload: Payload<Types>,
457 pub(crate) hash: BlockHash<Types>,
458 pub(crate) size: u64,
459 pub(crate) num_transactions: u64,
460}
461
462impl<Types: NodeType> BlockQueryData<Types> {
463 pub fn new(header: Header<Types>, payload: Payload<Types>) -> Self
464 where
465 Header<Types>: QueryableHeader<Types>,
466 Payload<Types>: QueryablePayload<Types>,
467 {
468 Self {
469 hash: header.commit(),
470 size: payload_size::<Types>(&payload),
471 num_transactions: payload.len(header.metadata()) as u64,
472 header,
473 payload,
474 }
475 }
476
477 pub async fn genesis(
478 validated_state: &Types::ValidatedState,
479 instance_state: &Types::InstanceState,
480 base: Version,
481 ) -> Self
482 where
483 Header<Types>: QueryableHeader<Types>,
484 Payload<Types>: QueryablePayload<Types>,
485 {
486 let leaf = Leaf2::<Types>::genesis(validated_state, instance_state, base).await;
487 Self::new(leaf.block_header().clone(), leaf.block_payload().unwrap())
488 }
489
490 pub fn header(&self) -> &Header<Types> {
491 &self.header
492 }
493
494 pub fn metadata(&self) -> &Metadata<Types> {
495 self.header.metadata()
496 }
497
498 pub fn payload_hash(&self) -> VidCommitment {
499 self.header.payload_commitment()
500 }
501
502 pub fn payload(&self) -> &Payload<Types> {
503 &self.payload
504 }
505
506 pub fn hash(&self) -> BlockHash<Types> {
507 self.hash
508 }
509
510 pub fn size(&self) -> u64 {
511 self.size
512 }
513
514 pub fn num_transactions(&self) -> u64 {
515 self.num_transactions
516 }
517
518 pub fn namespace_info(&self) -> NamespaceMap<Types>
519 where
520 Header<Types>: QueryableHeader<Types>,
521 Payload<Types>: QueryablePayload<Types>,
522 {
523 let mut map = NamespaceMap::<Types>::new();
524 for tx in self.payload.iter(self.header.metadata()) {
525 let Some(ns_id) = self.header.namespace_id(&tx.ns_index) else {
526 continue;
527 };
528 map.entry(ns_id)
529 .or_insert_with(|| NamespaceInfo {
530 num_transactions: 0,
531 size: self.header.namespace_size(&tx.ns_index, self.size as usize),
532 })
533 .num_transactions += 1;
534 }
535 map
536 }
537}
538
539impl<Types: NodeType> BlockQueryData<Types>
540where
541 Header<Types>: QueryableHeader<Types>,
542 Payload<Types>: QueryablePayload<Types>,
543{
544 pub fn transaction(&self, ix: &TransactionIndex<Types>) -> Option<Transaction<Types>> {
545 self.payload().transaction(self.metadata(), ix)
546 }
547
548 pub fn transaction_by_hash(
549 &self,
550 hash: Commitment<Transaction<Types>>,
551 ) -> Option<TransactionIndex<Types>> {
552 self.payload().by_hash(self.metadata(), hash)
553 }
554
555 pub fn transaction_proof(
556 &self,
557 vid_common: &VidCommonQueryData<Types>,
558 ix: &TransactionIndex<Types>,
559 ) -> Option<TransactionInclusionProof<Types>> {
560 self.payload()
561 .transaction_proof(self.metadata(), vid_common, ix)
562 }
563
564 pub fn len(&self) -> usize {
565 self.payload.len(self.metadata())
566 }
567
568 pub fn is_empty(&self) -> bool {
569 self.len() == 0
570 }
571
572 pub fn enumerate(
573 &self,
574 ) -> impl '_ + Iterator<Item = (TransactionIndex<Types>, Transaction<Types>)> {
575 self.payload.enumerate(self.metadata())
576 }
577}
578
579impl<Types: NodeType> HeightIndexed for BlockQueryData<Types> {
580 fn height(&self) -> u64 {
581 self.header.block_number()
582 }
583}
584
585#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
586#[serde(bound = "")]
587pub struct ADVZPayloadQueryData<Types: NodeType> {
588 pub(crate) height: u64,
589 pub(crate) block_hash: BlockHash<Types>,
590 pub(crate) hash: ADVZCommitment,
591 pub(crate) size: u64,
592 pub(crate) data: Payload<Types>,
593}
594
595#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
596#[serde(bound = "")]
597pub struct PayloadQueryData<Types: NodeType> {
598 pub(crate) height: u64,
599 pub(crate) block_hash: BlockHash<Types>,
600 pub(crate) hash: VidCommitment,
601 pub(crate) size: u64,
602 pub(crate) data: Payload<Types>,
603}
604
605impl<Types: NodeType> From<BlockQueryData<Types>> for PayloadQueryData<Types> {
606 fn from(block: BlockQueryData<Types>) -> Self {
607 Self {
608 height: block.height(),
609 block_hash: block.hash(),
610 hash: block.header.payload_commitment(),
611 size: block.size(),
612 data: block.payload,
613 }
614 }
615}
616
617impl<Types: NodeType> PayloadQueryData<Types> {
618 pub fn to_legacy(&self) -> Option<ADVZPayloadQueryData<Types>> {
619 let VidCommitment::V0(advz_commit) = self.hash else {
620 return None;
621 };
622
623 Some(ADVZPayloadQueryData {
624 height: self.height,
625 block_hash: self.block_hash,
626 hash: advz_commit,
627 size: self.size,
628 data: self.data.clone(),
629 })
630 }
631
632 pub async fn genesis(
633 validated_state: &Types::ValidatedState,
634 instance_state: &Types::InstanceState,
635 base: Version,
636 ) -> Self
637 where
638 Header<Types>: QueryableHeader<Types>,
639 Payload<Types>: QueryablePayload<Types>,
640 {
641 BlockQueryData::genesis(validated_state, instance_state, base)
642 .await
643 .into()
644 }
645
646 pub fn hash(&self) -> VidCommitment {
647 self.hash
648 }
649
650 pub fn block_hash(&self) -> BlockHash<Types> {
651 self.block_hash
652 }
653
654 pub fn size(&self) -> u64 {
655 self.size
656 }
657
658 pub fn data(&self) -> &Payload<Types> {
659 &self.data
660 }
661}
662
663impl<Types: NodeType> HeightIndexed for PayloadQueryData<Types> {
664 fn height(&self) -> u64 {
665 self.height
666 }
667}
668
669#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
671#[serde(bound = "")]
672pub struct ADVZCommonQueryData<Types: NodeType> {
673 pub(crate) height: u64,
674 pub(crate) block_hash: BlockHash<Types>,
675 pub(crate) payload_hash: ADVZCommitment,
676 pub(crate) common: ADVZCommon,
677}
678
679impl<Types: NodeType> ADVZCommonQueryData<Types> {
680 pub fn new(header: Header<Types>, common: ADVZCommon) -> anyhow::Result<Self> {
681 let VidCommitment::V0(payload_hash) = header.payload_commitment() else {
682 return Err(anyhow::anyhow!("Inconsistent header type."));
683 };
684 Ok(Self {
685 height: header.block_number(),
686 block_hash: header.commit(),
687 payload_hash,
688 common,
689 })
690 }
691
692 pub async fn genesis(
693 validated_state: &Types::ValidatedState,
694 instance_state: &Types::InstanceState,
695 base: Version,
696 ) -> anyhow::Result<Self> {
697 let leaf = Leaf::<Types>::genesis(validated_state, instance_state, base).await;
698 let payload = leaf.block_payload().unwrap();
699 let bytes = payload.encode();
700 let disperse = advz_scheme(GENESIS_VID_NUM_STORAGE_NODES)
701 .disperse(bytes)
702 .unwrap();
703
704 Self::new(leaf.block_header().clone(), disperse.common)
705 }
706
707 pub fn block_hash(&self) -> BlockHash<Types> {
708 self.block_hash
709 }
710
711 pub fn payload_hash(&self) -> ADVZCommitment {
712 self.payload_hash
713 }
714
715 pub fn common(&self) -> &ADVZCommon {
716 &self.common
717 }
718}
719
720impl<Types: NodeType> HeightIndexed for ADVZCommonQueryData<Types> {
721 fn height(&self) -> u64 {
722 self.height
723 }
724}
725
726impl<Types: NodeType> HeightIndexed for (ADVZCommonQueryData<Types>, Option<VidShare>) {
727 fn height(&self) -> u64 {
728 self.0.height
729 }
730}
731
732#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
733#[serde(bound = "")]
734pub struct VidCommonQueryData<Types: NodeType> {
735 pub(crate) height: u64,
736 pub(crate) block_hash: BlockHash<Types>,
737 pub(crate) payload_hash: VidCommitment,
738 pub(crate) common: VidCommon,
739}
740
741impl<Types: NodeType> VidCommonQueryData<Types> {
742 pub fn new(header: Header<Types>, common: VidCommon) -> Self {
743 Self {
744 height: header.block_number(),
745 block_hash: header.commit(),
746 payload_hash: header.payload_commitment(),
747 common,
748 }
749 }
750
751 pub async fn genesis(
752 validated_state: &Types::ValidatedState,
753 instance_state: &Types::InstanceState,
754 base: Version,
755 ) -> Self {
756 let leaf = Leaf::<Types>::genesis(validated_state, instance_state, base).await;
757 let payload = leaf.block_payload().unwrap();
758 let bytes = payload.encode();
759 let disperse = advz_scheme(GENESIS_VID_NUM_STORAGE_NODES)
760 .disperse(bytes)
761 .unwrap();
762
763 Self::new(leaf.block_header().clone(), VidCommon::V0(disperse.common))
764 }
765
766 pub fn block_hash(&self) -> BlockHash<Types> {
767 self.block_hash
768 }
769
770 pub fn payload_hash(&self) -> VidCommitment {
771 self.payload_hash
772 }
773
774 pub fn common(&self) -> &VidCommon {
775 &self.common
776 }
777}
778
779impl<Types: NodeType> HeightIndexed for VidCommonQueryData<Types> {
780 fn height(&self) -> u64 {
781 self.height
782 }
783}
784
785impl<Types: NodeType> HeightIndexed for (VidCommonQueryData<Types>, Option<VidShare>) {
786 fn height(&self) -> u64 {
787 self.0.height
788 }
789}
790
791#[derive(Clone, Debug, PartialEq, Eq)]
792pub struct BlockWithTransaction<Types: NodeType>
793where
794 Header<Types>: QueryableHeader<Types>,
795 Payload<Types>: QueryablePayload<Types>,
796{
797 pub block: BlockQueryData<Types>,
798 pub transaction: TransactionQueryData<Types>,
799 pub index: TransactionIndex<Types>,
800}
801
802impl<Types: NodeType> BlockWithTransaction<Types>
803where
804 Header<Types>: QueryableHeader<Types>,
805 Payload<Types>: QueryablePayload<Types>,
806{
807 pub fn with_hash(block: BlockQueryData<Types>, hash: TransactionHash<Types>) -> Option<Self> {
808 let (tx, i, index) = block.enumerate().enumerate().find_map(|(i, (index, tx))| {
809 if tx.commit() == hash {
810 Some((tx, i as u64, index))
811 } else {
812 None
813 }
814 })?;
815 let transaction = TransactionQueryData::new(tx, &block, &index, i)?;
816
817 Some(BlockWithTransaction {
818 block,
819 transaction,
820 index,
821 })
822 }
823}
824
825#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
826#[serde(bound = "")]
827pub struct TransactionQueryData<Types: NodeType>
828where
829 Header<Types>: QueryableHeader<Types>,
830 Payload<Types>: QueryablePayload<Types>,
831{
832 transaction: Transaction<Types>,
833 hash: TransactionHash<Types>,
834 index: u64,
835 block_hash: BlockHash<Types>,
836 block_height: u64,
837 namespace: NamespaceId<Types>,
838 pos_in_namespace: u32,
839}
840
841#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
842#[serde(bound = "")]
843pub struct TransactionWithProofQueryData<Types: NodeType>
844where
845 Header<Types>: QueryableHeader<Types>,
846 Payload<Types>: QueryablePayload<Types>,
847{
848 transaction: Transaction<Types>,
856 hash: TransactionHash<Types>,
857 index: u64,
858 proof: TransactionInclusionProof<Types>,
859 block_hash: BlockHash<Types>,
860 block_height: u64,
861 namespace: NamespaceId<Types>,
862 pos_in_namespace: u32,
863}
864
865impl<Types: NodeType> TransactionQueryData<Types>
866where
867 Header<Types>: QueryableHeader<Types>,
868 Payload<Types>: QueryablePayload<Types>,
869{
870 pub fn new(
871 transaction: Transaction<Types>,
872 block: &BlockQueryData<Types>,
873 i: &TransactionIndex<Types>,
874 index: u64,
875 ) -> Option<Self> {
876 Some(Self {
877 hash: transaction.commit(),
878 transaction,
879 index,
880 block_hash: block.hash(),
881 block_height: block.height(),
882 namespace: block.header().namespace_id(&i.ns_index)?,
883 pos_in_namespace: i.position,
884 })
885 }
886
887 pub fn transaction(&self) -> &Transaction<Types> {
889 &self.transaction
890 }
891
892 pub fn hash(&self) -> TransactionHash<Types> {
894 self.hash
895 }
896
897 pub fn index(&self) -> u64 {
899 self.index
900 }
901
902 pub fn block_height(&self) -> u64 {
904 self.block_height
905 }
906
907 pub fn block_hash(&self) -> BlockHash<Types> {
909 self.block_hash
910 }
911}
912
913impl<Types: NodeType> TransactionWithProofQueryData<Types>
914where
915 Header<Types>: QueryableHeader<Types>,
916 Payload<Types>: QueryablePayload<Types>,
917{
918 pub fn new(data: TransactionQueryData<Types>, proof: TransactionInclusionProof<Types>) -> Self {
919 Self {
920 proof,
921 transaction: data.transaction,
922 hash: data.hash,
923 index: data.index,
924 block_hash: data.block_hash,
925 block_height: data.block_height,
926 namespace: data.namespace,
927 pos_in_namespace: data.pos_in_namespace,
928 }
929 }
930
931 pub fn proof(&self) -> &TransactionInclusionProof<Types> {
933 &self.proof
934 }
935
936 pub fn transaction(&self) -> &Transaction<Types> {
938 &self.transaction
939 }
940
941 pub fn hash(&self) -> TransactionHash<Types> {
943 self.hash
944 }
945
946 pub fn index(&self) -> u64 {
948 self.index
949 }
950
951 pub fn block_height(&self) -> u64 {
953 self.block_height
954 }
955
956 pub fn block_hash(&self) -> BlockHash<Types> {
958 self.block_hash
959 }
960}
961
962pub(crate) fn payload_size<Types: NodeType>(payload: &Payload<Types>) -> u64 {
963 payload.encode().len() as u64
964}
965
966#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
967#[serde(bound = "")]
968pub struct BlockSummaryQueryData<Types: NodeType>
969where
970 Header<Types>: QueryableHeader<Types>,
971{
972 pub(crate) header: Header<Types>,
973 pub(crate) hash: BlockHash<Types>,
974 pub(crate) size: u64,
975 pub(crate) num_transactions: u64,
976 pub(crate) namespaces: NamespaceMap<Types>,
977}
978
979impl<Types: NodeType> BlockSummaryQueryData<Types>
981where
982 Header<Types>: QueryableHeader<Types>,
983{
984 pub fn header(&self) -> &Header<Types> {
985 &self.header
986 }
987
988 pub fn hash(&self) -> BlockHash<Types> {
989 self.hash
990 }
991
992 pub fn size(&self) -> u64 {
993 self.size
994 }
995
996 pub fn num_transactions(&self) -> u64 {
997 self.num_transactions
998 }
999
1000 pub fn namespaces(&self) -> &NamespaceMap<Types> {
1001 &self.namespaces
1002 }
1003}
1004
1005impl<Types: NodeType> HeightIndexed for BlockSummaryQueryData<Types>
1006where
1007 Header<Types>: QueryableHeader<Types>,
1008{
1009 fn height(&self) -> u64 {
1010 self.header.block_number()
1011 }
1012}
1013
1014#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
1015#[serde(bound = "")]
1016pub struct TransactionSummaryQueryData<Types: NodeType> {
1017 pub(crate) hash: TransactionHash<Types>,
1018 pub(crate) header: Header<Types>,
1019 pub(crate) transaction: Transaction<Types>,
1023}
1024
1025impl<Types: NodeType> From<BlockQueryData<Types>> for BlockSummaryQueryData<Types>
1029where
1030 Header<Types>: QueryableHeader<Types>,
1031 Payload<Types>: QueryablePayload<Types>,
1032{
1033 fn from(value: BlockQueryData<Types>) -> Self {
1034 BlockSummaryQueryData {
1035 namespaces: value.namespace_info(),
1036 header: value.header,
1037 hash: value.hash,
1038 size: value.size,
1039 num_transactions: value.num_transactions,
1040 }
1041 }
1042}
1043
1044#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
1045pub struct NamespaceInfo {
1046 pub num_transactions: u64,
1047 pub size: u64,
1048}
1049
1050pub type NamespaceMap<Types> = HashMap<NamespaceId<Types>, NamespaceInfo>;
1051
1052#[derive(Clone, Debug, PartialEq, Eq)]
1057pub struct PayloadMetadata<Types>
1058where
1059 Types: NodeType,
1060 Header<Types>: QueryableHeader<Types>,
1061{
1062 pub height: u64,
1063 pub block_hash: BlockHash<Types>,
1064 pub hash: VidCommitment,
1065 pub size: u64,
1066 pub num_transactions: u64,
1067 pub namespaces: NamespaceMap<Types>,
1068}
1069
1070impl<Types> HeightIndexed for PayloadMetadata<Types>
1071where
1072 Types: NodeType,
1073 Header<Types>: QueryableHeader<Types>,
1074{
1075 fn height(&self) -> u64 {
1076 self.height
1077 }
1078}
1079
1080impl<Types> From<BlockQueryData<Types>> for PayloadMetadata<Types>
1081where
1082 Types: NodeType,
1083 Header<Types>: QueryableHeader<Types>,
1084 Payload<Types>: QueryablePayload<Types>,
1085{
1086 fn from(block: BlockQueryData<Types>) -> Self {
1087 Self {
1088 height: block.height(),
1089 block_hash: block.hash(),
1090 hash: block.payload_hash(),
1091 size: block.size(),
1092 num_transactions: block.num_transactions(),
1093 namespaces: block.namespace_info(),
1094 }
1095 }
1096}
1097
1098#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1103pub struct VidCommonMetadata<Types>
1104where
1105 Types: NodeType,
1106{
1107 pub height: u64,
1108 pub block_hash: BlockHash<Types>,
1109 pub payload_hash: VidCommitment,
1110}
1111
1112impl<Types> HeightIndexed for VidCommonMetadata<Types>
1113where
1114 Types: NodeType,
1115{
1116 fn height(&self) -> u64 {
1117 self.height
1118 }
1119}
1120
1121impl<Types> From<VidCommonQueryData<Types>> for VidCommonMetadata<Types>
1122where
1123 Types: NodeType,
1124{
1125 fn from(common: VidCommonQueryData<Types>) -> Self {
1126 Self {
1127 height: common.height(),
1128 block_hash: common.block_hash(),
1129 payload_hash: common.payload_hash(),
1130 }
1131 }
1132}
1133
1134#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq)]
1135pub struct Limits {
1136 pub small_object_range_limit: usize,
1137 pub large_object_range_limit: usize,
1138}