// Copyright (C) 2024 Riften Labs AS // // This software is licensed under the GNU Affero General Public License (AGPL), version 3.0 or later. // A copy of the license can be found in the LICENSE file or at https://www.gnu.org/licenses/agpl-3.0.html use anyhow::{bail, Result}; use bitcoin_hashes::hex::ToHex; use bitcoincash::consensus::serialize; use bitcoincash::{consensus::deserialize, BlockHash, BlockHeader}; use rusqlite::{params, Connection}; use crate::chain::NewHeader; /// Load all headers we have stored in our database pub fn load_all_headers(conn: &Connection) -> Result> { let mut stmt = conn.prepare("SELECT header, height FROM headers")?; let headers_iter = stmt.query_map([], |row| { let data: Vec = row.get(0)?; let height: u64 = row.get(1)?; Ok((data, height)) })?; let mut headers = Vec::new(); for header in headers_iter { let (blob, height) = header?; headers.push(( deserialize(&blob) .unwrap_or_else(|_| panic!("Failed to deserialize header {}", height)), height, )); } Ok(headers) } pub fn db_get_header(conn: &Connection, blockhash: &BlockHash) -> Result { let mut stmt = conn.prepare("SELECT header FROM headers WHERE key = ?")?; let mut row = stmt.query([blockhash.to_hex()])?; let header: Option> = row.next()?.map(|r| r.get(0).expect("query header")); match header { Some(h) => { let header = deserialize(&h)?; Ok(header) } None => bail!("Header does not exist"), } } /// Store headers to database pub fn store_headers(conn: &Connection, headers: &[NewHeader]) -> Result<()> { let mut stmt = conn.prepare("INSERT OR IGNORE INTO headers (key, height, header) VALUES (?, ?, ?)")?; for h in headers { stmt.execute(params![h.hash.to_hex(), h.height, serialize(&h.header)])?; } Ok(()) }