1#![allow(clippy::too_many_arguments)]
2use crate::idl::arcium::{
7 accounts::{MXEAccount, MxeRecoveryAccount, RecoveryClusterAccount},
8 types::{
9 AbortReason,
10 CircuitFailureReason,
11 ExecutionFailure,
12 KeyRecoveryFailureReason,
13 MxeStatus,
14 RecoveryKeyMaterial,
15 SetUnset,
16 },
17};
18use anchor_lang::{
19 declare_program,
20 prelude::{instruction::Instruction, *},
21};
22use std::hash::{Hash, Hasher};
23
24pub const RESCUE_KEY_COUNT: usize = 5;
26
27declare_program!(arcium);
28declare_program!(arcium_staking);
29
30use arcium::types::{
31 ArxNodeConfig,
32 CallbackAccount,
33 CallbackInstruction,
34 ComputationReference,
35 NodeMetadata,
36 NodeRef,
37};
38
39impl Hash for ComputationReference {
40 fn hash<H: Hasher>(&self, state: &mut H) {
41 self.computation_offset.hash(state);
42 self.priority_fee.hash(state);
43 }
44}
45
46impl Eq for ComputationReference {}
47
48impl PartialEq for ComputationReference {
49 fn eq(&self, other: &Self) -> bool {
50 self.computation_offset == other.computation_offset
51 && self.priority_fee == other.priority_fee
52 }
53}
54
55impl PartialEq for NodeMetadata {
56 fn eq(&self, other: &Self) -> bool {
57 self.location == other.location && self.ip == other.ip && self.peer_id == other.peer_id
58 }
59}
60
61impl PartialEq for ArxNodeConfig {
62 fn eq(&self, other: &Self) -> bool {
63 self.authority == other.authority && self.callback_authority == other.callback_authority
64 }
65}
66
67impl PartialEq for NodeRef {
68 fn eq(&self, other: &Self) -> bool {
69 self.offset == other.offset && self.vote == other.vote
70 }
71}
72
73impl MXEAccount {
74 pub fn is_active(&self) -> bool {
75 matches!(self.status, MxeStatus::Active)
76 }
77
78 pub fn is_in_migration(&self) -> bool {
79 matches!(self.status, MxeStatus::Migration)
80 }
81}
82
83impl MXEAccount {
84 pub fn x25519_pubkey(&self) -> Option<[u8; 32]> {
85 match &self.utility_pubkeys {
86 SetUnset::Set(keys) => Some(keys.x25519_pubkey),
87 SetUnset::Unset(keys, set_vec) => {
88 if set_vec.iter().all(|&b| b) {
89 Some(keys.x25519_pubkey)
90 } else {
91 None
92 }
93 }
94 }
95 }
96
97 pub fn ed25519_verifying_key(&self) -> Option<[u8; 32]> {
98 match &self.utility_pubkeys {
99 SetUnset::Set(keys) => Some(keys.ed25519_verifying_key),
100 SetUnset::Unset(keys, set_vec) => {
101 if set_vec.iter().all(|&b| b) {
102 Some(keys.ed25519_verifying_key)
103 } else {
104 None
105 }
106 }
107 }
108 }
109
110 pub fn elgamal_pubkey(&self) -> Option<[u8; 32]> {
111 match &self.utility_pubkeys {
112 SetUnset::Set(keys) => Some(keys.elgamal_pubkey),
113 SetUnset::Unset(keys, set_vec) => {
114 if set_vec.iter().all(|&b| b) {
115 Some(keys.elgamal_pubkey)
116 } else {
117 None
118 }
119 }
120 }
121 }
122}
123
124impl ExecutionFailure {
125 pub fn discriminator(&self) -> u8 {
126 match self {
127 ExecutionFailure::Serialization => 0,
128 ExecutionFailure::Router => 1,
129 ExecutionFailure::Circuit => 2,
130 ExecutionFailure::Inputs => 3,
131 ExecutionFailure::ProtocolInit => 4,
132 ExecutionFailure::ProtocolRun => 5,
133 ExecutionFailure::OutputTooLarge => 6,
134 ExecutionFailure::TrustedDealer => 7,
135 ExecutionFailure::Abort(AbortReason::InvalidMAC) => 50,
136 ExecutionFailure::Abort(AbortReason::ExpectedSentShare) => 51,
137 ExecutionFailure::Abort(AbortReason::ExpectedFieldElement) => 52,
138 ExecutionFailure::Abort(AbortReason::ExpectedAbort) => 53,
139 ExecutionFailure::Abort(AbortReason::MalformedData) => 54,
140 ExecutionFailure::Abort(AbortReason::ComputationFailed) => 55,
141 ExecutionFailure::Abort(AbortReason::InternalError) => 56,
142 ExecutionFailure::Abort(AbortReason::PreprocessingStreamError) => 57,
143 ExecutionFailure::Abort(AbortReason::DivisionByZero) => 58,
144 ExecutionFailure::Abort(AbortReason::NoSignature) => 59,
145 ExecutionFailure::Abort(AbortReason::InvalidSignature) => 60,
146 ExecutionFailure::Abort(AbortReason::PrimitiveError) => 61,
147 ExecutionFailure::Abort(AbortReason::InvalidBatchLength) => 62,
148 ExecutionFailure::Abort(AbortReason::QuadraticNonResidue) => 63,
149 ExecutionFailure::Abort(AbortReason::BitConversionError) => 64,
150 ExecutionFailure::Abort(AbortReason::ChannelClosed) => 65,
151 ExecutionFailure::Abort(AbortReason::TimeoutElapsed) => 66,
152 ExecutionFailure::Abort(AbortReason::KeyRecoveryError) => 67,
153 ExecutionFailure::KeyRecoveryFailure(KeyRecoveryFailureReason::KeysDigestMismatch) => {
154 100
155 }
156 ExecutionFailure::KeyRecoveryFailure(
157 KeyRecoveryFailureReason::X25519PubkeyMismatch,
158 ) => 101,
159 ExecutionFailure::KeyRecoveryFailure(
160 KeyRecoveryFailureReason::Ed25519VerifyingKeyMismatch,
161 ) => 102,
162 ExecutionFailure::KeyRecoveryFailure(
163 KeyRecoveryFailureReason::ElGamalPubkeyMismatch,
164 ) => 103,
165 ExecutionFailure::KeyRecoveryFailure(KeyRecoveryFailureReason::TooManyCorruptPeers) => {
166 104
167 }
168 ExecutionFailure::KeyRecoveryFailure(KeyRecoveryFailureReason::NoPubkeysSet) => 105,
169 ExecutionFailure::KeyRecoveryFailure(KeyRecoveryFailureReason::Serialization) => 106,
170 ExecutionFailure::CircuitFailure(CircuitFailureReason::OnChainCircuitNotReady) => 120,
171 ExecutionFailure::CircuitFailure(CircuitFailureReason::OffChainCircuitFetchFailed) => {
172 121
173 }
174 ExecutionFailure::CircuitFailure(CircuitFailureReason::OffChainCircuitHashMismatch) => {
175 122
176 }
177 ExecutionFailure::CircuitFailure(CircuitFailureReason::CircuitCUMismatch) => 123,
178 ExecutionFailure::CircuitFailure(CircuitFailureReason::LocalCircuitFetchFailed) => 124,
179 ExecutionFailure::CircuitFailure(CircuitFailureReason::CircuitSerialization) => 125,
180 ExecutionFailure::CircuitFailure(CircuitFailureReason::OtherArxError) => 126,
181 }
182 }
183
184 pub fn from_discriminator(discriminator: u8) -> Option<Self> {
185 match discriminator {
186 0 => Some(ExecutionFailure::Serialization),
187 1 => Some(ExecutionFailure::Router),
188 2 => Some(ExecutionFailure::Circuit),
189 3 => Some(ExecutionFailure::Inputs),
190 4 => Some(ExecutionFailure::ProtocolInit),
191 5 => Some(ExecutionFailure::ProtocolRun),
192 6 => Some(ExecutionFailure::OutputTooLarge),
193 7 => Some(ExecutionFailure::TrustedDealer),
194 50 => Some(ExecutionFailure::Abort(AbortReason::InvalidMAC)),
195 51 => Some(ExecutionFailure::Abort(AbortReason::ExpectedSentShare)),
196 52 => Some(ExecutionFailure::Abort(AbortReason::ExpectedFieldElement)),
197 53 => Some(ExecutionFailure::Abort(AbortReason::ExpectedAbort)),
198 54 => Some(ExecutionFailure::Abort(AbortReason::MalformedData)),
199 55 => Some(ExecutionFailure::Abort(AbortReason::ComputationFailed)),
200 56 => Some(ExecutionFailure::Abort(AbortReason::InternalError)),
201 57 => Some(ExecutionFailure::Abort(
202 AbortReason::PreprocessingStreamError,
203 )),
204 58 => Some(ExecutionFailure::Abort(AbortReason::DivisionByZero)),
205 59 => Some(ExecutionFailure::Abort(AbortReason::NoSignature)),
206 60 => Some(ExecutionFailure::Abort(AbortReason::InvalidSignature)),
207 61 => Some(ExecutionFailure::Abort(AbortReason::PrimitiveError)),
208 62 => Some(ExecutionFailure::Abort(AbortReason::InvalidBatchLength)),
209 63 => Some(ExecutionFailure::Abort(AbortReason::QuadraticNonResidue)),
210 64 => Some(ExecutionFailure::Abort(AbortReason::BitConversionError)),
211 65 => Some(ExecutionFailure::Abort(AbortReason::ChannelClosed)),
212 66 => Some(ExecutionFailure::Abort(AbortReason::TimeoutElapsed)),
213 67 => Some(ExecutionFailure::Abort(AbortReason::KeyRecoveryError)),
214 100 => Some(ExecutionFailure::KeyRecoveryFailure(
215 KeyRecoveryFailureReason::KeysDigestMismatch,
216 )),
217 101 => Some(ExecutionFailure::KeyRecoveryFailure(
218 KeyRecoveryFailureReason::X25519PubkeyMismatch,
219 )),
220 102 => Some(ExecutionFailure::KeyRecoveryFailure(
221 KeyRecoveryFailureReason::Ed25519VerifyingKeyMismatch,
222 )),
223 103 => Some(ExecutionFailure::KeyRecoveryFailure(
224 KeyRecoveryFailureReason::ElGamalPubkeyMismatch,
225 )),
226 104 => Some(ExecutionFailure::KeyRecoveryFailure(
227 KeyRecoveryFailureReason::TooManyCorruptPeers,
228 )),
229 105 => Some(ExecutionFailure::KeyRecoveryFailure(
230 KeyRecoveryFailureReason::NoPubkeysSet,
231 )),
232 106 => Some(ExecutionFailure::KeyRecoveryFailure(
233 KeyRecoveryFailureReason::Serialization,
234 )),
235 120 => Some(ExecutionFailure::CircuitFailure(
236 CircuitFailureReason::OnChainCircuitNotReady,
237 )),
238 121 => Some(ExecutionFailure::CircuitFailure(
239 CircuitFailureReason::OffChainCircuitFetchFailed,
240 )),
241 122 => Some(ExecutionFailure::CircuitFailure(
242 CircuitFailureReason::OffChainCircuitHashMismatch,
243 )),
244 123 => Some(ExecutionFailure::CircuitFailure(
245 CircuitFailureReason::CircuitCUMismatch,
246 )),
247 124 => Some(ExecutionFailure::CircuitFailure(
248 CircuitFailureReason::LocalCircuitFetchFailed,
249 )),
250 125 => Some(ExecutionFailure::CircuitFailure(
251 CircuitFailureReason::CircuitSerialization,
252 )),
253 126 => Some(ExecutionFailure::CircuitFailure(
254 CircuitFailureReason::OtherArxError,
255 )),
256
257 _ => None,
258 }
259 }
260}
261
262impl RecoveryClusterAccount {
263 pub fn n_peers(&self) -> usize {
264 self.recovery_peers
265 .iter()
266 .filter(|&peer| *peer != 0u32)
267 .count()
268 }
269}
270
271impl MxeRecoveryAccount {
272 pub fn n_peers_submitted_shares(&self) -> usize {
273 self.shares
274 .iter()
275 .filter(|&s| *s != [[0u8; 32]; RESCUE_KEY_COUNT])
276 .count()
277 }
278}
279
280impl RecoveryKeyMaterial {
281 pub fn is_initialized(&self) -> bool {
282 self.status == 1
283 }
284
285 pub fn is_finalized(&self) -> bool {
286 self.status == 2
287 }
288}
289
290impl CallbackInstruction {
291 pub fn to_instruction(&self, ix_data: &[u8]) -> Instruction {
292 let mut data = Vec::with_capacity(self.discriminator.len() + ix_data.len());
293 data.extend_from_slice(&self.discriminator);
294 data.extend_from_slice(ix_data);
295 Instruction {
296 program_id: self.program_id,
297 accounts: self.accounts.iter().map(|acc| acc.into()).collect(),
298 data,
299 }
300 }
301}
302
303impl From<&CallbackAccount> for AccountMeta {
304 fn from(acc: &CallbackAccount) -> Self {
305 AccountMeta {
306 pubkey: acc.pubkey,
307 is_signer: false,
308 is_writable: acc.is_writable,
309 }
310 }
311}
312
313impl From<arcium_staking::types::Epoch> for arcium::types::Epoch {
318 fn from(val: arcium_staking::types::Epoch) -> Self {
319 arcium::types::Epoch(val.0)
320 }
321}
322
323impl From<arcium::types::Epoch> for arcium_staking::types::Epoch {
324 fn from(val: arcium::types::Epoch) -> Self {
325 arcium_staking::types::Epoch(val.0)
326 }
327}
328
329#[repr(u8)]
330pub enum BLSDomainSeparator {
331 Success = 0,
332 Failure = 1,
333 PoP = 2,
334}