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