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