openmina_bootstrap_sandbox/
bootstrap.rs

1use 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        // FIXME: Using `supercharge_coinbase` (from block) above does not work
180        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}