mina_tree/scan_state/
snark_work.rs

1pub mod spec {
2    use crate::scan_state::{
3        scan_state::transaction_snark::{LedgerProof, Statement},
4        transaction_logic::transaction_witness::TransactionWitness,
5    };
6
7    pub enum Work {
8        Transition((Box<Statement<()>>, Box<TransactionWitness>)),
9        Merge(Box<(Statement<()>, Box<(LedgerProof, LedgerProof)>)>),
10    }
11}
12
13#[cfg(test)]
14mod tests {
15    use mina_p2p_messages::{
16        binprot::{
17            self,
18            macros::{BinProtRead, BinProtWrite},
19        },
20        v2::{
21            MinaBaseTransactionStatusStableV2, MinaTransactionTransactionStableV2,
22            SnarkWorkerWorkerRpcsVersionedGetWorkV2TResponse,
23            SnarkWorkerWorkerRpcsVersionedGetWorkV2TResponseA0Instances,
24        },
25    };
26
27    use binprot::{BinProtRead, BinProtWrite};
28
29    type SnarkWorkSpec = SnarkWorkerWorkerRpcsVersionedGetWorkV2TResponseA0Instances;
30
31    /// External worker input.
32    #[derive(Debug, BinProtRead, BinProtWrite)]
33    #[expect(clippy::large_enum_variant, reason = "This enum is only used in tests")]
34    pub enum ExternalSnarkWorkerRequest {
35        /// Queries worker for readiness, expected reply is `true`.
36        AwaitReadiness,
37        /// Commands worker to start specified snark job, expected reply is `ExternalSnarkWorkerResult`[ExternalSnarkWorkerResult].
38        PerformJob(SnarkWorkerWorkerRpcsVersionedGetWorkV2TResponse),
39    }
40
41    // fn read_input<R: std::io::Read>(
42    //     mut r: R,
43    // ) -> (NonZeroCurvePoint, CurrencyFeeStableV1, SnarkWorkSpec) {
44    //     let SnarkWorkerWorkerRpcsVersionedGetWorkV2TResponse(Some((
45    //         SnarkWorkerWorkerRpcsVersionedGetWorkV2TResponseA0 { instances, fee },
46    //         public_key,
47    //     ))) = SnarkWorkerWorkerRpcsVersionedGetWorkV2TResponse::binprot_read(&mut r)
48    //         .expect("cannot read work spec")
49    //     else {
50    //         unreachable!("incorrect work spec");
51    //     };
52
53    //     (public_key, fee, instances)
54    // }
55
56    // fn read_input<R: std::io::Read>(
57    //     mut r: R,
58    // ) {
59    //     let value: SnarkWorkerWorkerRpcsVersionedGetWorkV2TResponse = SnarkWorkerWorkerRpcsVersionedGetWorkV2TResponse::binprot_read(&mut r)
60    //         .expect("cannot read work spec");
61
62    //     let request = ExternalSnarkWorkerRequest::PerformJob(value);
63
64    //     let mut file = std::fs::File::create("/tmp/request.bin").unwrap();
65    //     ExternalSnarkWorkerRequest::binprot_write(&request, &mut file).unwrap();
66    //     file.sync_all().unwrap();
67
68    //     // (public_key, fee, instances)
69    // }
70
71    fn write_binprot<T: BinProtWrite, W: std::io::Write>(spec: T, mut w: W) {
72        let mut buf = Vec::new();
73        spec.binprot_write(&mut buf).unwrap();
74        let len = (buf.len() as u64).to_le_bytes();
75        w.write_all(&len).unwrap();
76        w.write_all(&buf).unwrap();
77    }
78
79    fn read_binprot<T, R>(mut r: R) -> T
80    where
81        T: BinProtRead,
82        R: std::io::Read,
83    {
84        use std::io::Read;
85
86        let mut len_buf = [0; std::mem::size_of::<u64>()];
87        r.read_exact(&mut len_buf).unwrap();
88        let len = u64::from_le_bytes(len_buf);
89
90        let mut buf = Vec::with_capacity(len as usize);
91        let mut r = r.take(len);
92        r.read_to_end(&mut buf).unwrap();
93
94        let mut read = buf.as_slice();
95        T::binprot_read(&mut read).unwrap()
96    }
97
98    fn read_input<R: std::io::Read>(mut r: R) {
99        let v: ExternalSnarkWorkerRequest = read_binprot(&mut r);
100        // let value: ExternalSnarkWorkerRequest = ExternalSnarkWorkerRequest::binprot_read(&mut r)
101        //     .expect("cannot read work spec");
102
103        println!("OK");
104
105        dbg!(v);
106
107        // let request = ExternalSnarkWorkerRequest::PerformJob(value);
108
109        // let mut file = std::fs::File::create("/tmp/request.bin").unwrap();
110        // ExternalSnarkWorkerRequest::binprot_write(&request, &mut file).unwrap();
111        // file.sync_all().unwrap();
112
113        // (public_key, fee, instances)
114    }
115
116    // #[test]
117    // fn snark_work() {
118    //     // const DATA: &[u8] = include_bytes!("/tmp/input.bin");
119    //     const DATA: &[u8] = include_bytes!("/tmp/spec1-header.bin");
120    //     // const DATA: &[u8] = include_bytes!("/tmp/spec1.bin");
121    //     let mut r = DATA;
122    //     read_input(&mut r);
123    //     // let (public_key, fee, instances) = read_input(&mut r);
124
125    //     // dbg!(instances);
126    //     // dbg!(&public_key, fee);
127    // }
128
129    #[test]
130    fn snark_work2() {
131        let Ok(r) = std::fs::read(
132            std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("requests_rampup4.bin"),
133        ) else {
134            return;
135        };
136        // const DATA: &[u8] = include_bytes!("/tmp/input.bin");
137        // const DATA: &[u8] = include_bytes!("/tmp/requests.bin");
138        // // const DATA: &[u8] = include_bytes!("/tmp/spec1.bin");
139        // let mut r = DATA;
140        let mut r = r.as_slice();
141
142        let requests =
143            Vec::<SnarkWorkerWorkerRpcsVersionedGetWorkV2TResponse>::binprot_read(&mut r).unwrap();
144
145        dbg!(requests.len());
146
147        let mut good = Vec::with_capacity(requests.len());
148
149        for (index, req) in requests.iter().enumerate() {
150            let index: usize = index;
151            let req: &SnarkWorkerWorkerRpcsVersionedGetWorkV2TResponse = req;
152
153            let Some((a, _prover)) = &req.0 else { panic!() };
154
155            let work = match &a.instances {
156                SnarkWorkerWorkerRpcsVersionedGetWorkV2TResponseA0Instances::One(w) => w,
157                SnarkWorkerWorkerRpcsVersionedGetWorkV2TResponseA0Instances::Two(_) => todo!(),
158            };
159
160            let (_stmt, witness) = match work {
161                mina_p2p_messages::v2::SnarkWorkerWorkerRpcsVersionedGetWorkV2TResponseA0Single::Transition(stmt, witness) => (stmt, witness),
162                mina_p2p_messages::v2::SnarkWorkerWorkerRpcsVersionedGetWorkV2TResponseA0Single::Merge(_) => todo!(),
163            };
164
165            if matches!(witness.status, MinaBaseTransactionStatusStableV2::Failed(_)) {
166                continue;
167            }
168
169            match &witness.transaction {
170                MinaTransactionTransactionStableV2::Command(cmd) => match &**cmd {
171                    mina_p2p_messages::v2::MinaBaseUserCommandStableV2::SignedCommand(_) => {
172                        eprintln!("[{}] signed", index)
173                    }
174                    mina_p2p_messages::v2::MinaBaseUserCommandStableV2::ZkappCommand(z) => {
175                        eprintln!("[{}] zkapp", index);
176                        eprintln!("zkapp {:#?}", z);
177                    }
178                },
179                MinaTransactionTransactionStableV2::FeeTransfer(_) => {
180                    eprintln!("[{}] fee_transfer", index)
181                }
182                MinaTransactionTransactionStableV2::Coinbase(_) => {
183                    eprintln!("[{}] coinbase", index)
184                }
185            }
186
187            // if !matches!(
188            //     witness.transaction,
189            //     MinaTransactionTransactionStableV2::FeeTransfer(_)
190            // ) {
191            //     continue;
192            // }
193
194            let is_good = match &witness.transaction {
195                MinaTransactionTransactionStableV2::Command(cmd) => {
196                    match &**cmd {
197                        mina_p2p_messages::v2::MinaBaseUserCommandStableV2::SignedCommand(cmd) => {
198                            match &cmd.payload.body {
199                                mina_p2p_messages::v2::MinaBaseSignedCommandPayloadBodyStableV2::Payment(_) => false,
200                                mina_p2p_messages::v2::MinaBaseSignedCommandPayloadBodyStableV2::StakeDelegation(_) => false,
201                            }
202                        },
203                        mina_p2p_messages::v2::MinaBaseUserCommandStableV2::ZkappCommand(_) => true,
204                    }
205                },
206                MinaTransactionTransactionStableV2::FeeTransfer(_) => false,
207                MinaTransactionTransactionStableV2::Coinbase(_) => false,
208            };
209
210            if is_good {
211                good.push(req.clone());
212            }
213
214            // match wi
215
216            // eprintln!("is_zkapp={:?}", is_zkapp);
217            // dbg!(is_zkapp);
218
219            // dbg!(&witness.transaction, &witness.status);
220        }
221
222        dbg!(good.len());
223        // dbg!(&good[0]);
224
225        for (index, value) in good.iter().enumerate().take(10) {
226            let value = ExternalSnarkWorkerRequest::PerformJob(value.clone());
227
228            let mut file =
229                std::fs::File::create(format!("/tmp/zkapp_{}_rampup4.bin", index)).unwrap();
230            write_binprot(value, &mut file);
231            file.sync_all().unwrap();
232        }
233
234        println!("OK");
235
236        // dbg!(&requests[0]);
237
238        // read_input(&mut r);
239        // let (public_key, fee, instances) = read_input(&mut r);
240
241        // dbg!(instances);
242        // dbg!(&public_key, fee);
243    }
244}