mina_node_native/graphql/
snark.rs

1use juniper::{graphql_object, GraphQLObject};
2use ledger::scan_state::scan_state::{AvailableJobMessage, ParallelScanAvailableJob};
3use mina_p2p_messages::v2::{
4    MinaBaseFeeExcessStableV1, MinaStateBlockchainStateValueStableV2SignedAmount,
5    TransactionSnarkScanStateTransactionWithWitnessStableV2, TransactionSnarkStableV2,
6};
7use node::snark_pool::JobState;
8
9use super::{account::GraphQLAccount, Context, ConversionError, GraphQLPublicKey};
10
11#[derive(GraphQLObject, Debug)]
12#[graphql(description = "A Mina block")]
13pub struct GraphQLPendingSnarkWork {
14    /// Work bundle with one or two snark work
15    pub work_bundle: Vec<GraphQLWorkDescription>,
16}
17
18#[derive(GraphQLObject, Debug)]
19pub struct GraphQLWorkDescription {
20    /// Base58Check-encoded hash of the source first-pass ledger
21    pub source_first_pass_ledger_hash: String,
22    /// Base58Check-encoded hash of the target first-pass ledger
23    pub target_first_pass_ledger_hash: String,
24    /// Base58Check-encoded hash of the source second-pass ledger
25    pub source_second_pass_ledger_hash: String,
26    /// Base58Check-encoded hash of the target second-pass ledger
27    pub target_second_pass_ledger_hash: String,
28    /// Total transaction fee that is not accounted for in the transition from
29    /// source ledger to target ledger
30    pub fee_excess: GraphQLFeeExcesses,
31    /// Increase/Decrease in total supply
32    pub supply_change: GraphQLSupplyChange,
33    /// Increase in total supply
34    pub supply_increase: String,
35    /// Unique identifier for a snark work
36    pub work_id: i32,
37}
38
39#[derive(GraphQLObject, Debug)]
40pub struct GraphQLFeeExcesses {
41    pub fee_token_left: String,
42    pub fee_excess_left: GraphQLFeeExcess,
43    pub fee_token_right: String,
44    pub fee_excess_right: GraphQLFeeExcess,
45}
46
47#[derive(GraphQLObject, Debug)]
48pub struct GraphQLFeeExcess {
49    pub fee_magnitude: String,
50    pub sign: String,
51}
52
53#[derive(GraphQLObject, Debug)]
54pub struct GraphQLSupplyChange {
55    pub amount_magnitude: String,
56    pub sign: String,
57}
58
59impl TryFrom<JobState> for GraphQLPendingSnarkWork {
60    type Error = ConversionError;
61
62    fn try_from(value: JobState) -> Result<Self, Self::Error> {
63        let mut work_bundle = Vec::new();
64
65        for job in value.job.into_iter() {
66            work_bundle.push(GraphQLWorkDescription::try_from(job)?);
67        }
68
69        Ok(Self { work_bundle })
70    }
71}
72
73impl TryFrom<AvailableJobMessage> for GraphQLWorkDescription {
74    type Error = ConversionError;
75
76    fn try_from(value: AvailableJobMessage) -> Result<Self, Self::Error> {
77        match value {
78            ParallelScanAvailableJob::Base(base) => GraphQLWorkDescription::try_from(base),
79            ParallelScanAvailableJob::Merge { left, .. } => {
80                GraphQLWorkDescription::try_from(left.0 .0)
81            }
82        }
83    }
84}
85
86impl TryFrom<MinaBaseFeeExcessStableV1> for GraphQLFeeExcesses {
87    type Error = ConversionError;
88
89    fn try_from(value: MinaBaseFeeExcessStableV1) -> Result<Self, Self::Error> {
90        Ok(Self {
91            fee_token_left: value.0.token.to_string(),
92            fee_excess_left: GraphQLFeeExcess {
93                fee_magnitude: value.0.amount.magnitude.to_string(),
94                sign: value.0.amount.sgn.to_string(),
95            },
96            fee_token_right: value.1.token.to_string(),
97            fee_excess_right: GraphQLFeeExcess {
98                fee_magnitude: value.1.amount.magnitude.to_string(),
99                sign: value.1.amount.sgn.to_string(),
100            },
101        })
102    }
103}
104
105impl TryFrom<MinaStateBlockchainStateValueStableV2SignedAmount> for GraphQLSupplyChange {
106    type Error = ConversionError;
107
108    fn try_from(
109        value: MinaStateBlockchainStateValueStableV2SignedAmount,
110    ) -> Result<Self, Self::Error> {
111        Ok(Self {
112            amount_magnitude: value.magnitude.to_string(),
113            sign: value.sgn.to_string(),
114        })
115    }
116}
117
118impl TryFrom<TransactionSnarkScanStateTransactionWithWitnessStableV2> for GraphQLWorkDescription {
119    type Error = ConversionError;
120
121    fn try_from(
122        value: TransactionSnarkScanStateTransactionWithWitnessStableV2,
123    ) -> Result<Self, Self::Error> {
124        Ok(Self {
125            source_first_pass_ledger_hash: value.statement.source.first_pass_ledger.to_string(),
126            target_first_pass_ledger_hash: value.statement.target.first_pass_ledger.to_string(),
127            source_second_pass_ledger_hash: value.statement.source.second_pass_ledger.to_string(),
128            target_second_pass_ledger_hash: value.statement.target.second_pass_ledger.to_string(),
129            fee_excess: GraphQLFeeExcesses::try_from(value.statement.fee_excess.clone())?,
130            supply_change: GraphQLSupplyChange::try_from(value.statement.supply_increase.clone())?,
131            supply_increase: value.statement.supply_increase.magnitude.to_string(),
132            work_id: 0,
133        })
134    }
135}
136
137impl TryFrom<TransactionSnarkStableV2> for GraphQLWorkDescription {
138    type Error = ConversionError;
139
140    fn try_from(value: TransactionSnarkStableV2) -> Result<Self, Self::Error> {
141        Ok(Self {
142            source_first_pass_ledger_hash: value.statement.source.first_pass_ledger.to_string(),
143            target_first_pass_ledger_hash: value.statement.target.first_pass_ledger.to_string(),
144            source_second_pass_ledger_hash: value.statement.source.second_pass_ledger.to_string(),
145            target_second_pass_ledger_hash: value.statement.target.second_pass_ledger.to_string(),
146            fee_excess: GraphQLFeeExcesses::try_from(value.statement.fee_excess.clone())?,
147            supply_change: GraphQLSupplyChange::try_from(value.statement.supply_increase.clone())?,
148            supply_increase: value.statement.supply_increase.magnitude.to_string(),
149            work_id: 0,
150        })
151    }
152}
153
154pub(crate) struct GraphQLSnarkWorker {
155    pub key: GraphQLPublicKey,
156    pub account: Option<GraphQLAccount>,
157    pub fee: String,
158}
159
160#[graphql_object(context = Context)]
161#[graphql(description = "A snark worker")]
162impl GraphQLSnarkWorker {
163    pub fn key(&self) -> String {
164        self.key.to_string()
165    }
166
167    pub fn fee(&self) -> String {
168        self.fee.to_string()
169    }
170
171    pub fn account(&self) -> Option<GraphQLAccount> {
172        self.account.clone()
173    }
174}