11use std:: cmp:: Ordering ;
22
33use fallible_iterator:: FallibleIterator ;
4- use heed:: {
5- types:: { OwnedType , SerdeBincode } ,
6- Database , RoTxn , RwTxn ,
7- } ;
4+ use heed:: { types:: SerdeBincode , Database , RoTxn , RwTxn } ;
85
9- use crate :: types:: { BlockHash , Body , Header } ;
6+ use crate :: types:: { Accumulator , BlockHash , Body , Header } ;
107
118#[ derive( Debug , thiserror:: Error ) ]
129pub enum Error {
@@ -16,6 +13,8 @@ pub enum Error {
1613 InvalidPrevSideHash ,
1714 #[ error( "invalid merkle root" ) ]
1815 InvalidMerkleRoot ,
16+ #[ error( "no accumulator for block {0}" ) ]
17+ NoAccumulator ( BlockHash ) ,
1918 #[ error( "no block with hash {0}" ) ]
2019 NoBlock ( BlockHash ) ,
2120 #[ error( "no header with hash {0}" ) ]
@@ -26,25 +25,50 @@ pub enum Error {
2625
2726#[ derive( Clone ) ]
2827pub struct Archive {
28+ accumulators : Database < SerdeBincode < BlockHash > , SerdeBincode < Accumulator > > ,
2929 headers : Database < SerdeBincode < BlockHash > , SerdeBincode < Header > > ,
3030 bodies : Database < SerdeBincode < BlockHash > , SerdeBincode < Body > > ,
31- hash_to_height : Database < SerdeBincode < BlockHash > , OwnedType < u32 > > ,
31+ hash_to_height : Database < SerdeBincode < BlockHash > , SerdeBincode < u32 > > ,
3232}
3333
3434impl Archive {
35- pub const NUM_DBS : u32 = 3 ;
35+ pub const NUM_DBS : u32 = 4 ;
3636
3737 pub fn new ( env : & heed:: Env ) -> Result < Self , Error > {
38+ let accumulators = env. create_database ( Some ( "accumulators" ) ) ?;
3839 let headers = env. create_database ( Some ( "headers" ) ) ?;
3940 let bodies = env. create_database ( Some ( "bodies" ) ) ?;
4041 let hash_to_height = env. create_database ( Some ( "hash_to_height" ) ) ?;
4142 Ok ( Self {
43+ accumulators,
4244 headers,
4345 bodies,
4446 hash_to_height,
4547 } )
4648 }
4749
50+ pub fn try_get_accumulator (
51+ & self ,
52+ rotxn : & RoTxn ,
53+ block_hash : BlockHash ,
54+ ) -> Result < Option < Accumulator > , Error > {
55+ if block_hash == BlockHash :: default ( ) {
56+ Ok ( Some ( Accumulator :: default ( ) ) )
57+ } else {
58+ let accumulator = self . accumulators . get ( rotxn, & block_hash) ?;
59+ Ok ( accumulator)
60+ }
61+ }
62+
63+ pub fn get_accumulator (
64+ & self ,
65+ rotxn : & RoTxn ,
66+ block_hash : BlockHash ,
67+ ) -> Result < Accumulator , Error > {
68+ self . try_get_accumulator ( rotxn, block_hash) ?
69+ . ok_or ( Error :: NoAccumulator ( block_hash) )
70+ }
71+
4872 pub fn try_get_header (
4973 & self ,
5074 rotxn : & RoTxn ,
@@ -104,6 +128,17 @@ impl Archive {
104128 . ok_or ( Error :: NoHeight ( block_hash) )
105129 }
106130
131+ /// Store a block body. The header must already exist.
132+ pub fn put_accumulator (
133+ & self ,
134+ rwtxn : & mut RwTxn ,
135+ block_hash : BlockHash ,
136+ accumulator : & Accumulator ,
137+ ) -> Result < ( ) , Error > {
138+ self . accumulators . put ( rwtxn, & block_hash, accumulator) ?;
139+ Ok ( ( ) )
140+ }
141+
107142 /// Store a block body. The header must already exist.
108143 pub fn put_body (
109144 & self ,
@@ -159,30 +194,30 @@ impl Archive {
159194 ) -> Result < BlockHash , Error > {
160195 let mut height0 = self . get_height ( rotxn, block_hash0) ?;
161196 let mut height1 = self . get_height ( rotxn, block_hash1) ?;
162- let mut header0 = self . get_header ( rotxn, block_hash0) ?;
163- let mut header1 = self . get_header ( rotxn, block_hash1) ?;
197+ let mut header0 = self . try_get_header ( rotxn, block_hash0) ?;
198+ let mut header1 = self . try_get_header ( rotxn, block_hash1) ?;
164199 // Find respective ancestors of block_hash0 and block_hash1 with height
165200 // equal to min(height0, height1)
166201 loop {
167202 match height0. cmp ( & height1) {
168203 Ordering :: Less => {
169- block_hash1 = header1. prev_side_hash ;
170- header1 = self . get_header ( rotxn, block_hash1) ?;
204+ block_hash1 = header1. unwrap ( ) . prev_side_hash ;
205+ header1 = self . try_get_header ( rotxn, block_hash1) ?;
171206 height1 -= 1 ;
172207 }
173208 Ordering :: Greater => {
174- block_hash0 = header0. prev_side_hash ;
175- header0 = self . get_header ( rotxn, block_hash0) ?;
209+ block_hash0 = header0. unwrap ( ) . prev_side_hash ;
210+ header0 = self . try_get_header ( rotxn, block_hash0) ?;
176211 height0 -= 1 ;
177212 }
178213 Ordering :: Equal => {
179214 if block_hash0 == block_hash1 {
180215 return Ok ( block_hash0) ;
181216 } else {
182- block_hash0 = header0. prev_side_hash ;
183- block_hash1 = header1. prev_side_hash ;
184- header0 = self . get_header ( rotxn, block_hash0) ?;
185- header1 = self . get_header ( rotxn, block_hash1) ?;
217+ block_hash0 = header0. unwrap ( ) . prev_side_hash ;
218+ block_hash1 = header1. unwrap ( ) . prev_side_hash ;
219+ header0 = self . try_get_header ( rotxn, block_hash0) ?;
220+ header1 = self . try_get_header ( rotxn, block_hash1) ?;
186221 height0 -= 1 ;
187222 height1 -= 1 ;
188223 }
0 commit comments