1
2mod error;
3mod package;
4mod states;
5
6pub use self::package::{
7 ChildTransactionInfo, ExitCpfpRequest, ExitTransactionPackage, FeeInfo, RbfRequirement,
8 TransactionInfo,
9};
10pub use self::error::ExitError;
11pub use self::states::{
12 ExitTx, ExitTxStatus, ExitTxOrigin, ExitStartState, ExitProcessingState, ExitAwaitingDeltaState,
13 ExitClaimableState, ExitClaimInProgressState, ExitClaimedState, ExitVtxoAlreadySpentState,
14};
15
16use ark::VtxoId;
17use bitcoin::Txid;
18
19use bitcoin_ext::{BlockDelta, BlockHeight, BlockRef, TxStatus};
20
21#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
24#[serde(tag = "type", rename_all = "kebab-case")]
25pub enum ExitState {
26 Start(ExitStartState),
27 Processing(ExitProcessingState),
28 AwaitingDelta(ExitAwaitingDeltaState),
29 Claimable(ExitClaimableState),
30 ClaimInProgress(ExitClaimInProgressState),
31 Claimed(ExitClaimedState),
37 VtxoAlreadySpent(ExitVtxoAlreadySpentState),
41}
42
43impl ExitState {
44 pub fn new_start(tip: BlockHeight) -> Self {
45 ExitState::Start(ExitStartState { tip_height: tip })
46 }
47
48 pub fn new_processing<T: IntoIterator<Item = Txid>>(tip: BlockHeight, txids: T) -> Self {
49 ExitState::Processing(ExitProcessingState {
50 tip_height: tip,
51 transactions: txids.into_iter()
52 .map(|id| ExitTx {
53 txid: id,
54 status: ExitTxStatus::VerifyInputs,
55 })
56 .collect::<Vec<_>>(),
57 })
58 }
59
60 pub fn new_processing_from_transactions(tip: BlockHeight, transactions: Vec<ExitTx>) -> Self {
61 ExitState::Processing(ExitProcessingState {
62 tip_height: tip,
63 transactions,
64 })
65 }
66
67 pub fn new_awaiting_delta(
68 tip: BlockHeight,
69 confirmed_block: BlockRef,
70 wait_delta: BlockDelta
71 ) -> Self {
72 debug_assert_ne!(wait_delta, 0, "wait delta must be non-zero");
73 let claimable_height = confirmed_block.height + wait_delta as BlockHeight;
74 ExitState::AwaitingDelta(ExitAwaitingDeltaState {
75 tip_height: tip,
76 confirmed_block,
77 claimable_height,
78 })
79 }
80
81 pub fn new_claimable(
82 tip: BlockHeight,
83 claimable_since: BlockRef,
84 last_scanned_block: Option<BlockRef>
85 ) -> Self {
86 ExitState::Claimable(ExitClaimableState {
87 tip_height: tip,
88 claimable_since,
89 last_scanned_block,
90 })
91 }
92
93 pub fn new_claim_in_progress(
94 tip: BlockHeight,
95 claimable_since: BlockRef,
96 claim_txid: Txid
97 ) -> Self {
98 ExitState::ClaimInProgress(ExitClaimInProgressState {
99 tip_height: tip,
100 claimable_since,
101 claim_txid,
102 })
103 }
104
105 pub fn new_claimed(tip: BlockHeight, txid: Txid, block: BlockRef) -> Self {
106 ExitState::Claimed(ExitClaimedState {
107 tip_height: tip,
108 txid,
109 block,
110 })
111 }
112
113 pub fn new_vtxo_already_spent(tip: BlockHeight) -> Self {
114 ExitState::VtxoAlreadySpent(ExitVtxoAlreadySpentState { tip_height: tip })
115 }
116
117 pub fn is_pending(&self) -> bool {
122 match self {
123 ExitState::Start(_) => true,
124 ExitState::Processing(_) => true,
125 ExitState::AwaitingDelta(_) => true,
126 _ => false,
127 }
128 }
129
130 pub fn is_claimable(&self) -> bool {
133 match self {
134 ExitState::Claimable(_) => true,
135 _ => false,
136 }
137 }
138
139 pub fn requires_confirmations(&self) -> bool {
140 match self {
141 ExitState::Processing(s) => {
142 s.transactions.iter().any(|s| match s.status {
143 ExitTxStatus::AwaitingInputConfirmation { .. } => true,
144 ExitTxStatus::AwaitingConfirmation { .. } => true,
145 _ => false,
146 })
147 },
148 ExitState::AwaitingDelta(_) => true,
149 ExitState::ClaimInProgress(_) => true,
150 _ => false,
151 }
152 }
153
154 pub fn claimable_height(&self) -> Option<BlockHeight> {
155 match self {
156 ExitState::AwaitingDelta(s) => Some(s.claimable_height),
157 ExitState::Claimable(s) => Some(s.claimable_since.height),
158 ExitState::ClaimInProgress(s) => Some(s.claimable_since.height),
159 _ => None,
160 }
161 }
162
163 pub fn warrants_exited_vtxo(&self) -> bool {
173 match self {
174 ExitState::Start(_) => false,
175 ExitState::Processing(_) => false,
176 ExitState::AwaitingDelta(_) => true,
177 ExitState::Claimable(_) => true,
178 ExitState::ClaimInProgress(_) => true,
179 ExitState::Claimed(_) => true,
180 ExitState::VtxoAlreadySpent(_) => false,
181 }
182 }
183}
184
185#[derive(Debug, Clone, PartialEq, Eq)]
186pub struct ExitProgressStatus {
187 pub vtxo_id: VtxoId,
189 pub state: ExitState,
191 pub error: Option<ExitError>,
193}
194
195#[derive(Debug, Clone, PartialEq, Eq)]
196pub struct ExitTransactionStatus {
197 pub vtxo_id: VtxoId,
199 pub state: ExitState,
201 pub history: Option<Vec<ExitState>>,
203 pub transactions: Vec<ExitTransactionPackage>,
205}
206
207#[derive(Clone, Copy, Debug, Eq, PartialEq)]
208pub struct ExitChildStatus {
209 pub txid: Txid,
210 pub status: TxStatus,
211 pub origin: ExitTxOrigin,
212 pub fee_info: Option<FeeInfo>,
213}