@@ -5,10 +5,32 @@ use crate::Coin;
55use crate :: EndOfSubSlotBundle ;
66use crate :: Program ;
77use crate :: RewardChainBlock ;
8+ use crate :: RewardChainBlockOld ;
89use crate :: VDFProof ;
910use crate :: { Foliage , FoliageTransactionBlock , TransactionsInfo } ;
1011use chia_traits:: Streamable ;
1112
13+ #[ cfg( feature = "py-bindings" ) ]
14+ use pyo3:: prelude:: * ;
15+
16+ // Pre-fork structure (before HARD_FORK2_HEIGHT)
17+ #[ streamable]
18+ pub struct FullBlockOld {
19+ finished_sub_slots : Vec < EndOfSubSlotBundle > ,
20+ reward_chain_block : RewardChainBlockOld ,
21+ challenge_chain_sp_proof : Option < VDFProof > , // # If not first sp in sub-slot
22+ challenge_chain_ip_proof : VDFProof ,
23+ reward_chain_sp_proof : Option < VDFProof > , // # If not first sp in sub-slot
24+ reward_chain_ip_proof : VDFProof ,
25+ infused_challenge_chain_ip_proof : Option < VDFProof > , // # Iff deficit < 4
26+ foliage : Foliage , // # Reward chain foliage data
27+ foliage_transaction_block : Option < FoliageTransactionBlock > , // # Reward chain foliage data (tx block)
28+ transactions_info : Option < TransactionsInfo > , // Reward chain foliage data (tx block additional)
29+ transactions_generator : Option < Program > , // Program that generates transactions
30+ transactions_generator_ref_list : Vec < u32 > , // List of block heights of previous generators referenced in this block
31+ }
32+
33+ // Post-fork structure (at or after HARD_FORK2_HEIGHT) - this is the default
1234#[ streamable]
1335pub struct FullBlock {
1436 finished_sub_slots : Vec < EndOfSubSlotBundle > ,
@@ -25,6 +47,84 @@ pub struct FullBlock {
2547 transactions_generator_ref_list : Vec < u32 > , // List of block heights of previous generators referenced in this block
2648}
2749
50+ impl FullBlockOld {
51+ pub fn prev_header_hash ( & self ) -> Bytes32 {
52+ self . foliage . prev_block_hash
53+ }
54+
55+ pub fn header_hash ( & self ) -> Bytes32 {
56+ self . foliage . hash ( ) . into ( )
57+ }
58+
59+ pub fn is_transaction_block ( & self ) -> bool {
60+ self . foliage . foliage_transaction_block_hash . is_some ( )
61+ }
62+
63+ pub fn total_iters ( & self ) -> u128 {
64+ self . reward_chain_block . total_iters
65+ }
66+
67+ pub fn height ( & self ) -> u32 {
68+ self . reward_chain_block . height
69+ }
70+
71+ pub fn weight ( & self ) -> u128 {
72+ self . reward_chain_block . weight
73+ }
74+
75+ pub fn get_included_reward_coins ( & self ) -> Vec < Coin > {
76+ if let Some ( ti) = & self . transactions_info {
77+ ti. reward_claims_incorporated . clone ( )
78+ } else {
79+ vec ! [ ]
80+ }
81+ }
82+
83+ pub fn is_fully_compactified ( & self ) -> bool {
84+ for sub_slot in & self . finished_sub_slots {
85+ if sub_slot. proofs . challenge_chain_slot_proof . witness_type != 0
86+ || !sub_slot
87+ . proofs
88+ . challenge_chain_slot_proof
89+ . normalized_to_identity
90+ {
91+ return false ;
92+ }
93+ if let Some ( proof) = & sub_slot. proofs . infused_challenge_chain_slot_proof {
94+ if proof. witness_type != 0 || !proof. normalized_to_identity {
95+ return false ;
96+ }
97+ }
98+ }
99+
100+ if let Some ( proof) = & self . challenge_chain_sp_proof {
101+ if proof. witness_type != 0 || !proof. normalized_to_identity {
102+ return false ;
103+ }
104+ }
105+ self . challenge_chain_ip_proof . witness_type == 0
106+ && self . challenge_chain_ip_proof . normalized_to_identity
107+ }
108+
109+ // Always safe: upgrade reward_chain_block to new version
110+ pub fn to_new ( & self ) -> FullBlock {
111+ FullBlock {
112+ finished_sub_slots : self . finished_sub_slots . clone ( ) ,
113+ reward_chain_block : self . reward_chain_block . to_new ( ) ,
114+ challenge_chain_sp_proof : self . challenge_chain_sp_proof . clone ( ) ,
115+ challenge_chain_ip_proof : self . challenge_chain_ip_proof . clone ( ) ,
116+ reward_chain_sp_proof : self . reward_chain_sp_proof . clone ( ) ,
117+ reward_chain_ip_proof : self . reward_chain_ip_proof . clone ( ) ,
118+ infused_challenge_chain_ip_proof : self . infused_challenge_chain_ip_proof . clone ( ) ,
119+ foliage : self . foliage . clone ( ) ,
120+ foliage_transaction_block : self . foliage_transaction_block . clone ( ) ,
121+ transactions_info : self . transactions_info . clone ( ) ,
122+ transactions_generator : self . transactions_generator . clone ( ) ,
123+ transactions_generator_ref_list : self . transactions_generator_ref_list . clone ( ) ,
124+ }
125+ }
126+ }
127+
28128impl FullBlock {
29129 pub fn prev_header_hash ( & self ) -> Bytes32 {
30130 self . foliage . prev_block_hash
@@ -83,12 +183,121 @@ impl FullBlock {
83183 self . challenge_chain_ip_proof . witness_type == 0
84184 && self . challenge_chain_ip_proof . normalized_to_identity
85185 }
186+
187+ // Validated downgrade: only safe if reward_chain_block can downgrade
188+ #[ cfg( feature = "py-bindings" ) ]
189+ pub fn to_old ( & self ) -> PyResult < FullBlockOld > {
190+ let reward_chain_block_old = self . reward_chain_block . to_old ( ) ?;
191+ Ok ( FullBlockOld {
192+ finished_sub_slots : self . finished_sub_slots . clone ( ) ,
193+ reward_chain_block : reward_chain_block_old,
194+ challenge_chain_sp_proof : self . challenge_chain_sp_proof . clone ( ) ,
195+ challenge_chain_ip_proof : self . challenge_chain_ip_proof . clone ( ) ,
196+ reward_chain_sp_proof : self . reward_chain_sp_proof . clone ( ) ,
197+ reward_chain_ip_proof : self . reward_chain_ip_proof . clone ( ) ,
198+ infused_challenge_chain_ip_proof : self . infused_challenge_chain_ip_proof . clone ( ) ,
199+ foliage : self . foliage . clone ( ) ,
200+ foliage_transaction_block : self . foliage_transaction_block . clone ( ) ,
201+ transactions_info : self . transactions_info . clone ( ) ,
202+ transactions_generator : self . transactions_generator . clone ( ) ,
203+ transactions_generator_ref_list : self . transactions_generator_ref_list . clone ( ) ,
204+ } )
205+ }
206+
207+ #[ cfg( not( feature = "py-bindings" ) ) ]
208+ pub fn to_old ( & self ) -> Result < FullBlockOld , String > {
209+ let reward_chain_block_old = self . reward_chain_block . to_old ( ) ?;
210+ Ok ( FullBlockOld {
211+ finished_sub_slots : self . finished_sub_slots . clone ( ) ,
212+ reward_chain_block : reward_chain_block_old,
213+ challenge_chain_sp_proof : self . challenge_chain_sp_proof . clone ( ) ,
214+ challenge_chain_ip_proof : self . challenge_chain_ip_proof . clone ( ) ,
215+ reward_chain_sp_proof : self . reward_chain_sp_proof . clone ( ) ,
216+ reward_chain_ip_proof : self . reward_chain_ip_proof . clone ( ) ,
217+ infused_challenge_chain_ip_proof : self . infused_challenge_chain_ip_proof . clone ( ) ,
218+ foliage : self . foliage . clone ( ) ,
219+ foliage_transaction_block : self . foliage_transaction_block . clone ( ) ,
220+ transactions_info : self . transactions_info . clone ( ) ,
221+ transactions_generator : self . transactions_generator . clone ( ) ,
222+ transactions_generator_ref_list : self . transactions_generator_ref_list . clone ( ) ,
223+ } )
224+ }
225+
226+ // Unchecked downgrade: caller guarantees reward_chain_block can downgrade
227+ pub fn to_old_unchecked ( & self ) -> FullBlockOld {
228+ FullBlockOld {
229+ finished_sub_slots : self . finished_sub_slots . clone ( ) ,
230+ reward_chain_block : self . reward_chain_block . to_old_unchecked ( ) ,
231+ challenge_chain_sp_proof : self . challenge_chain_sp_proof . clone ( ) ,
232+ challenge_chain_ip_proof : self . challenge_chain_ip_proof . clone ( ) ,
233+ reward_chain_sp_proof : self . reward_chain_sp_proof . clone ( ) ,
234+ reward_chain_ip_proof : self . reward_chain_ip_proof . clone ( ) ,
235+ infused_challenge_chain_ip_proof : self . infused_challenge_chain_ip_proof . clone ( ) ,
236+ foliage : self . foliage . clone ( ) ,
237+ foliage_transaction_block : self . foliage_transaction_block . clone ( ) ,
238+ transactions_info : self . transactions_info . clone ( ) ,
239+ transactions_generator : self . transactions_generator . clone ( ) ,
240+ transactions_generator_ref_list : self . transactions_generator_ref_list . clone ( ) ,
241+ }
242+ }
86243}
87244
88245#[ cfg( feature = "py-bindings" ) ]
89246use chia_traits:: ChiaToPython ;
247+
90248#[ cfg( feature = "py-bindings" ) ]
91- use pyo3:: prelude:: * ;
249+ #[ pymethods]
250+ impl FullBlockOld {
251+ #[ getter]
252+ #[ pyo3( name = "prev_header_hash" ) ]
253+ fn py_prev_header_hash ( & self ) -> Bytes32 {
254+ self . prev_header_hash ( )
255+ }
256+
257+ #[ getter]
258+ #[ pyo3( name = "header_hash" ) ]
259+ fn py_header_hash ( & self ) -> Bytes32 {
260+ self . header_hash ( )
261+ }
262+
263+ #[ pyo3( name = "is_transaction_block" ) ]
264+ fn py_is_transaction_block ( & self ) -> bool {
265+ self . is_transaction_block ( )
266+ }
267+
268+ #[ getter]
269+ #[ pyo3( name = "total_iters" ) ]
270+ fn py_total_iters < ' a > ( & self , py : Python < ' a > ) -> PyResult < Bound < ' a , PyAny > > {
271+ ChiaToPython :: to_python ( & self . total_iters ( ) , py)
272+ }
273+
274+ #[ getter]
275+ #[ pyo3( name = "height" ) ]
276+ fn py_height < ' a > ( & self , py : Python < ' a > ) -> PyResult < Bound < ' a , PyAny > > {
277+ ChiaToPython :: to_python ( & self . height ( ) , py)
278+ }
279+
280+ #[ getter]
281+ #[ pyo3( name = "weight" ) ]
282+ fn py_weight < ' a > ( & self , py : Python < ' a > ) -> PyResult < Bound < ' a , PyAny > > {
283+ ChiaToPython :: to_python ( & self . weight ( ) , py)
284+ }
285+
286+ #[ pyo3( name = "get_included_reward_coins" ) ]
287+ fn py_get_included_reward_coins ( & self ) -> Vec < Coin > {
288+ self . get_included_reward_coins ( )
289+ }
290+
291+ #[ pyo3( name = "is_fully_compactified" ) ]
292+ fn py_is_fully_compactified ( & self ) -> bool {
293+ self . is_fully_compactified ( )
294+ }
295+
296+ #[ pyo3( name = "to_new" ) ]
297+ fn py_to_new ( & self ) -> FullBlock {
298+ self . to_new ( )
299+ }
300+ }
92301
93302#[ cfg( feature = "py-bindings" ) ]
94303#[ pymethods]
@@ -137,4 +346,9 @@ impl FullBlock {
137346 fn py_is_fully_compactified ( & self ) -> bool {
138347 self . is_fully_compactified ( )
139348 }
349+
350+ #[ pyo3( name = "to_old" ) ]
351+ fn py_to_old ( & self ) -> PyResult < FullBlockOld > {
352+ self . to_old ( )
353+ }
140354}
0 commit comments