Skip to main content

arcium_client/
idl.rs

1#![allow(clippy::too_many_arguments)]
2// We need this because clippy otherwise complains about a function internally generated by anchor's
3// declare_program!.
4//! Generated modules from the idls of the programs we want to interact with.
5
6use 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
24/// Number of 32-byte elements (matches RESCUE_KEY_COUNT in arcis-compiler).
25pub 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
313// Although Epoch is the same in `arcium` and `arcium_staking`
314// (which imports it from `arcium`) when it gets exported via the idl this information gets lost and
315// rust thinks they're two different types. We add these two traits so that we can convert between
316// them and don't have to constantly think about which Epoch is needed where.
317impl 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}