openmina_bootstrap_sandbox/
bootstrap.rs1use std::{collections::BTreeMap, fs::File, path::Path};
2
3use binprot::BinProtRead;
4use ledger::{
5 mask::Mask,
6 scan_state::transaction_logic::{local_state::LocalState, protocol_state},
7 staged_ledger::{diff::Diff, staged_ledger::StagedLedger},
8 verifier::Verifier,
9};
10use mina_curves::pasta::Fp;
11use mina_p2p_messages::{
12 rpc::{GetBestTipV2, GetStagedLedgerAuxAndPendingCoinbasesAtHashV2Response},
13 rpc_kernel::RpcMethod,
14 v2,
15};
16use mina_signer::CompressedPubKey;
17use openmina_core::constants::constraint_constants;
18
19use super::snarked_ledger::SnarkedLedger;
20
21pub async fn again(path_main: &Path, height: u32) {
22 let path_blocks = path_main.join("blocks");
23 let path = path_main.join(height.to_string());
24
25 let mut best_tip_file = File::open(path.join("best_tip")).unwrap();
26 let best_tip = <<GetBestTipV2 as RpcMethod>::Response>::binprot_read(&mut best_tip_file)
27 .unwrap()
28 .unwrap();
29
30 let head = best_tip.data;
31 let last_protocol_state = best_tip.proof.1.header.protocol_state;
32 let last_protocol_state_hash = last_protocol_state.try_hash().unwrap();
33
34 let snarked_ledger_hash = last_protocol_state
35 .body
36 .blockchain_state
37 .ledger_proof_statement
38 .target
39 .first_pass_ledger
40 .clone();
41 let snarked_ledger_hash_str = match serde_json::to_value(snarked_ledger_hash).unwrap() {
42 serde_json::Value::String(s) => s,
43 _ => panic!(),
44 };
45 let snarked_ledger = match File::open(path.join("ledgers").join(snarked_ledger_hash_str)) {
46 Ok(file) => SnarkedLedger::load_bin(file).unwrap(),
47 Err(_) => SnarkedLedger::empty(),
48 };
49
50 let mut file = File::open(path.join("staged_ledger_aux")).unwrap();
51 let info =
52 GetStagedLedgerAuxAndPendingCoinbasesAtHashV2Response::binprot_read(&mut file).unwrap();
53
54 let expected_hash = last_protocol_state
55 .body
56 .blockchain_state
57 .staged_ledger_hash
58 .clone();
59 let mut storage = Storage::new(snarked_ledger.inner, info, expected_hash);
60
61 let file = File::open(path_main.join("blocks").join("table.json")).unwrap();
62 let table = serde_json::from_reader::<_, BTreeMap<String, u32>>(file).unwrap();
63
64 let mut last = head.header.protocol_state.previous_state_hash.clone();
65 let mut blocks = vec![];
66 blocks.push(head);
67 while last.0 != last_protocol_state_hash.inner().0 {
68 let height = table.get(&last.to_string()).unwrap();
69 let path = path_blocks.join(height.to_string()).join(last.to_string());
70
71 let mut file = File::open(path).unwrap();
72 let new = v2::MinaBlockBlockStableV2::binprot_read(&mut file).unwrap();
73 last = new.header.protocol_state.previous_state_hash.clone();
74 blocks.push(new);
75 }
76
77 let mut last_protocol_state = last_protocol_state;
78 while let Some(block) = blocks.pop() {
79 storage.apply_block(&block, &last_protocol_state);
80 last_protocol_state = block.header.protocol_state.clone();
81 }
82}
83
84pub struct Storage {
85 staged_ledger: StagedLedger,
86}
87
88impl Storage {
89 pub fn new(
90 snarked_ledger: Mask,
91 info: GetStagedLedgerAuxAndPendingCoinbasesAtHashV2Response,
92 expected_hash: v2::MinaBaseStagedLedgerHashStableV1,
93 ) -> Self {
94 let (scan_state, expected_ledger_hash, pending_coinbase, states) = info.unwrap();
95
96 let states = states
97 .into_iter()
98 .map(|state| (state.try_hash().unwrap().to_field::<Fp>().unwrap(), state))
99 .collect::<BTreeMap<_, _>>();
100
101 let mut staged_ledger = StagedLedger::of_scan_state_pending_coinbases_and_snarked_ledger(
102 (),
103 constraint_constants(),
104 Verifier,
105 (&scan_state).try_into().unwrap(),
106 snarked_ledger.clone(),
107 LocalState::empty(),
108 expected_ledger_hash.clone().try_into().unwrap(),
109 (&pending_coinbase).try_into().unwrap(),
110 |key| states.get(&key).cloned().unwrap(),
111 )
112 .unwrap();
113
114 let expected_hash_str = serde_json::to_string(&expected_hash).unwrap();
115 log::info!("expected staged ledger hash: {expected_hash_str}");
116
117 let actual_hash = v2::MinaBaseStagedLedgerHashStableV1::from(&staged_ledger.hash());
118 let actual_hash_str = serde_json::to_string(&actual_hash).unwrap();
119 log::info!("actual staged ledger hash {actual_hash_str}");
120
121 assert_eq!(expected_hash, actual_hash);
122
123 Storage { staged_ledger }
124 }
125
126 pub fn apply_block(
127 &mut self,
128 block: &v2::MinaBlockBlockStableV2,
129 prev_protocol_state: &v2::MinaStateProtocolStateValueStableV2,
130 ) {
131 let length = block
132 .header
133 .protocol_state
134 .body
135 .consensus_state
136 .blockchain_length
137 .as_u32();
138 let previous_state_hash = block.header.protocol_state.previous_state_hash.clone();
139 let _previous_state_hash = v2::StateHash::from(v2::DataHashLibStateHashStableV1(
140 prev_protocol_state.try_hash().unwrap().inner().0.clone(),
141 ));
142 assert_eq!(previous_state_hash, _previous_state_hash);
143 log::info!("will apply: {length} prev: {previous_state_hash}");
144
145 let global_slot = block
146 .header
147 .protocol_state
148 .body
149 .consensus_state
150 .global_slot_since_genesis
151 .clone();
152
153 dbg!(block
154 .header
155 .protocol_state
156 .body
157 .consensus_state
158 .global_slot_since_genesis
159 .as_u32());
160 dbg!(block
161 .header
162 .protocol_state
163 .body
164 .consensus_state
165 .curr_global_slot_since_hard_fork
166 .slot_number
167 .as_u32());
168
169 let prev_state_view = protocol_state::protocol_state_view(prev_protocol_state).unwrap();
170
171 let protocol_state = &block.header.protocol_state;
172 let consensus_state = &protocol_state.body.consensus_state;
173 let coinbase_receiver: CompressedPubKey =
174 (&consensus_state.coinbase_receiver).try_into().unwrap();
175 let _supercharge_coinbase = consensus_state.supercharge_coinbase;
176
177 dbg!(&coinbase_receiver, _supercharge_coinbase);
178
179 let supercharge_coinbase = false;
181
182 let diff: Diff = (&block.body.staged_ledger_diff).try_into().unwrap();
183
184 let prev_protocol_state: ledger::proofs::block::ProtocolState =
185 prev_protocol_state.try_into().unwrap();
186
187 let result = self
188 .staged_ledger
189 .apply(
190 None,
191 constraint_constants(),
192 (&global_slot).into(),
193 diff,
194 (),
195 &Verifier,
196 &prev_state_view,
197 prev_protocol_state.hashes(),
198 coinbase_receiver,
199 supercharge_coinbase,
200 )
201 .unwrap();
202 let hash = v2::MinaBaseStagedLedgerHashStableV1::from(&result.hash_after_applying);
203 let hash_str = serde_json::to_string(&hash).unwrap();
204 log::info!("new staged ledger hash {hash_str}");
205 let expected_hash_str = serde_json::to_string(
206 &block
207 .header
208 .protocol_state
209 .body
210 .blockchain_state
211 .staged_ledger_hash,
212 )
213 .unwrap();
214 log::info!("expected staged ledger hash {expected_hash_str}");
215 assert_eq!(hash_str, expected_hash_str);
216 }
217}