61 lines
1.9 KiB
Rust
61 lines
1.9 KiB
Rust
|
|
// 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<Vec<(BlockHeader, u64)>> {
|
||
|
|
let mut stmt = conn.prepare("SELECT header, height FROM headers")?;
|
||
|
|
let headers_iter = stmt.query_map([], |row| {
|
||
|
|
let data: Vec<u8> = 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<BlockHeader> {
|
||
|
|
let mut stmt = conn.prepare("SELECT header FROM headers WHERE key = ?")?;
|
||
|
|
|
||
|
|
let mut row = stmt.query([blockhash.to_hex()])?;
|
||
|
|
let header: Option<Vec<u8>> = 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(())
|
||
|
|
}
|