Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade status #29

Merged
merged 2 commits into from
Nov 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions nomen/src/db/event_log.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use sqlx::SqlitePool;

pub async fn save(conn: &SqlitePool, evt_type: &str, evt_data: &str) -> anyhow::Result<()> {
sqlx::query("INSERT INTO event_log (created_at, type, data) VALUES (unixepoch(), ?, ?);")
.bind(evt_type)
.bind(evt_data)
.execute(conn)
.await?;
Ok(())
}

pub async fn last_index_time(conn: &SqlitePool) -> anyhow::Result<i64> {
let (created_at,) = sqlx::query_as::<_, (i64,)>(
"SELECT created_at FROM event_log WHERE type = 'index' ORDER BY created_at DESC LIMIT 1;",
)
.fetch_one(conn)
.await?;

Ok(created_at)
}
95 changes: 92 additions & 3 deletions nomen/src/db/index.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![allow(clippy::module_name_repetitions)]

use bitcoin::{BlockHash, Txid};
use nomen_core::Nsid;
use nomen_core::{Hash160, Nsid, NsidBuilder};
use secp256k1::XOnlyPublicKey;
use sqlx::{Executor, Sqlite, SqlitePool};

Expand Down Expand Up @@ -70,7 +70,7 @@ pub async fn next_index_height(conn: &SqlitePool) -> anyhow::Result<usize> {
Ok(h as usize)
}

