1use ckb_chain_spec::consensus::ProposalWindow;
4use ckb_types::{
5 core::{BlockNumber, EpochNumber, EpochNumberWithFraction, HeaderView},
6 packed::Byte32,
7};
8
9#[derive(Debug, Clone, Copy)]
11enum TxVerifyPhase {
12 Submitted,
18 Proposed(BlockNumber),
24 Committed,
28}
29
30#[derive(Debug, Clone)]
32pub struct TxVerifyEnv {
33 phase: TxVerifyPhase,
36 number: BlockNumber,
38 epoch: EpochNumberWithFraction,
39 hash: Byte32,
40 parent_hash: Byte32,
41}
42
43impl TxVerifyEnv {
44 pub fn new_submit(header: &HeaderView) -> Self {
48 Self {
49 phase: TxVerifyPhase::Submitted,
50 number: header.number(),
51 epoch: header.epoch(),
52 hash: header.hash(),
53 parent_hash: header.parent_hash(),
54 }
55 }
56
57 pub fn new_proposed(header: &HeaderView, n_blocks: BlockNumber) -> Self {
61 Self {
62 phase: TxVerifyPhase::Proposed(n_blocks),
63 number: header.number(),
64 epoch: header.epoch(),
65 hash: header.hash(),
66 parent_hash: header.parent_hash(),
67 }
68 }
69
70 pub fn new_commit(header: &HeaderView) -> Self {
74 Self {
75 phase: TxVerifyPhase::Committed,
76 number: header.number(),
77 epoch: header.epoch(),
78 hash: header.hash(),
79 parent_hash: header.parent_hash(),
80 }
81 }
82
83 pub fn block_number(&self, proposal_window: ProposalWindow) -> BlockNumber {
85 match self.phase {
86 TxVerifyPhase::Submitted => self.number + 1 + proposal_window.closest(),
87 TxVerifyPhase::Proposed(already_proposed) => {
88 self.number.saturating_sub(already_proposed) + proposal_window.closest()
89 }
90 TxVerifyPhase::Committed => self.number,
91 }
92 }
93
94 pub fn epoch_number(&self, proposal_window: ProposalWindow) -> EpochNumber {
96 let n_blocks = match self.phase {
97 TxVerifyPhase::Submitted => 1 + proposal_window.closest(),
98 TxVerifyPhase::Proposed(already_proposed) => {
99 proposal_window.closest().saturating_sub(already_proposed)
100 }
101 TxVerifyPhase::Committed => 0,
102 };
103 self.epoch.minimum_epoch_number_after_n_blocks(n_blocks)
104 }
105
106 pub fn parent_hash(&self) -> Byte32 {
108 match self.phase {
109 TxVerifyPhase::Submitted => &self.hash,
110 TxVerifyPhase::Proposed(_) => &self.hash,
111 TxVerifyPhase::Committed => &self.parent_hash,
112 }
113 .to_owned()
114 }
115
116 pub fn epoch(&self) -> EpochNumberWithFraction {
118 self.epoch
119 }
120
121 pub fn epoch_number_without_proposal_window(&self) -> EpochNumber {
124 let n_blocks = match self.phase {
125 TxVerifyPhase::Submitted | TxVerifyPhase::Proposed(_) => 1,
126 TxVerifyPhase::Committed => 0,
127 };
128 self.epoch.minimum_epoch_number_after_n_blocks(n_blocks)
129 }
130
131 pub fn verifying_inflight_tx(&self) -> bool {
134 !self.verifying_committed_tx()
135 }
136
137 pub fn verifying_committed_tx(&self) -> bool {
140 matches!(self.phase, TxVerifyPhase::Committed)
141 }
142}