@@ -2,11 +2,10 @@ use std::collections::BTreeMap;
22use std:: fs;
33use std:: ops:: { Bound , RangeBounds } ;
44use std:: path:: PathBuf ;
5- use std:: str:: FromStr ;
65use std:: sync:: Arc ;
76
8- use bitcoin:: block:: { Header , Version } ;
9- use bitcoin:: { BlockHash , CompactTarget , Network , TxMerkleNode } ;
7+ use bitcoin:: block:: Header ;
8+ use bitcoin:: { consensus , BlockHash , Network } ;
109use rusqlite:: { params, params_from_iter, Connection , Result } ;
1110use tokio:: sync:: Mutex ;
1211
@@ -28,13 +27,8 @@ const SCHEMA_VERSION: u8 = 0;
2827// Always execute this query and adjust the schema with migrations
2928const INITIAL_HEADER_SCHEMA : & str = "CREATE TABLE IF NOT EXISTS headers (
3029 height INTEGER PRIMARY KEY,
31- block_hash TEXT NOT NULL,
32- version INTEGER NOT NULL,
33- prev_hash TEXT NOT NULL,
34- merkle_root TEXT NOT NULL,
35- time INTEGER NOT NULL,
36- bits INTEGER NOT NULL,
37- nonce INTEGER NOT NULL
30+ block_hash BLOB NOT NULL,
31+ header BLOB NOT NULL
3832) STRICT" ;
3933
4034const LOAD_QUERY_SELECT_PREFIX : & str = "SELECT * FROM headers " ;
@@ -127,30 +121,8 @@ impl SqliteHeaderDb {
127121 let mut rows = query. query ( params_from_iter ( param_list. iter ( ) ) ) ?;
128122 while let Some ( row) = rows. next ( ) ? {
129123 let height: u32 = row. get ( 0 ) ?;
130- let hash: String = row. get ( 1 ) ?;
131- let version: i32 = row. get ( 2 ) ?;
132- let prev_hash: String = row. get ( 3 ) ?;
133- let merkle_root: String = row. get ( 4 ) ?;
134- let time: u32 = row. get ( 5 ) ?;
135- let bits: u32 = row. get ( 6 ) ?;
136- let nonce: u32 = row. get ( 7 ) ?;
137-
138- let next_header = Header {
139- version : Version :: from_consensus ( version) ,
140- prev_blockhash : BlockHash :: from_str ( & prev_hash)
141- . map_err ( |_| SqlHeaderStoreError :: StringConversion ) ?,
142- merkle_root : TxMerkleNode :: from_str ( & merkle_root)
143- . map_err ( |_| SqlHeaderStoreError :: StringConversion ) ?,
144- time,
145- bits : CompactTarget :: from_consensus ( bits) ,
146- nonce,
147- } ;
148- if BlockHash :: from_str ( & hash)
149- . map_err ( |_| SqlHeaderStoreError :: StringConversion ) ?
150- . ne ( & next_header. block_hash ( ) )
151- {
152- return Err ( SqlHeaderStoreError :: Corruption ) ;
153- }
124+ let header: [ u8 ; 80 ] = row. get ( 2 ) ?;
125+ let next_header: Header = consensus:: deserialize ( & header) ?;
154126 if let Some ( header) = headers. values ( ) . last ( ) {
155127 if header. block_hash ( ) . ne ( & next_header. prev_blockhash ) {
156128 return Err ( SqlHeaderStoreError :: Corruption ) ;
@@ -167,55 +139,21 @@ impl SqliteHeaderDb {
167139 match changes {
168140 BlockHeaderChanges :: Connected ( indexed_header) => {
169141 let header = indexed_header. header ;
170- let hash: String = header. block_hash ( ) . to_string ( ) ;
171- let version: i32 = header. version . to_consensus ( ) ;
172- let prev_hash: String = header. prev_blockhash . as_raw_hash ( ) . to_string ( ) ;
173- let merkle_root: String = header. merkle_root . to_string ( ) ;
174- let time: u32 = header. time ;
175- let bits: u32 = header. bits . to_consensus ( ) ;
176- let nonce: u32 = header. nonce ;
177- let stmt = "INSERT OR REPLACE INTO headers (height, block_hash, version, prev_hash, merkle_root, time, bits, nonce) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)" ;
178- tx. execute (
179- stmt,
180- params ! [
181- indexed_header. height,
182- hash,
183- version,
184- prev_hash,
185- merkle_root,
186- time,
187- bits,
188- nonce
189- ] ,
190- ) ?;
142+ let hash: Vec < u8 > = consensus:: serialize ( & header. block_hash ( ) ) ;
143+ let header: Vec < u8 > = consensus:: serialize ( & indexed_header. header ) ;
144+ let stmt = "INSERT OR REPLACE INTO headers (height, block_hash, header) VALUES (?1, ?2, ?3)" ;
145+ tx. execute ( stmt, params ! [ indexed_header. height, hash, header] ) ?;
191146 }
192147 BlockHeaderChanges :: Reorganized {
193148 accepted,
194149 reorganized : _,
195150 } => {
196151 for indexed_header in accepted {
197152 let header = indexed_header. header ;
198- let hash: String = header. block_hash ( ) . to_string ( ) ;
199- let version: i32 = header. version . to_consensus ( ) ;
200- let prev_hash: String = header. prev_blockhash . as_raw_hash ( ) . to_string ( ) ;
201- let merkle_root: String = header. merkle_root . to_string ( ) ;
202- let time: u32 = header. time ;
203- let bits: u32 = header. bits . to_consensus ( ) ;
204- let nonce: u32 = header. nonce ;
205- let stmt = "INSERT OR REPLACE INTO headers (height, block_hash, version, prev_hash, merkle_root, time, bits, nonce) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)" ;
206- tx. execute (
207- stmt,
208- params ! [
209- indexed_header. height,
210- hash,
211- version,
212- prev_hash,
213- merkle_root,
214- time,
215- bits,
216- nonce
217- ] ,
218- ) ?;
153+ let hash: Vec < u8 > = consensus:: serialize ( & header. block_hash ( ) ) ;
154+ let header: Vec < u8 > = consensus:: serialize ( & indexed_header. header ) ;
155+ let stmt = "INSERT OR REPLACE INTO headers (height, block_hash, header) VALUES (?1, ?2, ?3)" ;
156+ tx. execute ( stmt, params ! [ indexed_header. height, hash, header] ) ?;
219157 }
220158 }
221159 }
@@ -230,20 +168,18 @@ impl SqliteHeaderDb {
230168 ) -> Result < Option < u32 > , SqlHeaderStoreError > {
231169 let write_lock = self . conn . lock ( ) . await ;
232170 let stmt = "SELECT height FROM headers WHERE block_hash = ?1" ;
233- let row : Option < u32 > =
234- write_lock. query_row ( stmt, params ! [ block_hash . to_string ( ) ] , |row| row. get ( 0 ) ) ?;
171+ let hash : Vec < u8 > = consensus :: serialize ( & block_hash ) ;
172+ let row : Option < u32 > = write_lock. query_row ( stmt, params ! [ hash ] , |row| row. get ( 0 ) ) ?;
235173 Ok ( row)
236174 }
237175
238176 async fn hash_at ( & mut self , height : u32 ) -> Result < Option < BlockHash > , SqlHeaderStoreError > {
239177 let write_lock = self . conn . lock ( ) . await ;
240178 let stmt = "SELECT block_hash FROM headers WHERE height = ?1" ;
241- let row: Option < String > = write_lock. query_row ( stmt, params ! [ height] , |row| row. get ( 0 ) ) ?;
179+ let row: Option < [ u8 ; 32 ] > =
180+ write_lock. query_row ( stmt, params ! [ height] , |row| row. get ( 0 ) ) ?;
242181 match row {
243- Some ( row) => match BlockHash :: from_str ( & row) {
244- Ok ( hash) => Ok ( Some ( hash) ) ,
245- Err ( _) => Err ( SqlHeaderStoreError :: StringConversion ) ,
246- } ,
182+ Some ( hash) => Ok ( Some ( consensus:: deserialize ( & hash) ?) ) ,
247183 None => Ok ( None ) ,
248184 }
249185 }
@@ -252,49 +188,9 @@ impl SqliteHeaderDb {
252188 let write_lock = self . conn . lock ( ) . await ;
253189 let stmt = "SELECT * FROM headers WHERE height = ?1" ;
254190 let query = write_lock. query_row ( stmt, params ! [ height] , |row| {
255- let hash: String = row. get ( 1 ) ?;
256- let version: i32 = row. get ( 2 ) ?;
257- let prev_hash: String = row. get ( 3 ) ?;
258- let merkle_root: String = row. get ( 4 ) ?;
259- let time: u32 = row. get ( 5 ) ?;
260- let bits: u32 = row. get ( 6 ) ?;
261- let nonce: u32 = row. get ( 7 ) ?;
262-
263- let header = Header {
264- version : Version :: from_consensus ( version) ,
265- prev_blockhash : BlockHash :: from_str ( & prev_hash) . map_err ( |e| {
266- rusqlite:: Error :: FromSqlConversionFailure (
267- 0 ,
268- rusqlite:: types:: Type :: Blob ,
269- Box :: new ( e) ,
270- )
271- } ) ?,
272- merkle_root : TxMerkleNode :: from_str ( & merkle_root) . map_err ( |e| {
273- rusqlite:: Error :: FromSqlConversionFailure (
274- 0 ,
275- rusqlite:: types:: Type :: Blob ,
276- Box :: new ( e) ,
277- )
278- } ) ?,
279- time,
280- bits : CompactTarget :: from_consensus ( bits) ,
281- nonce,
282- } ;
283-
284- if BlockHash :: from_str ( & hash)
285- . map_err ( |e| {
286- rusqlite:: Error :: FromSqlConversionFailure (
287- 0 ,
288- rusqlite:: types:: Type :: Blob ,
289- Box :: new ( e) ,
290- )
291- } ) ?
292- . ne ( & header. block_hash ( ) )
293- {
294- return Err ( rusqlite:: Error :: InvalidQuery ) ;
295- }
296-
297- Ok ( header)
191+ let header_slice: [ u8 ; 80 ] = row. get ( 2 ) ?;
192+ consensus:: deserialize ( & header_slice)
193+ . map_err ( |e| rusqlite:: Error :: ToSqlConversionFailure ( Box :: new ( e) ) )
298194 } ) ;
299195 match query {
300196 Ok ( header) => Ok ( Some ( header) ) ,
0 commit comments