pub async fn insert_index_height(
pub async fn insert_height(
conn: &SqlitePool,
height: i64,
blockhash: &BlockHash,
Expand All @@ -85,7 +85,7 @@ pub async fn insert_index_height(
Ok(())
}

pub async fn update_index_for_transfer(
pub async fn update_for_transfer(
conn: &sqlx::Pool<sqlx::Sqlite>,
nsid: Nsid,
new_owner: XOnlyPublicKey,
Expand All @@ -101,3 +101,92 @@ pub async fn update_index_for_transfer(
.await?;
Ok(())
}

pub enum UpgradeStatus {
Upgraded,
NotUpgraded,
}

pub async fn upgrade_v0_to_v1(
conn: impl sqlx::Executor<'_, Database = Sqlite> + Copy,
name: &str,
pubkey: XOnlyPublicKey,
blockheight: usize,
txid: Txid,
) -> anyhow::Result<UpgradeStatus> {
let fingerprint = hex::encode(
Hash160::default()
.chain_update(name.as_bytes())
.fingerprint(),
);
let nsid = hex::encode(NsidBuilder::new(name, &pubkey).finalize().as_ref());

let updated = sqlx::query(
"UPDATE blockchain_index
SET name = ?, pubkey = ?, protocol = 1, v1_upgrade_blockheight = ?, v1_upgrade_txid = ?
WHERE fingerprint = ? AND nsid = ? AND protocol = 0;",
)
.bind(name)
.bind(hex::encode(pubkey.serialize()))
.bind(blockheight as i64)
.bind(hex::encode(txid))
.bind(&fingerprint)
.bind(&nsid)
.execute(conn)
.await?;

if updated.rows_affected() > 0 {
return Ok(UpgradeStatus::Upgraded);
}

Ok(UpgradeStatus::NotUpgraded)
}

pub async fn update_v0_index(
conn: impl sqlx::Executor<'_, Database = Sqlite> + Copy,
name: &str,
pubkey: &XOnlyPublicKey,
nsid: Nsid,
) -> anyhow::Result<()> {
sqlx::query(
"UPDATE blockchain_index SET name = ?, pubkey = ? WHERE protocol = 0 AND nsid = ?;",
)
.bind(name)
.bind(pubkey.to_string())
.bind(hex::encode(nsid.as_slice()))
.execute(conn)
.await?;

Ok(())
}

pub async fn delete_from_transfer_cache(
conn: &sqlx::Pool<sqlx::Sqlite>,
id: i64,
) -> Result<(), anyhow::Error> {
tracing::debug!("DELETING transfer_cache with id {id}");
sqlx::query("DELETE FROM transfer_cache WHERE id = ?;")
.bind(id)
.execute(conn)
.await?;
Ok(())
}

pub async fn reindex(
conn: impl sqlx::Executor<'_, Database = Sqlite> + Copy,
blockheight: i64,
) -> anyhow::Result<()> {
sqlx::query("DELETE FROM blockchain_index WHERE blockheight >= ?;")
.bind(blockheight)
.execute(conn)
.await?;
sqlx::query("DELETE FROM transfer_cache WHERE blockheight >= ?;")
.bind(blockheight)
.execute(conn)
.await?;
sqlx::query("DELETE FROM old_transfer_cache WHERE blockheight >= ?;")
.bind(blockheight)
.execute(conn)
.await?;
Ok(())
}
187 changes: 10 additions & 177 deletions nomen/src/db/mod.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
use crate::config::Config;
pub use index::{
insert_blockchain_index, insert_index_height, insert_transfer_cache, next_index_height,
update_index_for_transfer, BlockchainIndex,
};
pub use name::{name_details, name_records, top_level_names, NameDetails, NameRecords};
use nomen_core::{Hash160, Name, Nsid, NsidBuilder};
use nostr_sdk::EventId;
pub use raw::{insert_raw_blockchain, RawBlockchain};
use secp256k1::XOnlyPublicKey;
use sqlx::{Sqlite, SqlitePool};

mod index;
mod name;
mod raw;
use sqlx::SqlitePool;

pub mod event_log;
pub mod index;
pub mod name;
pub mod raw;
pub mod relay_index;
pub mod stats;

static MIGRATIONS: [&str; 15] = [
static MIGRATIONS: [&str; 17] = [
"CREATE TABLE event_log (id INTEGER PRIMARY KEY, created_at, type, data);",
"CREATE TABLE index_height (blockheight INTEGER PRIMARY KEY, blockhash);",
"CREATE TABLE raw_blockchain (id INTEGER PRIMARY KEY, blockhash, txid, blocktime, blockheight, txheight, vout, data, indexed_at);",
Expand Down Expand Up @@ -50,7 +43,9 @@ static MIGRATIONS: [&str; 15] = [
"CREATE TABLE name_events (name, fingerprint, nsid, pubkey, created_at, event_id, records, indexed_at, raw_event);",
"CREATE UNIQUE INDEX name_events_unique_idx ON name_events(name, pubkey);",
"CREATE INDEX name_events_created_at_idx ON name_events(created_at);",
"CREATE TABLE relay_index_queue (name);"
"CREATE TABLE relay_index_queue (name);",
"ALTER TABLE blockchain_index ADD COLUMN v1_upgrade_blockheight;",
"ALTER TABLE blockchain_index ADD COLUMN v1_upgrade_txid",
];

pub async fn initialize(config: &Config) -> anyhow::Result<SqlitePool> {
Expand Down Expand Up @@ -79,165 +74,3 @@ pub async fn initialize(config: &Config) -> anyhow::Result<SqlitePool> {

Ok(conn)
}

pub async fn delete_from_transfer_cache(
conn: &sqlx::Pool<sqlx::Sqlite>,
id: i64,
) -> Result<(), anyhow::Error> {
tracing::debug!("DELETING transfer_cache with id {id}");
sqlx::query("DELETE FROM transfer_cache WHERE id = ?;")
.bind(id)
.execute(conn)
.await?;
Ok(())
}

pub async fn last_records_time(conn: &SqlitePool) -> anyhow::Result<u64> {
let (t,) = sqlx::query_as::<_, (i64,)>("SELECT COALESCE(MAX(created_at), 0) FROM name_events;")
.fetch_one(conn)
.await?;
Ok(t as u64)
}

#[allow(clippy::too_many_arguments)]
pub async fn insert_name_event(
conn: &SqlitePool,
name: Name,
fingerprint: [u8; 5],
nsid: Nsid,
pubkey: XOnlyPublicKey,
created_at: i64,
event_id: EventId,
records: String,
raw_event: String,
) -> anyhow::Result<()> {
sqlx::query(include_str!("./queries/insert_name_event.sql"))
.bind(name.to_string())
.bind(hex::encode(fingerprint))
.bind(nsid.to_string())
.bind(pubkey.to_string())
.bind(created_at)
.bind(event_id.to_string())
.bind(records)
.bind(raw_event)
.execute(conn)
.await?;
Ok(())
}

pub async fn save_event(conn: &SqlitePool, evt_type: &str, evt_data: &str) -> anyhow::Result<()> {
sqlx::query("INSERT INTO event_log (created_at, type, data) VALUES (unixepoch(), ?, ?);")
.bind(evt_type)
.bind(evt_data)
.execute(conn)
.await?;
Ok(())
}

pub async fn last_index_time(conn: &SqlitePool) -> anyhow::Result<i64> {
let (created_at,) = sqlx::query_as::<_, (i64,)>(
"SELECT created_at FROM event_log WHERE type = 'index' ORDER BY created_at DESC LIMIT 1;",
)
.fetch_one(conn)
.await?;

Ok(created_at)
}

pub type NameAndKey = (String, String);

pub async fn all_names(conn: &SqlitePool) -> anyhow::Result<Vec<NameAndKey>> {
let rows = sqlx::query_as::<_, NameAndKey>("SELECT name, pubkey FROM valid_names_vw;")
.fetch_all(conn)
.await?;
Ok(rows)
}

pub enum UpgradeStatus {
Upgraded,
NotUpgraded,
}

pub async fn upgrade_v0_to_v1(
conn: impl sqlx::Executor<'_, Database = Sqlite> + Copy,
name: &str,
pubkey: XOnlyPublicKey,
) -> anyhow::Result<UpgradeStatus> {
let fingerprint = hex::encode(
Hash160::default()
.chain_update(name.as_bytes())
.fingerprint(),
);
let nsid = hex::encode(NsidBuilder::new(name, &pubkey).finalize().as_ref());

let updated = sqlx::query(
"UPDATE blockchain_index SET name = ?, pubkey = ?, protocol = 1 WHERE fingerprint = ? AND nsid = ? AND protocol = 0;",
)
.bind(name)
.bind(hex::encode(pubkey.serialize()))
.bind(&fingerprint)
.bind(&nsid)
.execute(conn)
.await?;

if updated.rows_affected() > 0 {
return Ok(UpgradeStatus::Upgraded);
}

Ok(UpgradeStatus::NotUpgraded)
}

pub async fn check_name_availability(
conn: impl sqlx::Executor<'_, Database = Sqlite> + Copy,
name: &str,
) -> anyhow::Result<bool> {
let fp = hex::encode(
Hash160::default()
.chain_update(name.as_bytes())
.fingerprint(),
);
let (a,) = sqlx::query_as::<_, (bool,)>(
"SELECT COUNT(*) = 0 FROM valid_names_vw WHERE fingerprint = ?;",
)
.bind(&fp)
.fetch_one(conn)
.await?;
Ok(a)
}

pub async fn update_v0_index(
conn: impl sqlx::Executor<'_, Database = Sqlite> + Copy,
name: &str,
pubkey: &XOnlyPublicKey,
nsid: Nsid,
) -> anyhow::Result<()> {
sqlx::query(
"UPDATE blockchain_index SET name = ?, pubkey = ? WHERE protocol = 0 AND nsid = ?;",
)
.bind(name)
.bind(pubkey.to_string())
.bind(hex::encode(nsid.as_slice()))
.execute(conn)
.await?;

Ok(())
}

pub async fn reindex(
conn: impl sqlx::Executor<'_, Database = Sqlite> + Copy,
blockheight: i64,
) -> anyhow::Result<()> {
sqlx::query("DELETE FROM blockchain_index WHERE blockheight >= ?;")
.bind(blockheight)
.execute(conn)
.await?;
sqlx::query("DELETE FROM transfer_cache WHERE blockheight >= ?;")
.bind(blockheight)
.execute(conn)
.await?;
sqlx::query("DELETE FROM old_transfer_cache WHERE blockheight >= ?;")
.bind(blockheight)
.execute(conn)
.await?;
Ok(())
}
Loading