2022-05-19 09:19:04 -07:00
|
|
|
use rusqlite::{params, Connection, OptionalExtension};
|
2021-07-09 22:44:13 -07:00
|
|
|
|
|
|
|
pub fn get_schema_version(connection: &Connection) -> anyhow::Result<u32> {
|
2021-07-16 01:42:29 -07:00
|
|
|
let version: Option<u32> = connection
|
|
|
|
.query_row(
|
|
|
|
"SELECT version FROM schema_version WHERE id = 1",
|
2022-05-19 09:19:04 -07:00
|
|
|
[],
|
2021-07-16 01:42:29 -07:00
|
|
|
|row| row.get(0),
|
|
|
|
)
|
|
|
|
.optional()?;
|
2021-07-09 22:44:13 -07:00
|
|
|
Ok(version.unwrap_or(0))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn update_schema_version(connection: &Connection, version: u32) -> anyhow::Result<()> {
|
2021-07-16 01:42:29 -07:00
|
|
|
connection.execute(
|
|
|
|
"INSERT INTO schema_version(id, version) VALUES (1, ?1) \
|
|
|
|
ON CONFLICT (id) DO UPDATE SET version = excluded.version",
|
|
|
|
params![version],
|
|
|
|
)?;
|
2021-07-09 22:44:13 -07:00
|
|
|
Ok(())
|
|
|
|
}
|
2021-08-09 07:13:10 -07:00
|
|
|
|
2021-11-26 19:34:26 -08:00
|
|
|
pub fn reset_db(connection: &Connection) -> anyhow::Result<()> {
|
|
|
|
// don't drop account data: accounts, taddrs, secret_shares
|
2022-05-19 09:19:04 -07:00
|
|
|
connection.execute("DROP TABLE blocks", [])?;
|
|
|
|
connection.execute("DROP TABLE transactions", [])?;
|
|
|
|
connection.execute("DROP TABLE received_notes", [])?;
|
|
|
|
connection.execute("DROP TABLE sapling_witnesses", [])?;
|
|
|
|
connection.execute("DROP TABLE diversifiers", [])?;
|
|
|
|
connection.execute("DROP TABLE historical_prices", [])?;
|
2022-06-08 05:48:16 -07:00
|
|
|
update_schema_version(connection, 0)?;
|
2021-11-26 19:34:26 -08:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2021-08-09 07:13:10 -07:00
|
|
|
pub fn init_db(connection: &Connection) -> anyhow::Result<()> {
|
|
|
|
connection.execute(
|
|
|
|
"CREATE TABLE IF NOT EXISTS schema_version (
|
|
|
|
id INTEGER PRIMARY KEY NOT NULL,
|
|
|
|
version INTEGER NOT NULL)",
|
2022-05-19 09:19:04 -07:00
|
|
|
[],
|
2021-08-09 07:13:10 -07:00
|
|
|
)?;
|
|
|
|
|
2022-06-08 05:48:16 -07:00
|
|
|
let version = get_schema_version(connection)?;
|
2021-08-09 07:13:10 -07:00
|
|
|
|
|
|
|
if version < 1 {
|
|
|
|
connection.execute(
|
|
|
|
"CREATE TABLE IF NOT EXISTS accounts (
|
|
|
|
id_account INTEGER PRIMARY KEY,
|
|
|
|
name TEXT NOT NULL,
|
|
|
|
seed TEXT,
|
2022-03-07 06:47:06 -08:00
|
|
|
aindex INTEGER NOT NULL,
|
2021-08-09 07:13:10 -07:00
|
|
|
sk TEXT,
|
|
|
|
ivk TEXT NOT NULL UNIQUE,
|
|
|
|
address TEXT NOT NULL)",
|
2022-05-19 09:19:04 -07:00
|
|
|
[],
|
2021-08-09 07:13:10 -07:00
|
|
|
)?;
|
|
|
|
|
|
|
|
connection.execute(
|
|
|
|
"CREATE TABLE IF NOT EXISTS blocks (
|
|
|
|
height INTEGER PRIMARY KEY,
|
|
|
|
hash BLOB NOT NULL,
|
|
|
|
timestamp INTEGER NOT NULL,
|
|
|
|
sapling_tree BLOB NOT NULL)",
|
2022-05-19 09:19:04 -07:00
|
|
|
[],
|
2021-08-09 07:13:10 -07:00
|
|
|
)?;
|
|
|
|
|
|
|
|
connection.execute(
|
|
|
|
"CREATE TABLE IF NOT EXISTS transactions (
|
|
|
|
id_tx INTEGER PRIMARY KEY,
|
|
|
|
account INTEGER NOT NULL,
|
|
|
|
txid BLOB NOT NULL,
|
|
|
|
height INTEGER NOT NULL,
|
|
|
|
timestamp INTEGER NOT NULL,
|
|
|
|
value INTEGER NOT NULL,
|
|
|
|
address TEXT,
|
|
|
|
memo TEXT,
|
|
|
|
tx_index INTEGER,
|
|
|
|
CONSTRAINT tx_account UNIQUE (height, tx_index, account))",
|
2022-05-19 09:19:04 -07:00
|
|
|
[],
|
2021-08-09 07:13:10 -07:00
|
|
|
)?;
|
|
|
|
|
|
|
|
connection.execute(
|
|
|
|
"CREATE TABLE IF NOT EXISTS received_notes (
|
|
|
|
id_note INTEGER PRIMARY KEY,
|
|
|
|
account INTEGER NOT NULL,
|
|
|
|
position INTEGER NOT NULL,
|
|
|
|
tx INTEGER NOT NULL,
|
|
|
|
height INTEGER NOT NULL,
|
|
|
|
output_index INTEGER NOT NULL,
|
|
|
|
diversifier BLOB NOT NULL,
|
|
|
|
value INTEGER NOT NULL,
|
|
|
|
rcm BLOB NOT NULL,
|
|
|
|
nf BLOB NOT NULL UNIQUE,
|
|
|
|
spent INTEGER,
|
2022-03-07 06:47:06 -08:00
|
|
|
excluded BOOL,
|
2021-08-09 07:13:10 -07:00
|
|
|
CONSTRAINT tx_output UNIQUE (tx, output_index))",
|
2022-05-19 09:19:04 -07:00
|
|
|
[],
|
2021-08-09 07:13:10 -07:00
|
|
|
)?;
|
|
|
|
|
|
|
|
connection.execute(
|
|
|
|
"CREATE TABLE IF NOT EXISTS sapling_witnesses (
|
|
|
|
id_witness INTEGER PRIMARY KEY,
|
|
|
|
note INTEGER NOT NULL,
|
|
|
|
height INTEGER NOT NULL,
|
|
|
|
witness BLOB NOT NULL,
|
|
|
|
CONSTRAINT witness_height UNIQUE (note, height))",
|
2022-05-19 09:19:04 -07:00
|
|
|
[],
|
2021-08-09 07:13:10 -07:00
|
|
|
)?;
|
|
|
|
|
|
|
|
connection.execute(
|
|
|
|
"CREATE TABLE IF NOT EXISTS diversifiers (
|
|
|
|
account INTEGER PRIMARY KEY NOT NULL,
|
|
|
|
diversifier_index BLOB NOT NULL)",
|
2022-05-19 09:19:04 -07:00
|
|
|
[],
|
2021-08-09 07:13:10 -07:00
|
|
|
)?;
|
|
|
|
|
|
|
|
connection.execute(
|
|
|
|
"CREATE TABLE IF NOT EXISTS taddrs (
|
|
|
|
account INTEGER PRIMARY KEY NOT NULL,
|
|
|
|
sk TEXT NOT NULL,
|
|
|
|
address TEXT NOT NULL)",
|
2022-05-19 09:19:04 -07:00
|
|
|
[],
|
2021-08-09 07:13:10 -07:00
|
|
|
)?;
|
|
|
|
|
|
|
|
connection.execute(
|
|
|
|
"CREATE TABLE IF NOT EXISTS historical_prices (
|
|
|
|
currency TEXT NOT NULL,
|
|
|
|
timestamp INTEGER NOT NULL,
|
|
|
|
price REAL NOT NULL,
|
|
|
|
PRIMARY KEY (currency, timestamp))",
|
2022-05-19 09:19:04 -07:00
|
|
|
[],
|
2021-08-09 07:13:10 -07:00
|
|
|
)?;
|
|
|
|
|
2021-09-08 07:10:22 -07:00
|
|
|
connection.execute(
|
|
|
|
"CREATE TABLE IF NOT EXISTS contacts (
|
|
|
|
id INTEGER PRIMARY KEY,
|
|
|
|
name TEXT NOT NULL,
|
|
|
|
address TEXT NOT NULL,
|
|
|
|
dirty BOOL NOT NULL)",
|
2022-05-19 09:19:04 -07:00
|
|
|
[],
|
2021-09-08 07:10:22 -07:00
|
|
|
)?;
|
2022-03-16 04:51:09 -07:00
|
|
|
}
|
2022-03-16 04:14:08 -07:00
|
|
|
|
2022-03-16 04:51:09 -07:00
|
|
|
if version < 2 {
|
2022-03-16 04:14:08 -07:00
|
|
|
connection.execute(
|
2022-06-07 09:58:24 -07:00
|
|
|
"CREATE INDEX i_received_notes ON received_notes(account)",
|
|
|
|
[],
|
|
|
|
)?;
|
|
|
|
connection.execute("CREATE INDEX i_account ON accounts(address)", [])?;
|
|
|
|
connection.execute("CREATE INDEX i_contact ON contacts(address)", [])?;
|
|
|
|
connection.execute("CREATE INDEX i_transaction ON transactions(account)", [])?;
|
|
|
|
connection.execute("CREATE INDEX i_witness ON sapling_witnesses(height)", [])?;
|
2021-09-08 07:10:22 -07:00
|
|
|
}
|
|
|
|
|
2022-04-15 23:23:50 -07:00
|
|
|
if version < 3 {
|
|
|
|
connection.execute(
|
|
|
|
"CREATE TABLE IF NOT EXISTS messages (
|
|
|
|
id INTEGER PRIMARY KEY,
|
|
|
|
account INTEGER NOT NULL,
|
|
|
|
sender TEXT,
|
|
|
|
recipient TEXT NOT NULL,
|
|
|
|
subject TEXT NOT NULL,
|
|
|
|
body TEXT NOT NULL,
|
|
|
|
timestamp INTEGER NOT NULL,
|
|
|
|
height INTEGER NOT NULL,
|
|
|
|
read BOOL NOT NULL)",
|
2022-05-19 09:19:04 -07:00
|
|
|
[],
|
2022-04-15 23:23:50 -07:00
|
|
|
)?;
|
2022-04-16 06:15:05 -07:00
|
|
|
// Don't index because it *really* slows down inserts
|
|
|
|
// connection.execute(
|
|
|
|
// "CREATE INDEX i_messages ON messages(account)",
|
2022-05-19 09:19:04 -07:00
|
|
|
// [],
|
2022-04-16 06:15:05 -07:00
|
|
|
// )?;
|
2022-04-15 23:23:50 -07:00
|
|
|
}
|
|
|
|
|
2022-09-05 08:05:55 -07:00
|
|
|
if version < 4 {
|
|
|
|
connection.execute("ALTER TABLE messages ADD id_tx INTEGER", [])?;
|
|
|
|
}
|
|
|
|
|
|
|
|
if version != 4 {
|
|
|
|
update_schema_version(connection, 4)?;
|
2022-05-13 02:50:52 -07:00
|
|
|
log::info!("Database migrated");
|
|
|
|
}
|
2021-08-09 07:13:10 -07:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|