bark/exit/models/
mod.rs

1pub mod error;
2pub mod package;
3pub mod states;
4
5pub use package::*;
6pub use error::*;
7pub use states::*;
8
9use ark::VtxoId;
10use bitcoin::Txid;
11
12use bitcoin_ext::{BlockHeight, BlockRef, TxStatus};
13
14/// A utility type to wrap ExitState children so they can be easily serialized. This also helps with
15/// debugging a lot!
16#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
17#[serde(tag = "type", rename_all = "kebab-case")]
18pub enum ExitState {
19	Start(ExitStartState),
20	Processing(ExitProcessingState),
21	AwaitingDelta(ExitAwaitingDeltaState),
22	Claimable(ExitClaimableState),
23	ClaimInProgress(ExitClaimInProgressState),
24	Claimed(ExitClaimedState),
25}
26
27impl ExitState {
28	pub fn new_start(tip: BlockHeight) -> Self {
29		ExitState::Start(ExitStartState { tip_height: tip })
30	}
31
32	pub fn new_processing<T: IntoIterator<Item = Txid>>(tip: BlockHeight, txids: T) -> Self {
33		ExitState::Processing(ExitProcessingState {
34			tip_height: tip,
35			transactions: txids.into_iter()
36				.map(|id| ExitTx {
37					txid: id,
38					status: ExitTxStatus::VerifyInputs,
39				})
40				.collect::<Vec<_>>(),
41		})
42	}
43
44	pub fn new_processing_from_transactions(tip: BlockHeight, transactions: Vec<ExitTx>) -> Self {
45		ExitState::Processing(ExitProcessingState {
46			tip_height: tip,
47			transactions,
48		})
49	}
50
51	pub fn new_awaiting_delta(
52		tip: BlockHeight,
53		confirmed_block: BlockRef,
54		claimable_height: BlockHeight
55	) -> Self {
56		assert!(claimable_height >= confirmed_block.height);
57		ExitState::AwaitingDelta(ExitAwaitingDeltaState {
58			tip_height: tip,
59			confirmed_block,
60			claimable_height,
61		})
62	}
63
64	pub fn new_claimable(
65		tip: BlockHeight,
66		claimable_since: BlockRef,
67		last_scanned_block: Option<BlockRef>
68	) -> Self {
69		ExitState::Claimable(ExitClaimableState {
70			tip_height: tip,
71			claimable_since,
72			last_scanned_block,
73		})
74	}
75
76	pub fn new_claim_in_progress(
77		tip: BlockHeight,
78		claimable_since: BlockRef,
79		claim_txid: Txid
80	) -> Self {
81		ExitState::ClaimInProgress(ExitClaimInProgressState {
82			tip_height: tip,
83			claimable_since,
84			claim_txid,
85		})
86	}
87
88	pub fn new_claimed(tip: BlockHeight, txid: Txid, block: BlockRef) -> Self {
89		ExitState::Claimed(ExitClaimedState {
90			tip_height: tip,
91			txid,
92			block,
93		})
94	}
95
96	pub fn is_pending(&self) -> bool {
97		match self {
98			ExitState::Start(_) => true,
99			ExitState::Processing(_) => true,
100			ExitState::AwaitingDelta(_) => true,
101			_ => false,
102		}
103	}
104
105	pub fn requires_confirmations(&self) -> bool {
106		match self {
107			ExitState::Processing(s) => {
108				s.transactions.iter().any(|s| match s.status {
109					ExitTxStatus::AwaitingInputConfirmation { .. } => true,
110					ExitTxStatus::BroadcastWithCpfp { .. } => true,
111					_ => false,
112				})
113			},
114			ExitState::AwaitingDelta(_) => true,
115			ExitState::ClaimInProgress(_) => true,
116			_ => false,
117		}
118	}
119
120	/// Indicates whether the state relies on network updates during wallet sync to check whether
121	/// the exit can be spent
122	pub fn requires_network_update(&self) -> bool {
123		match self {
124			// If all transactions are either confirmed or already broadcast we can count Processing
125			// as requiring network updates since we don't need to create more exit packages.
126			ExitState::Processing(s) => s.transactions.iter().all(|s| match s.status {
127				ExitTxStatus::BroadcastWithCpfp { .. } => true,
128				ExitTxStatus::Confirmed { .. } => true,
129				_ => false,
130			}),
131			ExitState::AwaitingDelta(_) => true,
132			ExitState::Claimable(_) => true,
133			ExitState::ClaimInProgress(_) => true,
134			_ => false,
135		}
136	}
137
138	pub fn claimable_height(&self) -> Option<BlockHeight> {
139		match self {
140			ExitState::AwaitingDelta(s) => Some(s.claimable_height),
141			ExitState::Claimable(s) => Some(s.claimable_since.height),
142			ExitState::ClaimInProgress(s) => Some(s.claimable_since.height),
143			_ => None,
144		}
145	}
146}
147
148#[derive(Debug, Clone, PartialEq, Eq)]
149pub struct ExitProgressResponse {
150	/// Status of each pending exit transaction
151	pub exits: Vec<ExitProgressStatus>,
152	/// Whether all transactions have been confirmed
153	pub done: bool,
154	/// Block height at which all exit outputs will be spendable
155	pub claimable_height: Option<u32>,
156}
157
158#[derive(Debug, Clone, PartialEq, Eq)]
159pub struct ExitProgressStatus {
160	/// The ID of the VTXO that is being unilaterally exited
161	pub vtxo_id: VtxoId,
162	/// The current state of the exit transaction
163	pub state: ExitState,
164	/// Any error that occurred during the exit process
165	pub error: Option<ExitError>,
166}
167
168#[derive(Debug, Clone, PartialEq, Eq)]
169pub struct ExitTransactionStatus {
170	/// The ID of the VTXO that is being unilaterally exited
171	pub vtxo_id: VtxoId,
172	/// The current state of the exit transaction
173	pub state: ExitState,
174	/// The history of each state the exit transaction has gone through
175	pub history: Option<Vec<ExitState>>,
176	/// Each exit transaction package required for the unilateral exit
177	pub transactions: Vec<ExitTransactionPackage>,
178}
179
180#[derive(Clone, Copy, Debug,  Eq, PartialEq)]
181pub struct ExitChildStatus {
182	pub txid: Txid,
183	pub status: TxStatus,
184	pub origin: ExitTxOrigin,
185}